From 0ace0ad5b9de31b5aa2b3546ca0049b51cbbcaee Mon Sep 17 00:00:00 2001 From: fesily Date: Sun, 4 Jun 2023 20:34:59 +0800 Subject: [PATCH 1/6] support jit mode --- docs/luadebug/hookmgr.lua | 7 +++ extension/script/backend/worker.lua | 2 + extension/script/backend/worker/eval.lua | 10 ++++ .../script/backend/worker/eval/vmevent.lua | 45 ++++++++++++++++ extension/script/backend/worker/jit.lua | 54 +++++++++++++++++++ extension/script/debugger.lua | 1 - src/luadebug/rdebug_hookmgr.cpp | 30 ++++++++++- 7 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 extension/script/backend/worker/eval/vmevent.lua create mode 100644 extension/script/backend/worker/jit.lua diff --git a/docs/luadebug/hookmgr.lua b/docs/luadebug/hookmgr.lua index a64b4e9cb..0096a131c 100644 --- a/docs/luadebug/hookmgr.lua +++ b/docs/luadebug/hookmgr.lua @@ -135,4 +135,11 @@ end function hookmgr.coroutine_from(co) end +--- +---@param enable boolean +---启用luajit的jit支持 +--- +function hookmgr.enable_jit(enable) +end + return hookmgr diff --git a/extension/script/backend/worker.lua b/extension/script/backend/worker.lua index 1faddf4f5..08b9da76f 100644 --- a/extension/script/backend/worker.lua +++ b/extension/script/backend/worker.lua @@ -874,3 +874,5 @@ end) sendToMaster 'initWorker' {} hookmgr.update_open(true) + +return event diff --git a/extension/script/backend/worker/eval.lua b/extension/script/backend/worker/eval.lua index a59f639e0..62bfa37df 100644 --- a/extension/script/backend/worker/eval.lua +++ b/extension/script/backend/worker/eval.lua @@ -75,4 +75,14 @@ generate("ffi_reflect", function() end end) +generate("vmevent", function() + if not luaver.isjit then + return + end + local handler = assert(rdebug.load(readfile "backend.worker.eval.vmevent")) + return function(...) + return rdebug.eval(handler, ...) + end +end) + return m diff --git a/extension/script/backend/worker/eval/vmevent.lua b/extension/script/backend/worker/eval/vmevent.lua new file mode 100644 index 000000000..44fc95886 --- /dev/null +++ b/extension/script/backend/worker/eval/vmevent.lua @@ -0,0 +1,45 @@ +local jit = require("jit") +if jit.version_num ~= 20100 then + return "LuaJIT core/library version mismatch" +end +--TODO:检查是否有luajit profile被启用了 +local active = false +local record_count = 0 +local record_updeta_count = 32 + +---@module "script.debugger" +local luadebugger = debug.getregistry()["lua-debug"] +local function dump_trace() + luadebugger:event("update") +end +local function dump_record() + record_count = record_count + 1 + if record_count < record_updeta_count then + return + end + luadebugger:event("update") +end +local function dump_texit() + luadebugger:event("update") +end + +local function on() + jit.attach(dump_trace, "trace") + jit.attach(dump_record, "record") + jit.attach(dump_texit, "texit") + active = true +end +local function off() + jit.attach(dump_trace) + jit.attach(dump_record) + jit.attach(dump_texit) + active = false +end + +return function (enable) + if enable and not active then + on() + elseif active then + off() + end +end diff --git a/extension/script/backend/worker/jit.lua b/extension/script/backend/worker/jit.lua new file mode 100644 index 000000000..e22ef55a1 --- /dev/null +++ b/extension/script/backend/worker/jit.lua @@ -0,0 +1,54 @@ +local ev = require 'backend.event' +local rdebug = require 'luadebug.visitor' +local luaver = require 'backend.worker.luaver' +local hookmgr = require 'luadebug.hookmgr' + +local enable_jit = false + +local function set_jitmode(on) + on = on and "on" or "off" + local code = ([[ + if jit and jit.%s then + jit.%s() + end + ]]):format(on, on) + local thunk = rdebug.load(code) + if thunk then + rdebug.eval(thunk) + end +end + +local function attach_vmevent() + local worker = require 'backend.worker' + worker.autoUpdate(false) + local eval = require 'backend.worker.eval' + eval.vmevent(true) +end + +local function detach_vmevent() + local eval = require 'backend.worker.eval' + eval.vmevent(false) +end + +ev.on('initializing', function (config) + if not luaver.isjit then + return + end + enable_jit = config.enable_jit + if not enable_jit then + set_jitmode(false) + end + attach_vmevent() + hookmgr.enable_jit(true) +end) + +ev.on('terminated', function () + if not luaver.isjit then + return + end + if not enable_jit then + set_jitmode(true) + end + detach_vmevent() + hookmgr.enable_jit(false) +end) diff --git a/extension/script/debugger.lua b/extension/script/debugger.lua index b3b495ee2..02784b32a 100644 --- a/extension/script/debugger.lua +++ b/extension/script/debugger.lua @@ -113,7 +113,6 @@ local function detectLuaDebugPath(cfg) elseif _VERSION == "Lua 5.1" then if (tostring(assert):match('builtin') ~= nil) then rt = rt.."/luajit" - jit.off() else rt = rt.."/lua51" end diff --git a/src/luadebug/rdebug_hookmgr.cpp b/src/luadebug/rdebug_hookmgr.cpp index 5331e3c0a..3b8cfe415 100644 --- a/src/luadebug/rdebug_hookmgr.cpp +++ b/src/luadebug/rdebug_hookmgr.cpp @@ -368,6 +368,24 @@ struct hookmgr { } #endif +#if defined(LUAJIT_VERSION) + static void luaJIT_profile_callback(void* data, lua_State* hL, int samples, int vmstate) { + auto _this = (decltype(this))data; + _this->update_hook(hL); + } + constexpr auto profile_ms = + "i" + "100"; + void enable_jit(lua_State* hL, int enable) { + if (enable) { + luaJIT_profile_start(hL, profile_ms, luaJIT_profile_callback, this); + } + else { + luaJIT_profile_stop(hL); + } + } +#endif + // // common // @@ -716,8 +734,13 @@ static int coroutine_from(luadbg_State* L) { } #endif -LUADEBUG_FUNC -int luaopen_luadebug_hookmgr(luadbg_State* L) { +#if defined(LUAJIT_VERSION) +static int enable_jit(luadbg_State* L) { + hookmgr::get_self(L)->enable_jit(luadebug::debughost::get(L)), luadbg_toboolean(L, 1); + return 0; +} +#endif +LUADEBUG_FUNC int luaopen_luadebug_hookmgr(luadbg_State* L) { luadebug::debughost::get(L); luadbg_newtable(L); @@ -757,6 +780,9 @@ int luaopen_luadebug_hookmgr(luadbg_State* L) { #if defined(LUA_HOOKTHREAD) { "thread_open", thread_open }, { "coroutine_from", coroutine_from }, +#endif +#if defined(LUAJIT_VERSION) + { "enable_jit", enable_jit } #endif { NULL, NULL }, }; From b4e360ed6481607ff368d08e48f0fb9bde738267 Mon Sep 17 00:00:00 2001 From: fesily Date: Tue, 6 Jun 2023 10:15:17 +0800 Subject: [PATCH 2/6] manger function jit mode --- extension/script/backend/worker.lua | 12 +- extension/script/backend/worker/eval.lua | 10 +- .../script/backend/worker/eval/vmevent.lua | 22 +-- extension/script/backend/worker/jit.lua | 22 ++- src/luadebug/compat/internal.h | 12 ++ src/luadebug/compat/jit/fun.cpp | 10 ++ src/luadebug/compat/jit/gc.cpp | 18 +++ src/luadebug/compat/jit/trace.cpp | 128 ++++++++++++++++++ src/luadebug/rdebug_hookmgr.cpp | 78 ++++++++++- 9 files changed, 282 insertions(+), 30 deletions(-) create mode 100644 src/luadebug/compat/jit/fun.cpp create mode 100644 src/luadebug/compat/jit/gc.cpp create mode 100644 src/luadebug/compat/jit/trace.cpp diff --git a/extension/script/backend/worker.lua b/extension/script/backend/worker.lua index 08b9da76f..1e820e26b 100644 --- a/extension/script/backend/worker.lua +++ b/extension/script/backend/worker.lua @@ -652,9 +652,7 @@ function event.step(line) end end -function event.newproto(proto, level) - if not debuggeeReady() then return end - rdebug.getinfo(level, "S", info) +local function newprotoimpl(proto, info) local src = source.create(info.source) if not source.valid(src) then return false @@ -662,6 +660,14 @@ function event.newproto(proto, level) return breakpoint.newproto(proto, src, info.linedefined.."-"..info.lastlinedefined) end +function event.newproto(proto, level) + if not debuggeeReady() then return end + rdebug.getinfo(level, "S", info) + return newprotoimpl(proto, info) +end + +event.newprotoimpl = newprotoimpl + function event.update() debuggeeReady() workerThreadUpdate() diff --git a/extension/script/backend/worker/eval.lua b/extension/script/backend/worker/eval.lua index 62bfa37df..8d395ad8a 100644 --- a/extension/script/backend/worker/eval.lua +++ b/extension/script/backend/worker/eval.lua @@ -75,13 +75,17 @@ generate("ffi_reflect", function() end end) -generate("vmevent", function() +generate("vmevent", function () if not luaver.isjit then return end local handler = assert(rdebug.load(readfile "backend.worker.eval.vmevent")) - return function(...) - return rdebug.eval(handler, ...) + local ok, fn = rdebug.eval(handler) + if not ok then + return + end + return function (...) + return rdebug.eval(fn, ...) end end) diff --git a/extension/script/backend/worker/eval/vmevent.lua b/extension/script/backend/worker/eval/vmevent.lua index 44fc95886..c9985c2d5 100644 --- a/extension/script/backend/worker/eval/vmevent.lua +++ b/extension/script/backend/worker/eval/vmevent.lua @@ -5,34 +5,36 @@ end --TODO:检查是否有luajit profile被启用了 local active = false local record_count = 0 -local record_updeta_count = 32 +local record_updeta_count = 1024 ---@module "script.debugger" local luadebugger = debug.getregistry()["lua-debug"] -local function dump_trace() + +local function update_trace() luadebugger:event("update") end -local function dump_record() +local function update_record() record_count = record_count + 1 if record_count < record_updeta_count then return end luadebugger:event("update") + record_count = 0 end -local function dump_texit() +local function update_texit() luadebugger:event("update") end local function on() - jit.attach(dump_trace, "trace") - jit.attach(dump_record, "record") - jit.attach(dump_texit, "texit") + jit.attach(update_trace, "trace") + jit.attach(update_record, "record") + jit.attach(update_texit, "texit") active = true end local function off() - jit.attach(dump_trace) - jit.attach(dump_record) - jit.attach(dump_texit) + jit.attach(update_trace) + jit.attach(update_record) + jit.attach(update_texit) active = false end diff --git a/extension/script/backend/worker/jit.lua b/extension/script/backend/worker/jit.lua index e22ef55a1..dd1345a9b 100644 --- a/extension/script/backend/worker/jit.lua +++ b/extension/script/backend/worker/jit.lua @@ -4,6 +4,7 @@ local luaver = require 'backend.worker.luaver' local hookmgr = require 'luadebug.hookmgr' local enable_jit = false +local disable_vmevent = false local function set_jitmode(on) on = on and "on" or "off" @@ -19,10 +20,8 @@ local function set_jitmode(on) end local function attach_vmevent() - local worker = require 'backend.worker' - worker.autoUpdate(false) local eval = require 'backend.worker.eval' - eval.vmevent(true) + return eval.vmevent(true) end local function detach_vmevent() @@ -34,21 +33,30 @@ ev.on('initializing', function (config) if not luaver.isjit then return end - enable_jit = config.enable_jit + enable_jit = disable_vmevent or config.enable_jit if not enable_jit then set_jitmode(false) + return end - attach_vmevent() + if not attach_vmevent() then + disable_vmevent = true + return + end + local worker = require 'backend.worker' + worker.autoUpdate(false) hookmgr.enable_jit(true) end) -ev.on('terminated', function () +local function terminated() if not luaver.isjit then return end if not enable_jit then set_jitmode(true) + return end detach_vmevent() hookmgr.enable_jit(false) -end) +end + +ev.on('terminated', terminated) diff --git a/src/luadebug/compat/internal.h b/src/luadebug/compat/internal.h index 8f48fe566..6d8b16f83 100644 --- a/src/luadebug/compat/internal.h +++ b/src/luadebug/compat/internal.h @@ -12,8 +12,10 @@ const void* lua_tocfunction_pointer(lua_State* L, int idx); #ifdef LUAJIT_VERSION union TValue; struct GCproto; +union GCobj; using CallInfo = TValue; using Proto = GCproto; +using GCobject = GCobj; #else struct CallInfo; struct Proto; @@ -26,6 +28,16 @@ CallInfo* lua_debug2ci(lua_State* L, const lua_Debug* ar); #ifdef LUAJIT_VERSION int lua_isluafunc(lua_State* L, lua_Debug* ar); +using lua_foreach_gcobj_cb = void (*)(lua_State* L, void* ud, GCobject* o); +void lua_foreach_gcobj(lua_State* L, lua_foreach_gcobj_cb cb, void* ud); +Proto* lua_toproto(GCobject* o); +bool luajit_set_jitmode(lua_State* L, GCproto* pt, bool enable); +struct ProtoInfo { + const char* source; + int linedefined; + int lastlinedefined; +}; +ProtoInfo lua_getprotoinfo(lua_State* L, Proto* pt); #endif int lua_stacklevel(lua_State* L); diff --git a/src/luadebug/compat/jit/fun.cpp b/src/luadebug/compat/jit/fun.cpp new file mode 100644 index 000000000..9ee312f11 --- /dev/null +++ b/src/luadebug/compat/jit/fun.cpp @@ -0,0 +1,10 @@ +#include +#include +ProtoInfo lua_getprotoinfo(lua_State* L, Proto* pt) { + GCstr* name = proto_chunkname(pt); + return { + .source = strdata(name), + .linedefined = pt->firstline, + .lastlinedefined = (pt->firstline || !pt->numline) ? pt->firstline + pt->numline : 0, + }; +} \ No newline at end of file diff --git a/src/luadebug/compat/jit/gc.cpp b/src/luadebug/compat/jit/gc.cpp new file mode 100644 index 000000000..f9339f206 --- /dev/null +++ b/src/luadebug/compat/jit/gc.cpp @@ -0,0 +1,18 @@ +#include +#include + +void lua_foreach_gcobj(lua_State* L, lua_foreach_gcobj_cb cb, void* ud) { + auto g = G(L); + auto p = gcref(g->gc.root); + while (p != NULL) { + cb(L, ud, p); + p = gcref(p->gch.nextgc); + } +} + +Proto* lua_toproto(GCobject* o) { + if (o->gch.gct == ~LJ_TPROTO) { + return gco2pt(o); + } + return nullptr; +} diff --git a/src/luadebug/compat/jit/trace.cpp b/src/luadebug/compat/jit/trace.cpp new file mode 100644 index 000000000..a3440f0fe --- /dev/null +++ b/src/luadebug/compat/jit/trace.cpp @@ -0,0 +1,128 @@ +#include +#include +#include + +#include + +#if LJ_HASJIT +/* Unpatch the bytecode modified by a root trace. */ +static void trace_unpatch(jit_State* J, GCtrace* T) { + BCOp op = bc_op(T->startins); + BCIns* pc = mref(T->startpc, BCIns); + UNUSED(J); + if (op == BC_JMP) + return; /* No need to unpatch branches in parent traces (yet). */ + switch (bc_op(*pc)) { + case BC_JFORL: + lj_assertJ(traceref(J, bc_d(*pc)) == T, "JFORL references other trace"); + *pc = T->startins; + pc += bc_j(T->startins); + lj_assertJ(bc_op(*pc) == BC_JFORI, "FORL does not point to JFORI"); + setbc_op(pc, BC_FORI); + break; + case BC_JITERL: + case BC_JLOOP: + lj_assertJ(op == BC_ITERL || op == BC_ITERN || op == BC_LOOP || bc_isret(op), "bad original bytecode %d", op); + *pc = T->startins; + break; + case BC_JMP: + lj_assertJ(op == BC_ITERL, "bad original bytecode %d", op); + pc += bc_j(*pc) + 2; + if (bc_op(*pc) == BC_JITERL) { + lj_assertJ(traceref(J, bc_d(*pc)) == T, "JITERL references other trace"); + *pc = T->startins; + } + break; + case BC_JFUNCF: + lj_assertJ(op == BC_FUNCF, "bad original bytecode %d", op); + *pc = T->startins; + break; + default: /* Already unpatched. */ + break; + } +} +static void trace_flushroot(jit_State* J, GCtrace* T) { + GCproto* pt = &gcref(T->startpt)->pt; + lj_assertJ(T->root == 0, "not a root trace"); + lj_assertJ(pt != NULL, "trace has no prototype"); + /* First unpatch any modified bytecode. */ + trace_unpatch(J, T); + /* Unlink root trace from chain anchored in prototype. */ + if (pt->trace == T->traceno) { /* Trace is first in chain. Easy. */ + pt->trace = T->nextroot; + } + else if (pt->trace) { /* Otherwise search in chain of root traces. */ + GCtrace* T2 = traceref(J, pt->trace); + if (T2) { + for (; T2->nextroot; T2 = traceref(J, T2->nextroot)) + if (T2->nextroot == T->traceno) { + T2->nextroot = T->nextroot; /* Unlink from chain. */ + break; + } + } + } +} +void lj_trace_flushproto(global_State* g, GCproto* pt) { + while (pt->trace != 0) + trace_flushroot(G2J(g), traceref(G2J(g), pt->trace)); +} + +/* Re-enable compiling a prototype by unpatching any modified bytecode. */ +void lj_trace_reenableproto(GCproto* pt) { + if ((pt->flags & PROTO_ILOOP)) { + BCIns* bc = proto_bc(pt); + BCPos i, sizebc = pt->sizebc; + pt->flags &= ~PROTO_ILOOP; + if (bc_op(bc[0]) == BC_IFUNCF) + setbc_op(&bc[0], BC_FUNCF); + for (i = 1; i < sizebc; i++) { + BCOp op = bc_op(bc[i]); + if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP) + setbc_op(&bc[i], (int)op + (int)BC_LOOP - (int)BC_ILOOP); + } + } +} + +/* Set JIT mode for a single prototype. */ +static void setptmode(global_State* g, GCproto* pt, int mode) { + if ((mode & LUAJIT_MODE_ON)) { /* (Re-)enable JIT compilation. */ + pt->flags &= ~PROTO_NOJIT; + lj_trace_reenableproto(pt); /* Unpatch all ILOOP etc. bytecodes. */ + } + else { /* Flush and/or disable JIT compilation. */ + if (!(mode & LUAJIT_MODE_FLUSH)) + pt->flags |= PROTO_NOJIT; + lj_trace_flushproto(g, pt); /* Flush all traces of prototype. */ + } +} + +/* Recursively set the JIT mode for all children of a prototype. */ +static void setptmode_all(global_State* g, GCproto* pt, int mode) { + ptrdiff_t i; + if (!(pt->flags & PROTO_CHILD)) return; + for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) { + GCobj* o = proto_kgc(pt, i); + if (o->gch.gct == ~LJ_TPROTO) { + setptmode(g, gco2pt(o), mode); + setptmode_all(g, gco2pt(o), mode); + } + } +} +#endif + +bool luajit_set_jitmode(lua_State* L, GCproto* pt, bool enable) { +#ifdef LJ_HASJIT + bool nojit = pt->flags & PROTO_NOJIT; + if (enable) { + if (nojit) + setptmode_all(G(L), pt, LUAJIT_MODE_ON); + } + else { + if (!nojit) + setptmode_all(G(L), pt, LUAJIT_MODE_OFF); + } + return nojit; +#else + return false; +#endif +} \ No newline at end of file diff --git a/src/luadebug/rdebug_hookmgr.cpp b/src/luadebug/rdebug_hookmgr.cpp index 3b8cfe415..9484ad636 100644 --- a/src/luadebug/rdebug_hookmgr.cpp +++ b/src/luadebug/rdebug_hookmgr.cpp @@ -108,19 +108,42 @@ struct hookmgr { // bpmap break_proto; int break_mask = 0; +#ifdef LUAJIT_VERSION + luadebug::flatmap break_jitblack; +#endif void break_add(lua_State* hL, Proto* p) { break_proto.set(p, bpmap::status::Break); +#ifdef LUAJIT_VERSION + auto old_nojit = luajit_set_jitmode(hL, p, false); + if (old_nojit) { + break_jitblack.insert_or_assign(p, true); + } +#endif } void break_del(lua_State* hL, Proto* p) { break_proto.set(p, bpmap::status::Ignore); +#ifdef LUAJIT_VERSION + // 如果原来就关闭了就不再启用 + if (break_jitblack.find(p)) { + break_jitblack.erase(p); + } + else { + luajit_set_jitmode(hL, p, true); + } +#endif } void break_freeobj(Proto* p) { break_proto.set(p, bpmap::status::None); } void break_open(lua_State* hL, bool enable) { - if (enable) + if (enable) { break_update(hL, lua_getcallinfo(hL), LUA_HOOKCALL); +#ifdef LUAJIT_VERSION + if (enable_jit_flag) + break_updateprotos(hL); +#endif + } else break_hookmask(hL, 0); } @@ -190,6 +213,44 @@ struct hookmgr { updatehookmask(hL); } } +#ifdef LUAJIT_VERSION + inline void break_updateproto(lua_State* hL, Proto* pt) { + auto status = break_proto.get(pt); + if (status != bpmap::status::None) { + return; + } + break_del(hL, pt); + + luadbgL_checkstack(L, 4, NULL); + push_callback(L); + luadebug::debughost::set(L, hL); + luadbg_pushstring(L, "newprotoimpl"); + luadbg_pushlightuserdata(L, pt); + luadbg_createtable(L, 0, 3); + auto info = lua_getprotoinfo(hL, pt); + luadbg_pushstring(L, info.source); + luadbg_setfield(L, -2, "source"); + luadbg_pushinteger(L, info.linedefined); + luadbg_setfield(L, -2, "linedefined"); + luadbg_pushinteger(L, info.lastlinedefined); + luadbg_setfield(L, -2, "lastlinedefined"); + if (luadbg_pcall(L, 3, 0, 0) != LUADBG_OK) { + luadbg_pop(L, 1); + } + } + void break_updateprotos(lua_State* hL) { + lua_foreach_gcobj( + hL, [](lua_State* hL, void* ud, GCobject* o) { + auto _this = (decltype(this))ud; + auto proto = lua_toproto(o); + if (!proto) + return; + _this->break_updateproto(hL, proto); + }, + this + ); + } +#endif // // funcbp @@ -370,18 +431,21 @@ struct hookmgr { #if defined(LUAJIT_VERSION) static void luaJIT_profile_callback(void* data, lua_State* hL, int samples, int vmstate) { - auto _this = (decltype(this))data; + auto _this = (hookmgr*)data; _this->update_hook(hL); } - constexpr auto profile_ms = - "i" - "100"; + bool enable_jit_flag = false; void enable_jit(lua_State* hL, int enable) { + constexpr auto profile_ms = + "i" + "100"; if (enable) { luaJIT_profile_start(hL, profile_ms, luaJIT_profile_callback, this); + enable_jit_flag = true; } else { luaJIT_profile_stop(hL); + enable_jit_flag = false; } } #endif @@ -736,7 +800,7 @@ static int coroutine_from(luadbg_State* L) { #if defined(LUAJIT_VERSION) static int enable_jit(luadbg_State* L) { - hookmgr::get_self(L)->enable_jit(luadebug::debughost::get(L)), luadbg_toboolean(L, 1); + hookmgr::get_self(L)->enable_jit(luadebug::debughost::get(L), luadbg_toboolean(L, 1)); return 0; } #endif @@ -782,7 +846,7 @@ LUADEBUG_FUNC int luaopen_luadebug_hookmgr(luadbg_State* L) { { "coroutine_from", coroutine_from }, #endif #if defined(LUAJIT_VERSION) - { "enable_jit", enable_jit } + { "enable_jit", enable_jit }, #endif { NULL, NULL }, }; From 415eb7f2db9c152cffbe4ec5767b82d6fe6aa419 Mon Sep 17 00:00:00 2001 From: fesily Date: Tue, 6 Jun 2023 11:12:18 +0800 Subject: [PATCH 3/6] check jit flag --- extension/script/backend/worker/eval.lua | 4 +++ .../script/backend/worker/eval/vmevent.lua | 13 ++++++---- .../backend/worker/{jit.lua => luajit.lua} | 6 ++--- src/luadebug/rdebug_hookmgr.cpp | 26 ++++++++++++------- 4 files changed, 31 insertions(+), 18 deletions(-) rename extension/script/backend/worker/{jit.lua => luajit.lua} (91%) diff --git a/extension/script/backend/worker/eval.lua b/extension/script/backend/worker/eval.lua index 8d395ad8a..516290be1 100644 --- a/extension/script/backend/worker/eval.lua +++ b/extension/script/backend/worker/eval.lua @@ -84,6 +84,10 @@ generate("vmevent", function () if not ok then return end + if rdebug.type(fn) ~= "function" then + return function () + end + end return function (...) return rdebug.eval(fn, ...) end diff --git a/extension/script/backend/worker/eval/vmevent.lua b/extension/script/backend/worker/eval/vmevent.lua index c9985c2d5..49b9146b6 100644 --- a/extension/script/backend/worker/eval/vmevent.lua +++ b/extension/script/backend/worker/eval/vmevent.lua @@ -1,8 +1,11 @@ local jit = require("jit") -if jit.version_num ~= 20100 then - return "LuaJIT core/library version mismatch" +if not jit.status() then + return "LuaJIT jit is not enabled" +end +if not pcall(require, 'jit.profile') then + --需要profile来update防止正在运行的代码全部被jit了而不无法update + return "LuaJIT profile is not enabled" end ---TODO:检查是否有luajit profile被启用了 local active = false local record_count = 0 local record_updeta_count = 1024 @@ -32,9 +35,9 @@ local function on() active = true end local function off() - jit.attach(update_trace) - jit.attach(update_record) jit.attach(update_texit) + jit.attach(update_record) + jit.attach(update_trace) active = false end diff --git a/extension/script/backend/worker/jit.lua b/extension/script/backend/worker/luajit.lua similarity index 91% rename from extension/script/backend/worker/jit.lua rename to extension/script/backend/worker/luajit.lua index dd1345a9b..98d18093a 100644 --- a/extension/script/backend/worker/jit.lua +++ b/extension/script/backend/worker/luajit.lua @@ -4,7 +4,7 @@ local luaver = require 'backend.worker.luaver' local hookmgr = require 'luadebug.hookmgr' local enable_jit = false -local disable_vmevent = false +local no_vmevent = false local function set_jitmode(on) on = on and "on" or "off" @@ -33,13 +33,13 @@ ev.on('initializing', function (config) if not luaver.isjit then return end - enable_jit = disable_vmevent or config.enable_jit + enable_jit = no_vmevent or not config.disable_jit if not enable_jit then set_jitmode(false) return end if not attach_vmevent() then - disable_vmevent = true + no_vmevent = true return end local worker = require 'backend.worker' diff --git a/src/luadebug/rdebug_hookmgr.cpp b/src/luadebug/rdebug_hookmgr.cpp index 9484ad636..528614909 100644 --- a/src/luadebug/rdebug_hookmgr.cpp +++ b/src/luadebug/rdebug_hookmgr.cpp @@ -115,21 +115,25 @@ struct hookmgr { void break_add(lua_State* hL, Proto* p) { break_proto.set(p, bpmap::status::Break); #ifdef LUAJIT_VERSION - auto old_nojit = luajit_set_jitmode(hL, p, false); - if (old_nojit) { - break_jitblack.insert_or_assign(p, true); + if (enable_jit_flag) { + auto old_nojit = luajit_set_jitmode(hL, p, false); + if (old_nojit) { + break_jitblack.insert_or_assign(p, true); + } } #endif } void break_del(lua_State* hL, Proto* p) { break_proto.set(p, bpmap::status::Ignore); #ifdef LUAJIT_VERSION - // 如果原来就关闭了就不再启用 - if (break_jitblack.find(p)) { - break_jitblack.erase(p); - } - else { - luajit_set_jitmode(hL, p, true); + if (enable_jit_flag) { + // 如果原来就关闭了就不再启用 + if (break_jitblack.find(p)) { + break_jitblack.erase(p); + } + else { + luajit_set_jitmode(hL, p, true); + } } #endif } @@ -438,8 +442,10 @@ struct hookmgr { void enable_jit(lua_State* hL, int enable) { constexpr auto profile_ms = "i" - "100"; + "200"; if (enable) { + if (enable_jit_flag) + luaJIT_profile_stop(hL); luaJIT_profile_start(hL, profile_ms, luaJIT_profile_callback, this); enable_jit_flag = true; } From 75da28cf4aad8b5b94b758e3d24b8f17cdfcac51 Mon Sep 17 00:00:00 2001 From: fesily Date: Tue, 6 Jun 2023 11:14:21 +0800 Subject: [PATCH 4/6] format code --- src/luadebug/compat/jit/fun.cpp | 2 +- src/luadebug/compat/jit/trace.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/luadebug/compat/jit/fun.cpp b/src/luadebug/compat/jit/fun.cpp index 9ee312f11..c1e5aaac9 100644 --- a/src/luadebug/compat/jit/fun.cpp +++ b/src/luadebug/compat/jit/fun.cpp @@ -7,4 +7,4 @@ ProtoInfo lua_getprotoinfo(lua_State* L, Proto* pt) { .linedefined = pt->firstline, .lastlinedefined = (pt->firstline || !pt->numline) ? pt->firstline + pt->numline : 0, }; -} \ No newline at end of file +} diff --git a/src/luadebug/compat/jit/trace.cpp b/src/luadebug/compat/jit/trace.cpp index a3440f0fe..5662cb8bb 100644 --- a/src/luadebug/compat/jit/trace.cpp +++ b/src/luadebug/compat/jit/trace.cpp @@ -125,4 +125,4 @@ bool luajit_set_jitmode(lua_State* L, GCproto* pt, bool enable) { #else return false; #endif -} \ No newline at end of file +} From 8844b228adeb3df86f71ada55436baa59509113e Mon Sep 17 00:00:00 2001 From: fesily Date: Tue, 6 Jun 2023 11:21:18 +0800 Subject: [PATCH 5/6] fix build err --- src/luadebug/compat/jit/fun.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/luadebug/compat/jit/fun.cpp b/src/luadebug/compat/jit/fun.cpp index c1e5aaac9..893cd22be 100644 --- a/src/luadebug/compat/jit/fun.cpp +++ b/src/luadebug/compat/jit/fun.cpp @@ -2,9 +2,9 @@ #include ProtoInfo lua_getprotoinfo(lua_State* L, Proto* pt) { GCstr* name = proto_chunkname(pt); - return { - .source = strdata(name), - .linedefined = pt->firstline, - .lastlinedefined = (pt->firstline || !pt->numline) ? pt->firstline + pt->numline : 0, - }; + ProtoInfo info; + info.source = strdata(name); + info.linedefined = pt->firstline; + info.lastlinedefined = (pt->firstline || !pt->numline) ? pt->firstline + pt->numline : 0; + return info; } From 6a2868f65940b76e3b777ba14445ab0cd86c775e Mon Sep 17 00:00:00 2001 From: fesily Date: Fri, 9 Jun 2023 11:27:10 +0800 Subject: [PATCH 6/6] use vmevent.bc --- extension/script/backend/worker.lua | 5 ++++- extension/script/backend/worker/eval/vmevent.lua | 6 ++++++ src/luadebug/rdebug_hookmgr.cpp | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/extension/script/backend/worker.lua b/extension/script/backend/worker.lua index 1e820e26b..dc268e58a 100644 --- a/extension/script/backend/worker.lua +++ b/extension/script/backend/worker.lua @@ -666,7 +666,10 @@ function event.newproto(proto, level) return newprotoimpl(proto, info) end -event.newprotoimpl = newprotoimpl +function event.newprotoimpl(proto, info) + if not debuggeeReady() then return end + return newprotoimpl(proto, info) +end function event.update() debuggeeReady() diff --git a/extension/script/backend/worker/eval/vmevent.lua b/extension/script/backend/worker/eval/vmevent.lua index 49b9146b6..00e84396b 100644 --- a/extension/script/backend/worker/eval/vmevent.lua +++ b/extension/script/backend/worker/eval/vmevent.lua @@ -28,7 +28,12 @@ local function update_texit() luadebugger:event("update") end +local function update_bc(pt) + luadebugger:event("create_proto", pt) +end + local function on() + jit.attach(update_bc, "bc") jit.attach(update_trace, "trace") jit.attach(update_record, "record") jit.attach(update_texit, "texit") @@ -38,6 +43,7 @@ local function off() jit.attach(update_texit) jit.attach(update_record) jit.attach(update_trace) + jit.attach(update_bc) active = false end diff --git a/src/luadebug/rdebug_hookmgr.cpp b/src/luadebug/rdebug_hookmgr.cpp index 528614909..11aa9a132 100644 --- a/src/luadebug/rdebug_hookmgr.cpp +++ b/src/luadebug/rdebug_hookmgr.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "compat/internal.h" #include "rdebug_debughost.h" @@ -875,6 +876,13 @@ static bool call_event(luadbg_State* L, int nargs) { } bool event(luadbg_State* L, lua_State* hL, const char* name, int start) { +#ifdef LUAJIT_VERSION + using namespace std::string_view_literals; + if (name == "create_proto"sv) { + hookmgr::get_self(L)->break_updateproto(hL, lua_getproto(hL, start + 1)); + return true; + } +#endif if (luadbg_rawgetp(L, LUADBG_REGISTRYINDEX, &HOOK_CALLBACK) != LUADBG_TFUNCTION) { // TODO cache event? luadbg_pop(L, 1);