diff options
Diffstat (limited to 'lib/bc.lua')
-rw-r--r-- | lib/bc.lua | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/lib/bc.lua b/lib/bc.lua deleted file mode 100644 index 15317bcd..00000000 --- a/lib/bc.lua +++ /dev/null | |||
@@ -1,192 +0,0 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- LuaJIT bytecode listing module. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2012 Mike Pall. All rights reserved. | ||
5 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
6 | ---------------------------------------------------------------------------- | ||
7 | -- | ||
8 | -- This module lists the bytecode of a Lua function. If it's loaded by -jbc | ||
9 | -- it hooks into the parser and lists all functions of a chunk as they | ||
10 | -- are parsed. | ||
11 | -- | ||
12 | -- Example usage: | ||
13 | -- | ||
14 | -- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' | ||
15 | -- luajit -jbc=- foo.lua | ||
16 | -- luajit -jbc=foo.list foo.lua | ||
17 | -- | ||
18 | -- Default output is to stderr. To redirect the output to a file, pass a | ||
19 | -- filename as an argument (use '-' for stdout) or set the environment | ||
20 | -- variable LUAJIT_LISTFILE. The file is overwritten every time the module | ||
21 | -- is started. | ||
22 | -- | ||
23 | -- This module can also be used programmatically: | ||
24 | -- | ||
25 | -- local bc = require("jit.bc") | ||
26 | -- | ||
27 | -- local function foo() print("hello") end | ||
28 | -- | ||
29 | -- bc.dump(foo) --> -- BYTECODE -- [...] | ||
30 | -- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" | ||
31 | -- | ||
32 | -- local out = { | ||
33 | -- -- Do something with each line: | ||
34 | -- write = function(t, ...) io.write(...) end, | ||
35 | -- close = function(t) end, | ||
36 | -- flush = function(t) end, | ||
37 | -- } | ||
38 | -- bc.dump(foo, out) | ||
39 | -- | ||
40 | ------------------------------------------------------------------------------ | ||
41 | |||
42 | -- Cache some library functions and objects. | ||
43 | local jit = require("jit") | ||
44 | assert(jit.version_num == 20000, "LuaJIT core/library version mismatch") | ||
45 | local jutil = require("jit.util") | ||
46 | local vmdef = require("jit.vmdef") | ||
47 | local bit = require("bit") | ||
48 | local sub, gsub, format = string.sub, string.gsub, string.format | ||
49 | local byte, band, shr = string.byte, bit.band, bit.rshift | ||
50 | local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck | ||
51 | local funcuvname = jutil.funcuvname | ||
52 | local bcnames = vmdef.bcnames | ||
53 | local stdout, stderr = io.stdout, io.stderr | ||
54 | |||
55 | ------------------------------------------------------------------------------ | ||
56 | |||
57 | local function ctlsub(c) | ||
58 | if c == "\n" then return "\\n" | ||
59 | elseif c == "\r" then return "\\r" | ||
60 | elseif c == "\t" then return "\\t" | ||
61 | elseif c == "\r" then return "\\r" | ||
62 | else return format("\\%03d", byte(c)) | ||
63 | end | ||
64 | end | ||
65 | |||
66 | -- Return one bytecode line. | ||
67 | local function bcline(func, pc, prefix) | ||
68 | local ins, m = funcbc(func, pc) | ||
69 | if not ins then return end | ||
70 | local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) | ||
71 | local a = band(shr(ins, 8), 0xff) | ||
72 | local oidx = 6*band(ins, 0xff) | ||
73 | local op = sub(bcnames, oidx+1, oidx+6) | ||
74 | local s = format("%04d %s %-6s %3s ", | ||
75 | pc, prefix or " ", op, ma == 0 and "" or a) | ||
76 | local d = shr(ins, 16) | ||
77 | if mc == 13*128 then -- BCMjump | ||
78 | return format("%s=> %04d\n", s, pc+d-0x7fff) | ||
79 | end | ||
80 | if mb ~= 0 then | ||
81 | d = band(d, 0xff) | ||
82 | elseif mc == 0 then | ||
83 | return s.."\n" | ||
84 | end | ||
85 | local kc | ||
86 | if mc == 10*128 then -- BCMstr | ||
87 | kc = funck(func, -d-1) | ||
88 | kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) | ||
89 | elseif mc == 9*128 then -- BCMnum | ||
90 | kc = funck(func, d) | ||
91 | if op == "TSETM " then kc = kc - 2^52 end | ||
92 | elseif mc == 12*128 then -- BCMfunc | ||
93 | local fi = funcinfo(funck(func, -d-1)) | ||
94 | if fi.ffid then | ||
95 | kc = vmdef.ffnames[fi.ffid] | ||
96 | else | ||
97 | kc = fi.loc | ||
98 | end | ||
99 | elseif mc == 5*128 then -- BCMuv | ||
100 | kc = funcuvname(func, d) | ||
101 | end | ||
102 | if ma == 5 then -- BCMuv | ||
103 | local ka = funcuvname(func, a) | ||
104 | if kc then kc = ka.." ; "..kc else kc = ka end | ||
105 | end | ||
106 | if mb ~= 0 then | ||
107 | local b = shr(ins, 24) | ||
108 | if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end | ||
109 | return format("%s%3d %3d\n", s, b, d) | ||
110 | end | ||
111 | if kc then return format("%s%3d ; %s\n", s, d, kc) end | ||
112 | if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits | ||
113 | return format("%s%3d\n", s, d) | ||
114 | end | ||
115 | |||
116 | -- Collect branch targets of a function. | ||
117 | local function bctargets(func) | ||
118 | local target = {} | ||
119 | for pc=1,1000000000 do | ||
120 | local ins, m = funcbc(func, pc) | ||
121 | if not ins then break end | ||
122 | if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end | ||
123 | end | ||
124 | return target | ||
125 | end | ||
126 | |||
127 | -- Dump bytecode instructions of a function. | ||
128 | local function bcdump(func, out, all) | ||
129 | if not out then out = stdout end | ||
130 | local fi = funcinfo(func) | ||
131 | if all and fi.children then | ||
132 | for n=-1,-1000000000,-1 do | ||
133 | local k = funck(func, n) | ||
134 | if not k then break end | ||
135 | if type(k) == "proto" then bcdump(k, out, true) end | ||
136 | end | ||
137 | end | ||
138 | out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) | ||
139 | local target = bctargets(func) | ||
140 | for pc=1,1000000000 do | ||
141 | local s = bcline(func, pc, target[pc] and "=>") | ||
142 | if not s then break end | ||
143 | out:write(s) | ||
144 | end | ||
145 | out:write("\n") | ||
146 | out:flush() | ||
147 | end | ||
148 | |||
149 | ------------------------------------------------------------------------------ | ||
150 | |||
151 | -- Active flag and output file handle. | ||
152 | local active, out | ||
153 | |||
154 | -- List handler. | ||
155 | local function h_list(func) | ||
156 | return bcdump(func, out) | ||
157 | end | ||
158 | |||
159 | -- Detach list handler. | ||
160 | local function bclistoff() | ||
161 | if active then | ||
162 | active = false | ||
163 | jit.attach(h_list) | ||
164 | if out and out ~= stdout and out ~= stderr then out:close() end | ||
165 | out = nil | ||
166 | end | ||
167 | end | ||
168 | |||
169 | -- Open the output file and attach list handler. | ||
170 | local function bcliston(outfile) | ||
171 | if active then bclistoff() end | ||
172 | if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end | ||
173 | if outfile then | ||
174 | out = outfile == "-" and stdout or assert(io.open(outfile, "w")) | ||
175 | else | ||
176 | out = stderr | ||
177 | end | ||
178 | jit.attach(h_list, "bc") | ||
179 | active = true | ||
180 | end | ||
181 | |||
182 | -- Public module functions. | ||
183 | module(...) | ||
184 | |||
185 | line = bcline | ||
186 | dump = bcdump | ||
187 | targets = bctargets | ||
188 | |||
189 | on = bcliston | ||
190 | off = bclistoff | ||
191 | start = bcliston -- For -j command line option. | ||
192 | |||