aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/LuaJIT-1.1.7/jit/dumphints.lua
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/LuaJIT-1.1.7/jit/dumphints.lua239
1 files changed, 239 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/jit/dumphints.lua b/libraries/LuaJIT-1.1.7/jit/dumphints.lua
new file mode 100644
index 0000000..4a64676
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/jit/dumphints.lua
@@ -0,0 +1,239 @@
1----------------------------------------------------------------------------
2-- LuaJIT hints 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 bytecode and the hints from
8-- the optimizer for all functions to be compiled.
9--
10-- Try: luajit -O -j dumphints -e 'return 1'
11--
12-- Default output is to stderr. To redirect output to a file,
13-- pass a filename as an argument or set the environment variable
14-- "LUAJIT_DUMPHINTSFILE".
15-- Note: The file is overwritten each time you run luajit.
16--
17-- TODO: Find a way to be more selective on what to dump.
18------------------------------------------------------------------------------
19
20-- Priority for compiler pipeline. Should run before backend (positive)
21-- and should be even because we only catch successful compiles.
22local PRIORITY = 10
23
24-- Cache some library functions and objects.
25local jit = require("jit")
26assert(jit.version_num == 10107, "LuaJIT core/library version mismatch")
27local jutil = require("jit.util")
28local type, pairs, format = type, pairs, string.format
29local bytecode, const = jutil.bytecode, jutil.const
30local hints, fhints = jutil.hints, jutil.fhints
31local stdout, stderr = io.stdout, io.stderr
32
33-- Turn compilation off for the whole module. LuaJIT would do that anyway.
34jit.off(true, true)
35
36-- Separator line.
37local sepline = "-------------------------------"
38
39
40-- Pretty-print a constant.
41local function conststr(func, idx)
42 local k = const(func, idx)
43 if k == nil then return "nil"
44 elseif k == true then return "true"
45 elseif k == false then return "false"
46 elseif type(k) == "string" then
47 if #k > 10 then return format('"%.10s"~', k)
48 else return '"'..k..'"' end
49 else return k.."" end
50end
51
52-- Pretty-print a bytecode instruction.
53local function bytecodeline(func, pc, flag)
54 local op, a, b, c = bytecode(func, pc)
55 if not op then return end
56 if op == "JMP" then
57 return format("\n%04d %s JMP => %04d", pc, flag, pc+1+b)
58 end
59 if op == "FORLOOP" or op == "FORPREP" then
60 return format("\n%04d %s %-9s %3d => %04d", pc, flag, op, a, pc+1+b)
61 end
62 local s = format("\n%04d %s %-9s %3d %4s %4s",
63 pc, flag, op, a, b or "", c or "")
64 if b and b < 0 then s = s.." ; "..conststr(func, b) end
65 if c and c < 0 then s = s.." ; "..conststr(func, c) end
66 return s
67end
68
69-- Precompute inverse hints table.
70local invhints = {}
71for k,v in pairs(hints) do invhints[v] = k end
72
73-- The inverse resolver for inline functions is loaded on demand.
74local getname
75
76-- Helper functions to pretty-print hints.
77local function typehint(h, v, st, pc)
78 if st[pc+hints.INLINE] then return "" end
79 local tp = type(v)
80 if tp == "function" then
81 tp = debug.getinfo(v, "S").what
82 elseif tp == "number" and v % 1 == 0 then
83 tp = "integer"
84 elseif v == false then
85 tp = "mixed"
86 end
87 return " #"..h.."("..tp..")"
88end
89
90local hintprint = {
91 COMBINE = function(h, v, st, pc)
92 if v == false then return "" end -- Dead instructions are already marked.
93 end,
94 TYPE = typehint,
95 TYPEKEY = typehint,
96 INLINE = function(h, v, st, pc)
97 if not getname then getname = require("jit.opt_inline").getname end
98 return " #INLINE("..getname(st[pc+hints.TYPE], v)..")"
99 end,
100}
101
102-- Generate range string from table: pc[-pc] [,...]
103local function rangestring(t)
104 local s = ""
105 for i,range in ipairs(t) do
106 if i ~= 1 then s = s.."," end
107 local pc = range % 65536
108 range = (range - pc) / 65536
109 s = s..pc
110 if range ~= 0 then s = s..(-(pc+range)) end
111 end
112 return s
113end
114
115-- Dump instructions and hints for a (to be compiled) function.
116local function dumphints(st, out)
117 if not out then out = stderr end
118 local func = st.func
119 local COMBINE = hints.COMBINE
120
121 -- Need to recompute branch targets (not part of hints).
122 local target = {}
123 for pc=1,1e6 do
124 local op, a, b, c = bytecode(func, pc)
125 if not op then break end
126 if op == "JMP" or op == "FORLOOP" then
127 local t = pc+1+b
128 if st[pc+COMBINE] ~= false then target[t] = true end
129 elseif op == "LOADBOOL" and c ~= 0 then
130 target[pc+2] = true
131 end
132 end
133
134 -- Map hints to bytecode instructions.
135 local hintstr = {}
136 for k,v in pairs(st) do
137 -- CHECK: must match hint shift in ljit_hints.h:JIT_H2NUM().
138 if type(k) == "number" and k >= 65536 then
139 local pc = k % 65536
140 if pc > 0 then
141 k = k - pc
142 local h = invhints[k] or (k/65536)
143 local hp = hintprint[h]
144 local s = hp and hp(h, v, st, pc) or (" #"..h)
145 local hs = hintstr[pc]
146 hintstr[pc] = hs and (hs..s) or s
147 end
148 end
149 end
150
151 -- Write header.
152 local info = debug.getinfo(func, "S")
153 out:write(sepline, " ", info.source, ":", info.linedefined)
154
155 -- Write function hints.
156 for k,v in pairs(fhints) do
157 if st[v] then out:write("\n#", k) end
158 end
159
160 -- Write instruction hints and bytecode.
161 local function dumprange(firstpc, lastpc)
162 for pc=firstpc,lastpc do
163 local prefix = " "
164 if st[pc+COMBINE] == false then prefix = "**"
165 elseif target[pc] then prefix = "=>" end
166 local line = bytecodeline(func, pc, prefix)
167 if not line then break end
168 local h = hintstr[pc]
169 if h then
170 out:write(format("%-40s %s", line, h))
171 else
172 out:write(line)
173 end
174 end
175 end
176
177 -- Handle deoptimization range table.
178 local t = st.deopt
179 if t then
180 out:write(" DEOPT=", rangestring(t))
181 for i,range in ipairs(t) do
182 if i ~= 1 then out:write("\n----") end
183 local pc = range % 65536
184 range = (range - pc) / 65536
185 dumprange(pc, pc+range)
186 end
187 else
188 dumprange(1, 1000000)
189 end
190
191 -- Write footer.
192 out:write("\n", sepline, "\n")
193 out:flush()
194end
195
196
197-- Active flag and output file handle.
198local active, out
199
200-- Dump hints handler for compiler pipeline.
201local function h_dumphints(st)
202 local ok, err = pcall(dumphints, st, out)
203 if not ok then
204 stderr:write("\nERROR: jit.dumphints disabled: ", err, "\n")
205 jit.attach(h_dumphints) -- Better turn ourselves off after a failure.
206 if out and out ~= stdout then out:close() end
207 out = nil
208 active = nil
209 end
210end
211
212-- Detach dump handler from compiler pipeline.
213local function dumphintsoff()
214 if active then
215 active = false
216 jit.attach(h_dumphints)
217 if out and out ~= stdout then out:close() end
218 out = nil
219 end
220end
221
222-- Open the output file and attach dump handler to compiler pipeline.
223local function dumphintson(filename)
224 if active then dumphintsoff() end
225 local outfile = filename or os.getenv("LUAJIT_DUMPHINTSFILE")
226 out = outfile and (outfile == "-" and stdout or assert(io.open(outfile, "w")))
227 jit.attach(h_dumphints, PRIORITY)
228 active = true
229end
230
231
232-- Public module functions.
233module(...)
234
235dump = dumphints
236on = dumphintson
237off = dumphintsoff
238start = dumphintson -- For -j command line option.
239