aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/LuaJIT-1.1.7/jit/dump.lua
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/LuaJIT-1.1.7/jit/dump.lua')
-rw-r--r--libraries/LuaJIT-1.1.7/jit/dump.lua265
1 files changed, 265 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/jit/dump.lua b/libraries/LuaJIT-1.1.7/jit/dump.lua
new file mode 100644
index 0000000..2287c23
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/jit/dump.lua
@@ -0,0 +1,265 @@
1----------------------------------------------------------------------------
2-- LuaJIT machine code dumper module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT/X license. See luajit.h for full copyright notice.
6----------------------------------------------------------------------------
7-- Activate this module to dump the machine code for all functions
8-- immediately after they have been compiled. The disassembler
9-- output is mixed with the bytecode listing.
10--
11-- Try: luajit -j dump -e 'print "foo"'
12-- luajit -j dump=foo.dump foo.lua
13-- luajit -j off -j dump -e 'jit.compile(assert(loadfile"foo.lua")))'
14--
15-- Default output is to stderr. To redirect output to a file,
16-- pass a filename as an argument or set the environment variable
17-- "LUAJIT_DUMPFILE".
18-- Note: The file is overwritten each time you run luajit.
19--
20-- TODO: Find a way to be more selective on what to dump.
21------------------------------------------------------------------------------
22
23-- Priority for compiler pipeline. Must run after backend (negative)
24-- and should be even because we only catch successful compiles.
25local PRIORITY = -98
26
27-- Cache some library functions and objects.
28local jit = require("jit")
29assert(jit.version_num == 10107, "LuaJIT core/library version mismatch")
30local jutil = require("jit.util")
31local type, format, gsub = type, string.format, string.gsub
32local bytecode, const = jutil.bytecode, jutil.const
33local getinfo = debug.getinfo
34local stdout, stderr = io.stdout, io.stderr
35
36-- Load the right disassembler.
37local dis = require("jit.dis_"..jit.arch)
38local discreate, disass_ = dis.create, dis.disass
39
40-- Turn compilation off for the whole module. LuaJIT would do that anyway.
41jit.off(true, true)
42
43-- Separator line.
44local sepline = "-------------------------------"
45
46-- Map JSUB indices to names.
47-- CHECK: must match the order in ljit_x86.h. Regenerate with:
48-- grep '^ *JSUB_[^_].*,' ljit_x86.h | sed -e 's/^ *JSUB_/ "/' -e 's/,.*/",/'
49local jsubnames = {
50 "STACKPTR",
51 "GATE_LJ",
52 "GATE_JL",
53 "GATE_JC",
54 "GROW_STACK",
55 "GROW_CI",
56 "GATE_JC_PATCH",
57 "GATE_JC_DEBUG",
58 "DEOPTIMIZE_CALLER",
59 "DEOPTIMIZE",
60 "DEOPTIMIZE_OPEN",
61 "HOOKINS",
62 "GCSTEP",
63 "STRING_SUB3",
64 "STRING_SUB2",
65 "HOOKCALL",
66 "HOOKRET",
67 "METACALL",
68 "METATAILCALL",
69 "BARRIERF",
70 "GETGLOBAL",
71 "GETTABLE_KSTR",
72 "GETTABLE_STR",
73 "BARRIERBACK",
74 "SETGLOBAL",
75 "SETTABLE_KSTR",
76 "SETTABLE_STR",
77 "GETTABLE_KNUM",
78 "GETTABLE_NUM",
79 "SETTABLE_KNUM",
80 "SETTABLE_NUM",
81 "LOG2_TWORD",
82 "CONCAT_STR2",
83}
84
85-- Generate map from JSUB addresses to JSUB names.
86local jsubmap = {}
87do
88 local jsubmcode = jutil.jsubmcode
89 for pc=0,100000 do
90 local addr = jsubmcode(pc)
91 if not addr then break end
92 jsubmap[addr] = jsubnames[pc+1] or "JSUB#"..pc
93 end
94end
95
96-- Pretty-print a constant.
97local function conststr(func, idx)
98 local k = const(func, idx)
99 if k == nil then return "nil"
100 elseif k == true then return "true"
101 elseif k == false then return "false"
102 elseif type(k) == "string" then
103 if #k > 10 then return format('"%.10s"~', k)
104 else return '"'..k..'"' end
105 else return k.."" end
106end
107
108-- Pretty-print a bytecode instruction (one or two lines).
109local function bytecodeout(out, func, pc)
110 local op, a, b, c = bytecode(func, pc)
111 if not op then
112 return true
113 elseif op == "JMP" then
114 out:write(format("\n--%04d-- JMP => %04d", pc, pc+1+b))
115 elseif op == "FORLOOP" or op == "FORPREP" then
116 out:write(format("\n--%04d-- %-9s %3d => %04d", pc, op, a, pc+1+b))
117 else
118 out:write(format("\n--%04d-- %-9s %3d %4s %4s",
119 pc, op, a, b or "", c or ""))
120 if b and b < 0 then out:write(" ; ", conststr(func, b)) end
121 if c and c < 0 then out:write(" ; ", conststr(func, c)) end
122 end
123end
124
125-- Dump machine code and mix it with the bytecode listing.
126local function dumpfunc(func, out, deopt)
127 if not out then out = stderr end
128 local info = getinfo(func, "S")
129
130 -- Don't bother checking for the right blocks to dump.
131 -- Dump the main block (if not deopt) and always all deopt blocks.
132 for block=deopt and 2 or 1,1000000 do
133 local addr, code, mfmiter = jutil.mcode(func, block)
134 if not addr then
135 if code then return code end -- Not compiled: return status.
136 break -- No more blocks to dump.
137 end
138
139 -- Print header.
140 out:write(sepline, " ", info.source, ":", info.linedefined)
141 if block ~= 1 then out:write(" DEOPT block ", block) end
142
143 -- Create disassembler context.
144 local ctx = discreate(code, addr, function(s) out:write(s) end)
145 ctx.symtab = jsubmap
146
147 -- Dump an mcode block.
148 local pc, ofs = 1, 0
149 local len, isdeopt = mfmiter()
150 if isdeopt then pc = len; len = 0
151 elseif block ~= 1 then break end -- Stop before next main block.
152 for t, m in mfmiter do
153 if t == "COMBINE" then
154 bytecodeout(out, func, pc)
155 else
156 if len ~= 0 then
157 out:write("\n")
158 if len > 0 then
159 ctx:disass(ofs, len)
160 ofs = ofs + len
161 else
162 out:write(format("%08x ** deoptimized\n", addr+ofs))
163 ofs = ofs - len
164 end
165 len = 0
166 end
167 if type(t) == "number" then
168 if m then
169 if isdeopt then
170 pc = t - 1
171 else
172 bytecodeout(out, func, pc)
173 len = -t
174 end
175 else
176 len = t
177 if bytecodeout(out, func, pc) then break end
178 end
179 end
180 end
181 pc = pc + 1
182 end
183 if len and len ~= 0 then
184 out:write(sepline, " tail code\n")
185 ctx:disass(ofs, len)
186 end
187 end
188
189 -- Print footer.
190 out:write(sepline, "\n")
191 out:flush()
192end
193
194-- Dump the internal JIT subroutines.
195local function dumpjsub_(out)
196 if not out then out = stderr end
197 local addr, code = jutil.jsubmcode()
198
199 -- Create disassembler context.
200 local ctx = discreate(code, addr, function(s) out:write(s) end)
201 ctx.symtab = jsubmap
202
203 -- Collect addresses and sort them.
204 local t = {}
205 for addr in pairs(jsubmap) do t[#t+1] = addr end
206 t[#t+1] = addr + #code
207 table.sort(t)
208
209 -- Go through the addresses in ascending order.
210 local ofs = addr
211 for i=2,#t do
212 local next = t[i]
213 out:write("\n->", jsubmap[ofs], ":\n") -- Output label for JSUB.
214 ctx:disass(ofs-addr, next-ofs) -- Disassemble corresponding code block.
215 ofs = next
216 end
217 out:flush()
218end
219
220
221-- Active flag and output file handle.
222local active, out
223
224-- Dump handler for compiler pipeline.
225local function h_dump(st)
226 local ok, err = pcall(dumpfunc, st.func, out, st.deopt)
227 if not ok then
228 stderr:write("\nERROR: jit.dump disabled: ", err, "\n")
229 jit.attach(h_dump) -- Better turn ourselves off after a failure.
230 if out and out ~= stdout then out:close() end
231 out = nil
232 active = nil
233 end
234end
235
236-- Detach dump handler from compiler pipeline.
237local function dumpoff()
238 if active then
239 active = false
240 jit.attach(h_dump)
241 if out and out ~= stdout then out:close() end
242 out = nil
243 end
244end
245
246-- Open the output file and attach dump handler to compiler pipeline.
247local function dumpon(filename)
248 if active then dumpoff() end
249 local outfile = filename or os.getenv("LUAJIT_DUMPFILE")
250 out = outfile and (outfile == "-" and stdout or assert(io.open(outfile, "w")))
251 jit.attach(h_dump, PRIORITY)
252 active = true
253end
254
255
256-- Public module functions.
257module(...)
258
259disass = disass_
260dump = dumpfunc
261dumpjsub = dumpjsub_
262on = dumpon
263off = dumpoff
264start = dumpon -- For -j command line option.
265