diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/LuaJIT-1.1.7/jit/dumphints.lua | 239 |
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. | ||
22 | local PRIORITY = 10 | ||
23 | |||
24 | -- Cache some library functions and objects. | ||
25 | local jit = require("jit") | ||
26 | assert(jit.version_num == 10107, "LuaJIT core/library version mismatch") | ||
27 | local jutil = require("jit.util") | ||
28 | local type, pairs, format = type, pairs, string.format | ||
29 | local bytecode, const = jutil.bytecode, jutil.const | ||
30 | local hints, fhints = jutil.hints, jutil.fhints | ||
31 | local stdout, stderr = io.stdout, io.stderr | ||
32 | |||
33 | -- Turn compilation off for the whole module. LuaJIT would do that anyway. | ||
34 | jit.off(true, true) | ||
35 | |||
36 | -- Separator line. | ||
37 | local sepline = "-------------------------------" | ||
38 | |||
39 | |||
40 | -- Pretty-print a constant. | ||
41 | local 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 | ||
50 | end | ||
51 | |||
52 | -- Pretty-print a bytecode instruction. | ||
53 | local 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 | ||
67 | end | ||
68 | |||
69 | -- Precompute inverse hints table. | ||
70 | local invhints = {} | ||
71 | for k,v in pairs(hints) do invhints[v] = k end | ||
72 | |||
73 | -- The inverse resolver for inline functions is loaded on demand. | ||
74 | local getname | ||
75 | |||
76 | -- Helper functions to pretty-print hints. | ||
77 | local 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..")" | ||
88 | end | ||
89 | |||
90 | local 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] [,...] | ||
103 | local 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 | ||
113 | end | ||
114 | |||
115 | -- Dump instructions and hints for a (to be compiled) function. | ||
116 | local 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() | ||
194 | end | ||
195 | |||
196 | |||
197 | -- Active flag and output file handle. | ||
198 | local active, out | ||
199 | |||
200 | -- Dump hints handler for compiler pipeline. | ||
201 | local 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 | ||
210 | end | ||
211 | |||
212 | -- Detach dump handler from compiler pipeline. | ||
213 | local 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 | ||
220 | end | ||
221 | |||
222 | -- Open the output file and attach dump handler to compiler pipeline. | ||
223 | local 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 | ||
229 | end | ||
230 | |||
231 | |||
232 | -- Public module functions. | ||
233 | module(...) | ||
234 | |||
235 | dump = dumphints | ||
236 | on = dumphintson | ||
237 | off = dumphintsoff | ||
238 | start = dumphintson -- For -j command line option. | ||
239 | |||