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 | |||
