From 6523585c66c04cea54df50013df8886b589847d8 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 23 Jan 2012 23:36:30 +1000 Subject: Add luaproc and LuaJIT libraries. Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly. --- libraries/LuaJIT-1.1.7/jit/dump.lua | 265 ++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 libraries/LuaJIT-1.1.7/jit/dump.lua (limited to 'libraries/LuaJIT-1.1.7/jit/dump.lua') diff --git a/libraries/LuaJIT-1.1.7/jit/dump.lua b/libraries/LuaJIT-1.1.7/jit/dump.lua new file mode 100644 index 0000000..2287c23 --- /dev/null +++ b/libraries/LuaJIT-1.1.7/jit/dump.lua @@ -0,0 +1,265 @@ +---------------------------------------------------------------------------- +-- LuaJIT machine code dumper module. +-- +-- Copyright (C) 2005-2011 Mike Pall. All rights reserved. +-- Released under the MIT/X license. See luajit.h for full copyright notice. +---------------------------------------------------------------------------- +-- Activate this module to dump the machine code for all functions +-- immediately after they have been compiled. The disassembler +-- output is mixed with the bytecode listing. +-- +-- Try: luajit -j dump -e 'print "foo"' +-- luajit -j dump=foo.dump foo.lua +-- luajit -j off -j dump -e 'jit.compile(assert(loadfile"foo.lua")))' +-- +-- Default output is to stderr. To redirect output to a file, +-- pass a filename as an argument or set the environment variable +-- "LUAJIT_DUMPFILE". +-- Note: The file is overwritten each time you run luajit. +-- +-- TODO: Find a way to be more selective on what to dump. +------------------------------------------------------------------------------ + +-- Priority for compiler pipeline. Must run after backend (negative) +-- and should be even because we only catch successful compiles. +local PRIORITY = -98 + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 10107, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local type, format, gsub = type, string.format, string.gsub +local bytecode, const = jutil.bytecode, jutil.const +local getinfo = debug.getinfo +local stdout, stderr = io.stdout, io.stderr + +-- Load the right disassembler. +local dis = require("jit.dis_"..jit.arch) +local discreate, disass_ = dis.create, dis.disass + +-- Turn compilation off for the whole module. LuaJIT would do that anyway. +jit.off(true, true) + +-- Separator line. +local sepline = "-------------------------------" + +-- Map JSUB indices to names. +-- CHECK: must match the order in ljit_x86.h. Regenerate with: +-- grep '^ *JSUB_[^_].*,' ljit_x86.h | sed -e 's/^ *JSUB_/ "/' -e 's/,.*/",/' +local jsubnames = { + "STACKPTR", + "GATE_LJ", + "GATE_JL", + "GATE_JC", + "GROW_STACK", + "GROW_CI", + "GATE_JC_PATCH", + "GATE_JC_DEBUG", + "DEOPTIMIZE_CALLER", + "DEOPTIMIZE", + "DEOPTIMIZE_OPEN", + "HOOKINS", + "GCSTEP", + "STRING_SUB3", + "STRING_SUB2", + "HOOKCALL", + "HOOKRET", + "METACALL", + "METATAILCALL", + "BARRIERF", + "GETGLOBAL", + "GETTABLE_KSTR", + "GETTABLE_STR", + "BARRIERBACK", + "SETGLOBAL", + "SETTABLE_KSTR", + "SETTABLE_STR", + "GETTABLE_KNUM", + "GETTABLE_NUM", + "SETTABLE_KNUM", + "SETTABLE_NUM", + "LOG2_TWORD", + "CONCAT_STR2", +} + +-- Generate map from JSUB addresses to JSUB names. +local jsubmap = {} +do + local jsubmcode = jutil.jsubmcode + for pc=0,100000 do + local addr = jsubmcode(pc) + if not addr then break end + jsubmap[addr] = jsubnames[pc+1] or "JSUB#"..pc + end +end + +-- Pretty-print a constant. +local function conststr(func, idx) + local k = const(func, idx) + if k == nil then return "nil" + elseif k == true then return "true" + elseif k == false then return "false" + elseif type(k) == "string" then + if #k > 10 then return format('"%.10s"~', k) + else return '"'..k..'"' end + else return k.."" end +end + +-- Pretty-print a bytecode instruction (one or two lines). +local function bytecodeout(out, func, pc) + local op, a, b, c = bytecode(func, pc) + if not op then + return true + elseif op == "JMP" then + out:write(format("\n--%04d-- JMP => %04d", pc, pc+1+b)) + elseif op == "FORLOOP" or op == "FORPREP" then + out:write(format("\n--%04d-- %-9s %3d => %04d", pc, op, a, pc+1+b)) + else + out:write(format("\n--%04d-- %-9s %3d %4s %4s", + pc, op, a, b or "", c or "")) + if b and b < 0 then out:write(" ; ", conststr(func, b)) end + if c and c < 0 then out:write(" ; ", conststr(func, c)) end + end +end + +-- Dump machine code and mix it with the bytecode listing. +local function dumpfunc(func, out, deopt) + if not out then out = stderr end + local info = getinfo(func, "S") + + -- Don't bother checking for the right blocks to dump. + -- Dump the main block (if not deopt) and always all deopt blocks. + for block=deopt and 2 or 1,1000000 do + local addr, code, mfmiter = jutil.mcode(func, block) + if not addr then + if code then return code end -- Not compiled: return status. + break -- No more blocks to dump. + end + + -- Print header. + out:write(sepline, " ", info.source, ":", info.linedefined) + if block ~= 1 then out:write(" DEOPT block ", block) end + + -- Create disassembler context. + local ctx = discreate(code, addr, function(s) out:write(s) end) + ctx.symtab = jsubmap + + -- Dump an mcode block. + local pc, ofs = 1, 0 + local len, isdeopt = mfmiter() + if isdeopt then pc = len; len = 0 + elseif block ~= 1 then break end -- Stop before next main block. + for t, m in mfmiter do + if t == "COMBINE" then + bytecodeout(out, func, pc) + else + if len ~= 0 then + out:write("\n") + if len > 0 then + ctx:disass(ofs, len) + ofs = ofs + len + else + out:write(format("%08x ** deoptimized\n", addr+ofs)) + ofs = ofs - len + end + len = 0 + end + if type(t) == "number" then + if m then + if isdeopt then + pc = t - 1 + else + bytecodeout(out, func, pc) + len = -t + end + else + len = t + if bytecodeout(out, func, pc) then break end + end + end + end + pc = pc + 1 + end + if len and len ~= 0 then + out:write(sepline, " tail code\n") + ctx:disass(ofs, len) + end + end + + -- Print footer. + out:write(sepline, "\n") + out:flush() +end + +-- Dump the internal JIT subroutines. +local function dumpjsub_(out) + if not out then out = stderr end + local addr, code = jutil.jsubmcode() + + -- Create disassembler context. + local ctx = discreate(code, addr, function(s) out:write(s) end) + ctx.symtab = jsubmap + + -- Collect addresses and sort them. + local t = {} + for addr in pairs(jsubmap) do t[#t+1] = addr end + t[#t+1] = addr + #code + table.sort(t) + + -- Go through the addresses in ascending order. + local ofs = addr + for i=2,#t do + local next = t[i] + out:write("\n->", jsubmap[ofs], ":\n") -- Output label for JSUB. + ctx:disass(ofs-addr, next-ofs) -- Disassemble corresponding code block. + ofs = next + end + out:flush() +end + + +-- Active flag and output file handle. +local active, out + +-- Dump handler for compiler pipeline. +local function h_dump(st) + local ok, err = pcall(dumpfunc, st.func, out, st.deopt) + if not ok then + stderr:write("\nERROR: jit.dump disabled: ", err, "\n") + jit.attach(h_dump) -- Better turn ourselves off after a failure. + if out and out ~= stdout then out:close() end + out = nil + active = nil + end +end + +-- Detach dump handler from compiler pipeline. +local function dumpoff() + if active then + active = false + jit.attach(h_dump) + if out and out ~= stdout then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handler to compiler pipeline. +local function dumpon(filename) + if active then dumpoff() end + local outfile = filename or os.getenv("LUAJIT_DUMPFILE") + out = outfile and (outfile == "-" and stdout or assert(io.open(outfile, "w"))) + jit.attach(h_dump, PRIORITY) + active = true +end + + +-- Public module functions. +module(...) + +disass = disass_ +dump = dumpfunc +dumpjsub = dumpjsub_ +on = dumpon +off = dumpoff +start = dumpon -- For -j command line option. + -- cgit v1.1