summaryrefslogtreecommitdiff
path: root/lib/bc.lua
diff options
context:
space:
mode:
authorMike Pall <mike>2009-12-08 19:46:35 +0100
committerMike Pall <mike>2009-12-08 19:46:35 +0100
commit55b16959717084884fd4a0cbae6d19e3786c20c7 (patch)
treec8a07a43c13679751ed25a9d06796e9e7b2134a6 /lib/bc.lua
downloadluajit-2.0.0-beta1.tar.gz
luajit-2.0.0-beta1.tar.bz2
luajit-2.0.0-beta1.zip
RELEASE LuaJIT-2.0.0-beta1v2.0.0-beta1
Diffstat (limited to 'lib/bc.lua')
-rw-r--r--lib/bc.lua182
1 files changed, 182 insertions, 0 deletions
diff --git a/lib/bc.lua b/lib/bc.lua
new file mode 100644
index 00000000..532f2493
--- /dev/null
+++ b/lib/bc.lua
@@ -0,0 +1,182 @@
1----------------------------------------------------------------------------
2-- LuaJIT bytecode listing module.
3--
4-- Copyright (C) 2005-2009 Mike Pall. All rights reserved.
5-- Released under the MIT/X 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 wich 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.
43local jit = require("jit")
44assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
45local jutil = require("jit.util")
46local vmdef = require("jit.vmdef")
47local bit = require("bit")
48local sub, gsub, format = string.sub, string.gsub, string.format
49local byte, band, shr = string.byte, bit.band, bit.rshift
50local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck
51local funcuvname = jutil.funcuvname
52local bcnames = vmdef.bcnames
53local stdout, stderr = io.stdout, io.stderr
54
55------------------------------------------------------------------------------
56
57local 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
64end
65
66-- Return one bytecode line.
67local 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 s = format("%04d %s %-6s %3s ",
74 pc, prefix or " ", sub(bcnames, oidx+1, oidx+6), ma == 0 and "" or a)
75 local d = shr(ins, 16)
76 if mc == 13*128 then -- BCMjump
77 if ma == 0 then
78 return format("%s=> %04d\n", sub(s, 1, -3), pc+d-0x7fff)
79 end
80 return format("%s=> %04d\n", s, pc+d-0x7fff)
81 end
82 if mb ~= 0 then d = band(d, 0xff) end
83 local kc
84 if mc == 10*128 then -- BCMstr
85 kc = funck(func, -d-1)
86 kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub))
87 elseif mc == 9*128 then -- BCMnum
88 kc = funck(func, d)
89 elseif mc == 12*128 then -- BCMfunc
90 local fi = funcinfo(funck(func, -d-1))
91 if fi.ffid then
92 kc = vmdef.ffnames[fi.ffid]
93 else
94 kc = fi.loc
95 end
96 elseif mc == 5*128 then -- BCMuv
97 kc = funcuvname(func, d)
98 end
99 if ma == 5 then -- BCMuv
100 local ka = funcuvname(func, a)
101 if kc then kc = ka.." ; "..kc else kc = ka end
102 end
103 if mb ~= 0 then
104 local b = shr(ins, 24)
105 if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end
106 return format("%s%3d %3d\n", s, b, d)
107 end
108 if kc then return format("%s%3d ; %s\n", s, d, kc) end
109 if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits
110 return format("%s%3d\n", s, d)
111end
112
113-- Collect branch targets of a function.
114local function bctargets(func)
115 local target = {}
116 for pc=1,1000000000 do
117 local ins, m = funcbc(func, pc)
118 if not ins then break end
119 if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end
120 end
121 return target
122end
123
124-- Dump bytecode instructions of a function.
125local function bcdump(func, out)
126 if not out then out = stdout end
127 local fi = funcinfo(func)
128 out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined))
129 local target = bctargets(func)
130 for pc=1,1000000000 do
131 local s = bcline(func, pc, target[pc] and "=>")
132 if not s then break end
133 out:write(s)
134 end
135 out:write("\n")
136 out:flush()
137end
138
139------------------------------------------------------------------------------
140
141-- Active flag and output file handle.
142local active, out
143
144-- List handler.
145local function h_list(func)
146 return bcdump(func, out)
147end
148
149-- Detach list handler.
150local function bclistoff()
151 if active then
152 active = false
153 jit.attach(h_list)
154 if out and out ~= stdout and out ~= stderr then out:close() end
155 out = nil
156 end
157end
158
159-- Open the output file and attach list handler.
160local function bcliston(outfile)
161 if active then bclistoff() end
162 if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end
163 if outfile then
164 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
165 else
166 out = stderr
167 end
168 jit.attach(h_list, "bc")
169 active = true
170end
171
172-- Public module functions.
173module(...)
174
175line = bcline
176dump = bcdump
177targets = bctargets
178
179on = bcliston
180off = bclistoff
181start = bcliston -- For -j command line option.
182