aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/lib/dump.lua
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/lib/dump.lua')
-rw-r--r--libraries/luajit-2.0/lib/dump.lua685
1 files changed, 0 insertions, 685 deletions
diff --git a/libraries/luajit-2.0/lib/dump.lua b/libraries/luajit-2.0/lib/dump.lua
deleted file mode 100644
index 0f0e905..0000000
--- a/libraries/luajit-2.0/lib/dump.lua
+++ /dev/null
@@ -1,685 +0,0 @@
1----------------------------------------------------------------------------
2-- LuaJIT compiler dump module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module can be used to debug the JIT compiler itself. It dumps the
9-- code representations and structures used in various compiler stages.
10--
11-- Example usage:
12--
13-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)"
14-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R
15-- luajit -jdump=is myapp.lua | less -R
16-- luajit -jdump=-b myapp.lua
17-- luajit -jdump=+aH,myapp.html myapp.lua
18-- luajit -jdump=ixT,myapp.dump myapp.lua
19--
20-- The first argument specifies the dump mode. The second argument gives
21-- the output file name. Default output is to stdout, unless the environment
22-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the
23-- module is started.
24--
25-- Different features can be turned on or off with the dump mode. If the
26-- mode starts with a '+', the following features are added to the default
27-- set of features; a '-' removes them. Otherwise the features are replaced.
28--
29-- The following dump features are available (* marks the default):
30--
31-- * t Print a line for each started, ended or aborted trace (see also -jv).
32-- * b Dump the traced bytecode.
33-- * i Dump the IR (intermediate representation).
34-- r Augment the IR with register/stack slots.
35-- s Dump the snapshot map.
36-- * m Dump the generated machine code.
37-- x Print each taken trace exit.
38-- X Print each taken trace exit and the contents of all registers.
39--
40-- The output format can be set with the following characters:
41--
42-- T Plain text output.
43-- A ANSI-colored text output
44-- H Colorized HTML + CSS output.
45--
46-- The default output format is plain text. It's set to ANSI-colored text
47-- if the COLORTERM variable is set. Note: this is independent of any output
48-- redirection, which is actually considered a feature.
49--
50-- You probably want to use less -R to enjoy viewing ANSI-colored text from
51-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R"
52--
53------------------------------------------------------------------------------
54
55-- Cache some library functions and objects.
56local jit = require("jit")
57assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
58local jutil = require("jit.util")
59local vmdef = require("jit.vmdef")
60local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
61local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek
62local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap
63local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr
64local bit = require("bit")
65local band, shl, shr = bit.band, bit.lshift, bit.rshift
66local sub, gsub, format = string.sub, string.gsub, string.format
67local byte, char, rep = string.byte, string.char, string.rep
68local type, tostring = type, tostring
69local stdout, stderr = io.stdout, io.stderr
70
71-- Load other modules on-demand.
72local bcline, disass
73
74-- Active flag, output file handle and dump mode.
75local active, out, dumpmode
76
77------------------------------------------------------------------------------
78
79local symtabmt = { __index = false }
80local symtab = {}
81local nexitsym = 0
82
83-- Fill nested symbol table with per-trace exit stub addresses.
84local function fillsymtab_tr(tr, nexit)
85 local t = {}
86 symtabmt.__index = t
87 for i=0,nexit-1 do
88 local addr = traceexitstub(tr, i)
89 t[addr] = tostring(i)
90 end
91 local addr = traceexitstub(tr, nexit)
92 if addr then t[addr] = "stack_check" end
93end
94
95-- Fill symbol table with trace exit stub addresses.
96local function fillsymtab(tr, nexit)
97 local t = symtab
98 if nexitsym == 0 then
99 local ircall = vmdef.ircall
100 for i=0,#ircall do
101 local addr = ircalladdr(i)
102 if addr ~= 0 then t[addr] = ircall[i] end
103 end
104 end
105 if nexitsym == 1000000 then -- Per-trace exit stubs.
106 fillsymtab_tr(tr, nexit)
107 elseif nexit > nexitsym then -- Shared exit stubs.
108 for i=nexitsym,nexit-1 do
109 local addr = traceexitstub(i)
110 if addr == nil then -- Fall back to per-trace exit stubs.
111 fillsymtab_tr(tr, nexit)
112 setmetatable(symtab, symtabmt)
113 nexit = 1000000
114 break
115 end
116 t[addr] = tostring(i)
117 end
118 nexitsym = nexit
119 end
120 return t
121end
122
123local function dumpwrite(s)
124 out:write(s)
125end
126
127-- Disassemble machine code.
128local function dump_mcode(tr)
129 local info = traceinfo(tr)
130 if not info then return end
131 local mcode, addr, loop = tracemc(tr)
132 if not mcode then return end
133 if not disass then disass = require("jit.dis_"..jit.arch) end
134 out:write("---- TRACE ", tr, " mcode ", #mcode, "\n")
135 local ctx = disass.create(mcode, addr, dumpwrite)
136 ctx.hexdump = 0
137 ctx.symtab = fillsymtab(tr, info.nexit)
138 if loop ~= 0 then
139 symtab[addr+loop] = "LOOP"
140 ctx:disass(0, loop)
141 out:write("->LOOP:\n")
142 ctx:disass(loop, #mcode-loop)
143 symtab[addr+loop] = nil
144 else
145 ctx:disass(0, #mcode)
146 end
147end
148
149------------------------------------------------------------------------------
150
151local irtype_text = {
152 [0] = "nil",
153 "fal",
154 "tru",
155 "lud",
156 "str",
157 "p32",
158 "thr",
159 "pro",
160 "fun",
161 "p64",
162 "cdt",
163 "tab",
164 "udt",
165 "flt",
166 "num",
167 "i8 ",
168 "u8 ",
169 "i16",
170 "u16",
171 "int",
172 "u32",
173 "i64",
174 "u64",
175 "sfp",
176}
177
178local colortype_ansi = {
179 [0] = "%s",
180 "%s",
181 "%s",
182 "\027[36m%s\027[m",
183 "\027[32m%s\027[m",
184 "%s",
185 "\027[1m%s\027[m",
186 "%s",
187 "\027[1m%s\027[m",
188 "%s",
189 "\027[33m%s\027[m",
190 "\027[31m%s\027[m",
191 "\027[36m%s\027[m",
192 "\027[34m%s\027[m",
193 "\027[34m%s\027[m",
194 "\027[35m%s\027[m",
195 "\027[35m%s\027[m",
196 "\027[35m%s\027[m",
197 "\027[35m%s\027[m",
198 "\027[35m%s\027[m",
199 "\027[35m%s\027[m",
200 "\027[35m%s\027[m",
201 "\027[35m%s\027[m",
202 "\027[35m%s\027[m",
203}
204
205local function colorize_text(s, t)
206 return s
207end
208
209local function colorize_ansi(s, t)
210 return format(colortype_ansi[t], s)
211end
212
213local irtype_ansi = setmetatable({},
214 { __index = function(tab, t)
215 local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end })
216
217local html_escape = { ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;", }
218
219local function colorize_html(s, t)
220 s = gsub(s, "[<>&]", html_escape)
221 return format('<span class="irt_%s">%s</span>', irtype_text[t], s)
222end
223
224local irtype_html = setmetatable({},
225 { __index = function(tab, t)
226 local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end })
227
228local header_html = [[
229<style type="text/css">
230background { background: #ffffff; color: #000000; }
231pre.ljdump {
232font-size: 10pt;
233background: #f0f4ff;
234color: #000000;
235border: 1px solid #bfcfff;
236padding: 0.5em;
237margin-left: 2em;
238margin-right: 2em;
239}
240span.irt_str { color: #00a000; }
241span.irt_thr, span.irt_fun { color: #404040; font-weight: bold; }
242span.irt_tab { color: #c00000; }
243span.irt_udt, span.irt_lud { color: #00c0c0; }
244span.irt_num { color: #4040c0; }
245span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; }
246</style>
247]]
248
249local colorize, irtype
250
251-- Lookup tables to convert some literals into names.
252local litname = {
253 ["SLOAD "] = setmetatable({}, { __index = function(t, mode)
254 local s = ""
255 if band(mode, 1) ~= 0 then s = s.."P" end
256 if band(mode, 2) ~= 0 then s = s.."F" end
257 if band(mode, 4) ~= 0 then s = s.."T" end
258 if band(mode, 8) ~= 0 then s = s.."C" end
259 if band(mode, 16) ~= 0 then s = s.."R" end
260 if band(mode, 32) ~= 0 then s = s.."I" end
261 t[mode] = s
262 return s
263 end}),
264 ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", },
265 ["CONV "] = setmetatable({}, { __index = function(t, mode)
266 local s = irtype[band(mode, 31)]
267 s = irtype[band(shr(mode, 5), 31)].."."..s
268 if band(mode, 0x400) ~= 0 then s = s.." trunc"
269 elseif band(mode, 0x800) ~= 0 then s = s.." sext" end
270 local c = shr(mode, 14)
271 if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
272 t[mode] = s
273 return s
274 end}),
275 ["FLOAD "] = vmdef.irfield,
276 ["FREF "] = vmdef.irfield,
277 ["FPMATH"] = vmdef.irfpm,
278}
279
280local function ctlsub(c)
281 if c == "\n" then return "\\n"
282 elseif c == "\r" then return "\\r"
283 elseif c == "\t" then return "\\t"
284 elseif c == "\r" then return "\\r"
285 else return format("\\%03d", byte(c))
286 end
287end
288
289local function fmtfunc(func, pc)
290 local fi = funcinfo(func, pc)
291 if fi.loc then
292 return fi.loc
293 elseif fi.ffid then
294 return vmdef.ffnames[fi.ffid]
295 elseif fi.addr then
296 return format("C:%x", fi.addr)
297 else
298 return "(?)"
299 end
300end
301
302local function formatk(tr, idx)
303 local k, t, slot = tracek(tr, idx)
304 local tn = type(k)
305 local s
306 if tn == "number" then
307 if k == 2^52+2^51 then
308 s = "bias"
309 else
310 s = format("%+.14g", k)
311 end
312 elseif tn == "string" then
313 s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub))
314 elseif tn == "function" then
315 s = fmtfunc(k)
316 elseif tn == "table" then
317 s = format("{%p}", k)
318 elseif tn == "userdata" then
319 if t == 12 then
320 s = format("userdata:%p", k)
321 else
322 s = format("[%p]", k)
323 if s == "[0x00000000]" then s = "NULL" end
324 end
325 elseif t == 21 then -- int64_t
326 s = sub(tostring(k), 1, -3)
327 if sub(s, 1, 1) ~= "-" then s = "+"..s end
328 else
329 s = tostring(k) -- For primitives.
330 end
331 s = colorize(format("%-4s", s), t)
332 if slot then
333 s = format("%s @%d", s, slot)
334 end
335 return s
336end
337
338local function printsnap(tr, snap)
339 local n = 2
340 for s=0,snap[1]-1 do
341 local sn = snap[n]
342 if shr(sn, 24) == s then
343 n = n + 1
344 local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS
345 if ref < 0 then
346 out:write(formatk(tr, ref))
347 elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM
348 out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
349 else
350 local m, ot, op1, op2 = traceir(tr, ref)
351 out:write(colorize(format("%04d", ref), band(ot, 31)))
352 end
353 out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME
354 else
355 out:write("---- ")
356 end
357 end
358 out:write("]\n")
359end
360
361-- Dump snapshots (not interleaved with IR).
362local function dump_snap(tr)
363 out:write("---- TRACE ", tr, " snapshots\n")
364 for i=0,1000000000 do
365 local snap = tracesnap(tr, i)
366 if not snap then break end
367 out:write(format("#%-3d %04d [ ", i, snap[0]))
368 printsnap(tr, snap)
369 end
370end
371
372-- Return a register name or stack slot for a rid/sp location.
373local function ridsp_name(ridsp)
374 if not disass then disass = require("jit.dis_"..jit.arch) end
375 local rid = band(ridsp, 0xff)
376 if ridsp > 255 then return format("[%x]", shr(ridsp, 8)*4) end
377 if rid < 128 then return disass.regname(rid) end
378 return ""
379end
380
381-- Dump CALL* function ref and return optional ctype.
382local function dumpcallfunc(tr, ins)
383 local ctype
384 if ins > 0 then
385 local m, ot, op1, op2 = traceir(tr, ins)
386 if band(ot, 31) == 0 then -- nil type means CARG(func, ctype).
387 ins = op1
388 ctype = formatk(tr, op2)
389 end
390 end
391 if ins < 0 then
392 out:write(format("[0x%x](", tonumber((tracek(tr, ins)))))
393 else
394 out:write(format("%04d (", ins))
395 end
396 return ctype
397end
398
399-- Recursively gather CALL* args and dump them.
400local function dumpcallargs(tr, ins)
401 if ins < 0 then
402 out:write(formatk(tr, ins))
403 else
404 local m, ot, op1, op2 = traceir(tr, ins)
405 local oidx = 6*shr(ot, 8)
406 local op = sub(vmdef.irnames, oidx+1, oidx+6)
407 if op == "CARG " then
408 dumpcallargs(tr, op1)
409 if op2 < 0 then
410 out:write(" ", formatk(tr, op2))
411 else
412 out:write(" ", format("%04d", op2))
413 end
414 else
415 out:write(format("%04d", ins))
416 end
417 end
418end
419
420-- Dump IR and interleaved snapshots.
421local function dump_ir(tr, dumpsnap, dumpreg)
422 local info = traceinfo(tr)
423 if not info then return end
424 local nins = info.nins
425 out:write("---- TRACE ", tr, " IR\n")
426 local irnames = vmdef.irnames
427 local snapref = 65536
428 local snap, snapno
429 if dumpsnap then
430 snap = tracesnap(tr, 0)
431 snapref = snap[0]
432 snapno = 0
433 end
434 for ins=1,nins do
435 if ins >= snapref then
436 if dumpreg then
437 out:write(format(".... SNAP #%-3d [ ", snapno))
438 else
439 out:write(format(".... SNAP #%-3d [ ", snapno))
440 end
441 printsnap(tr, snap)
442 snapno = snapno + 1
443 snap = tracesnap(tr, snapno)
444 snapref = snap and snap[0] or 65536
445 end
446 local m, ot, op1, op2, ridsp = traceir(tr, ins)
447 local oidx, t = 6*shr(ot, 8), band(ot, 31)
448 local op = sub(irnames, oidx+1, oidx+6)
449 if op == "LOOP " then
450 if dumpreg then
451 out:write(format("%04d ------------ LOOP ------------\n", ins))
452 else
453 out:write(format("%04d ------ LOOP ------------\n", ins))
454 end
455 elseif op ~= "NOP " and op ~= "CARG " and
456 (dumpreg or op ~= "RENAME") then
457 if dumpreg then
458 out:write(format("%04d %-5s ", ins, ridsp_name(ridsp)))
459 else
460 out:write(format("%04d ", ins))
461 end
462 out:write(format("%s%s %s %s ",
463 band(ot, 128) == 0 and " " or ">",
464 band(ot, 64) == 0 and " " or "+",
465 irtype[t], op))
466 local m1, m2 = band(m, 3), band(m, 3*4)
467 if sub(op, 1, 4) == "CALL" then
468 local ctype
469 if m2 == 1*4 then -- op2 == IRMlit
470 out:write(format("%-10s (", vmdef.ircall[op2]))
471 else
472 ctype = dumpcallfunc(tr, op2)
473 end
474 if op1 ~= -1 then dumpcallargs(tr, op1) end
475 out:write(")")
476 if ctype then out:write(" ctype ", ctype) end
477 elseif op == "CNEW " and op2 == -1 then
478 out:write(formatk(tr, op1))
479 elseif m1 ~= 3 then -- op1 != IRMnone
480 if op1 < 0 then
481 out:write(formatk(tr, op1))
482 else
483 out:write(format(m1 == 0 and "%04d" or "#%-3d", op1))
484 end
485 if m2 ~= 3*4 then -- op2 != IRMnone
486 if m2 == 1*4 then -- op2 == IRMlit
487 local litn = litname[op]
488 if litn and litn[op2] then
489 out:write(" ", litn[op2])
490 elseif op == "UREFO " or op == "UREFC " then
491 out:write(format(" #%-3d", shr(op2, 8)))
492 else
493 out:write(format(" #%-3d", op2))
494 end
495 elseif op2 < 0 then
496 out:write(" ", formatk(tr, op2))
497 else
498 out:write(format(" %04d", op2))
499 end
500 end
501 end
502 out:write("\n")
503 end
504 end
505 if snap then
506 if dumpreg then
507 out:write(format(".... SNAP #%-3d [ ", snapno))
508 else
509 out:write(format(".... SNAP #%-3d [ ", snapno))
510 end
511 printsnap(tr, snap)
512 end
513end
514
515------------------------------------------------------------------------------
516
517local recprefix = ""
518local recdepth = 0
519
520-- Format trace error message.
521local function fmterr(err, info)
522 if type(err) == "number" then
523 if type(info) == "function" then info = fmtfunc(info) end
524 err = format(vmdef.traceerr[err], info)
525 end
526 return err
527end
528
529-- Dump trace states.
530local function dump_trace(what, tr, func, pc, otr, oex)
531 if what == "stop" or (what == "abort" and dumpmode.a) then
532 if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop")
533 elseif dumpmode.s then dump_snap(tr) end
534 if dumpmode.m then dump_mcode(tr) end
535 end
536 if what == "start" then
537 if dumpmode.H then out:write('<pre class="ljdump">\n') end
538 out:write("---- TRACE ", tr, " ", what)
539 if otr then out:write(" ", otr, "/", oex) end
540 out:write(" ", fmtfunc(func, pc), "\n")
541 recprefix = ""
542 elseif what == "stop" or what == "abort" then
543 out:write("---- TRACE ", tr, " ", what)
544 recprefix = nil
545 if what == "abort" then
546 out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
547 else
548 local info = traceinfo(tr)
549 local link, ltype = info.link, info.linktype
550 if link == tr or link == 0 then
551 out:write(" -> ", ltype, "\n")
552 elseif ltype == "root" then
553 out:write(" -> ", link, "\n")
554 else
555 out:write(" -> ", link, " ", ltype, "\n")
556 end
557 end
558 if dumpmode.H then out:write("</pre>\n\n") else out:write("\n") end
559 else
560 out:write("---- TRACE ", what, "\n\n")
561 end
562 out:flush()
563end
564
565-- Dump recorded bytecode.
566local function dump_record(tr, func, pc, depth, callee)
567 if depth ~= recdepth then
568 recdepth = depth
569 recprefix = rep(" .", depth)
570 end
571 local line
572 if pc >= 0 then
573 line = bcline(func, pc, recprefix)
574 if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
575 else
576 line = "0000 "..recprefix.." FUNCC \n"
577 callee = func
578 end
579 if pc <= 0 then
580 out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
581 else
582 out:write(line)
583 end
584 if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC
585 out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond.
586 end
587end
588
589------------------------------------------------------------------------------
590
591-- Dump taken trace exits.
592local function dump_texit(tr, ex, ngpr, nfpr, ...)
593 out:write("---- TRACE ", tr, " exit ", ex, "\n")
594 if dumpmode.X then
595 local regs = {...}
596 if jit.arch == "x64" then
597 for i=1,ngpr do
598 out:write(format(" %016x", regs[i]))
599 if i % 4 == 0 then out:write("\n") end
600 end
601 else
602 for i=1,ngpr do
603 out:write(format(" %08x", regs[i]))
604 if i % 8 == 0 then out:write("\n") end
605 end
606 end
607 for i=1,nfpr do
608 out:write(format(" %+17.14g", regs[ngpr+i]))
609 if i % 4 == 0 then out:write("\n") end
610 end
611 end
612end
613
614------------------------------------------------------------------------------
615
616-- Detach dump handlers.
617local function dumpoff()
618 if active then
619 active = false
620 jit.attach(dump_texit)
621 jit.attach(dump_record)
622 jit.attach(dump_trace)
623 if out and out ~= stdout and out ~= stderr then out:close() end
624 out = nil
625 end
626end
627
628-- Open the output file and attach dump handlers.
629local function dumpon(opt, outfile)
630 if active then dumpoff() end
631
632 local colormode = os.getenv("COLORTERM") and "A" or "T"
633 if opt then
634 opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end)
635 end
636
637 local m = { t=true, b=true, i=true, m=true, }
638 if opt and opt ~= "" then
639 local o = sub(opt, 1, 1)
640 if o ~= "+" and o ~= "-" then m = {} end
641 for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end
642 end
643 dumpmode = m
644
645 if m.t or m.b or m.i or m.s or m.m then
646 jit.attach(dump_trace, "trace")
647 end
648 if m.b then
649 jit.attach(dump_record, "record")
650 if not bcline then bcline = require("jit.bc").line end
651 end
652 if m.x or m.X then
653 jit.attach(dump_texit, "texit")
654 end
655
656 if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end
657 if outfile then
658 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
659 else
660 out = stdout
661 end
662
663 m[colormode] = true
664 if colormode == "A" then
665 colorize = colorize_ansi
666 irtype = irtype_ansi
667 elseif colormode == "H" then
668 colorize = colorize_html
669 irtype = irtype_html
670 out:write(header_html)
671 else
672 colorize = colorize_text
673 irtype = irtype_text
674 end
675
676 active = true
677end
678
679-- Public module functions.
680module(...)
681
682on = dumpon
683off = dumpoff
684start = dumpon -- For -j command line option.
685