comparison third_party/luajit/src/jit/dump.lua @ 186:8cf4ec5e2191 hg-web

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