static void traceexec (lua_State *L) { CallInfo *ci = L->ci; lu_byte mask = L->hookmask; int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); if (counthook) resethookcount(L); /* reset count */ if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ return; /* do not call hook again (VM yielded, so it did not move) */ } if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ if (mask & LUA_MASKLINE) { Proto *p = ci_func(ci)->p; int npc = pcRel(ci->u.l.savedpc, p); int newline = getfuncline(p, npc); if (npc == 0 || /* call linehook when enter a new function, */ ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ } L->oldpc = ci->u.l.savedpc; if (L->status == LUA_YIELD) { /* did hook yield? */ if (counthook) L->hookcount = 1; /* undo decrement to zero */ ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ ci->func = L->top - 1; /* protect stack below results */ luaD_throw(L, LUA_YIELD); } }
LUA_API lua_State *lua_newthread (lua_State *L) { global_State *g = G(L); lua_State *L1; lua_lock(L); luaC_checkGC(L); /* create new thread */ L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; L1->marked = luaC_white(g); L1->tt = LUA_TTHREAD; /* link it on list 'allgc' */ L1->next = g->allgc; g->allgc = obj2gco(L1); /* anchor it on L stack */ setthvalue(L, L->top, L1); api_incr_top(L); preinit_thread(L1, g); L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); /* initialize L1 extra space */ c_memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), LUA_EXTRASPACE); luai_userstatethread(L, L1); stack_init(L1, L); /* init stack */ lua_unlock(L); return L1; }
static void traceexec (lua_State *L) { lu_byte mask = L->hookmask; if (mask > LUA_MASKLINE) { /* instruction-hook set? */ if (L->hookcount == 0) { resethookcount(L); luaD_callhook(L, LUA_HOOKCOUNT, -1); return; } } if (mask & LUA_MASKLINE) { CallInfo *ci = L->ci; Proto *p = ci_func(ci)->l.p; int newline = getline(p, pcRel(*ci->u.l.pc, p)); if (!L->hookinit) { luaG_inithooks(L); return; } lua_assert(ci->state & CI_HASFRAME); if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ /* calls linehook when enters a new line or jumps back (loop) */ if (*ci->u.l.pc <= ci->u.l.savedpc || newline != getline(p, pcRel(ci->u.l.savedpc, p))) { luaD_callhook(L, LUA_HOOKLINE, newline); ci = L->ci; /* previous call may reallocate `ci' */ } ci->u.l.savedpc = *ci->u.l.pc; } }
/* ** this function can be called asynchronous (e.g. during a signal) */ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { if (func == NULL || mask == 0) { /* turn off hooks? */ mask = 0; func = NULL; } L->hook = func; L->basehookcount = count; resethookcount(L); L->hookmask = cast_byte(mask); return 1; }
/* ** This function can be called asynchronously (e.g. during a signal). ** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by ** 'resethookcount') are for debug only, and it is no problem if they ** get arbitrary values (causes at most one wrong hook call). 'hookmask' ** is an atomic value. We assume that pointers are atomic too (e.g., gcc ** ensures that for all platforms where it runs). Moreover, 'hook' is ** always checked before being called (see 'luaD_hook'). */ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { if (func == NULL || mask == 0) { /* turn off hooks? */ mask = 0; func = NULL; } if (isLua(L->ci)) L->oldpc = L->ci->u.l.savedpc; L->hook = func; L->basehookcount = count; resethookcount(L); L->hookmask = cast_byte(mask); }
lua_State *luaE_newthread (lua_State *L) { lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); luaC_link(L, obj2gco(L1), LUA_TTHREAD); preinit_state(L1, G(L)); stack_init(L1, L); /* init stack */ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); lua_assert(iswhite(obj2gco(L1))); return L1; }
static void preinit_state (lua_State *L) { L->stack = NULL; L->stacksize = 0; L->errorJmp = NULL; L->hook = NULL; L->hookmask = L->hookinit = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; L->nCcalls = 0; L->base_ci = L->ci = NULL; L->errfunc = 0; setnilvalue(gt(L)); }
lua_State *luaE_newthread (lua_State *L) { lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); luaC_link(L, obj2gco(L1), LUA_TTHREAD); setthvalue(L, L->top, L1); /* put thread on stack */ incr_top(L); preinit_state(L1, G(L)); stack_init(L1, L); /* init stack */ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); lua_assert(!isdead(G(L), obj2gco(L1))); L->top--; /* remove thread from stack */ return L1; }
LUA_API lua_State *lua_newthread (lua_State *L) { lua_State *L1; lua_lock(L); luaC_checkGC(L); L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; setthvalue(L, L->top, L1); api_incr_top(L); preinit_state(L1, G(L)); L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); luai_userstatethread(L, L1); stack_init(L1, L); /* init stack */ lua_unlock(L); return L1; }
/* ** preinitialize a state with consistent values without allocating ** any memory (to avoid errors) */ static void preinit_state (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->ci = NULL; L->stacksize = 0; L->errorJmp = NULL; L->nCcalls = 0; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->nny = 1; L->status = LUA_OK; L->errfunc = 0; }
static void traceexec (lua_State *L, const Instruction *pc) { lu_byte mask = L->hookmask; const Instruction *oldpc = L->savedpc; L->savedpc = pc; if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { resethookcount(L); luaD_callhook(L, LUA_HOOKCOUNT, -1); } if (mask & LUA_MASKLINE) { Proto *p = ci_func(L->ci)->l.p; int npc = pcRel(pc, p); int newline = getline(p, npc); /* call linehook when enter a new function, when jump back (loop), or when enter a new line */ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) luaD_callhook(L, LUA_HOOKLINE, newline); } }
static void preinit_state (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->stacksize = 0; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; L->nCcalls = L->baseCcalls = 0; L->status = 0; L->base_ci = L->ci = NULL; L->savedpc = NULL; L->errfunc = 0; setnilvalue(gt(L)); }
/* ** preinitialize a thread with consistent values without allocating ** any memory (to avoid errors) */ static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->ci = NULL; L->nci = 0; L->stacksize = 0; L->twups = L; /* thread has no upvalues */ L->errorJmp = NULL; L->nCcalls = 0; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->nny = 1; L->status = LUA_OK; L->errfunc = 0; L->base_ci.stacklevel = 0; /* RAVI base stack level */ }
// [@lvm] 检查并调用hook函数 static void traceexec (lua_State *L, const Instruction *pc) { lu_byte mask = L->hookmask; const Instruction *oldpc = L->savedpc; L->savedpc = pc; if (mask > LUA_MASKLINE) { /* instruction-hook set? */ if (L->hookcount == 0) { resethookcount(L); luaD_callhook(L, LUA_HOOKCOUNT, -1); } } if (mask & LUA_MASKLINE) { Proto *p = ci_func(L->ci)->l.p; int npc = pcRel(pc, p); //now pc int newline = getline(p, npc); /* call linehook when enter a new function, when jump back (loop), or when enter a new line */ // 看仔细了:`when jump back`,对应pc <= oldpc。这也算newline,所以导致 // LDT会在同一行停呀停! if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) luaD_callhook(L, LUA_HOOKLINE, newline); } }
static void traceexec (lua_State *L) { CallInfo *ci = L->ci; lu_byte mask = L->hookmask; if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { resethookcount(L); luaD_hook(L, LUA_HOOKCOUNT, -1); } if (mask & LUA_MASKLINE) { Proto *p = ci_func(ci)->p; int npc = pcRel(ci->u.l.savedpc, p); int newline = getfuncline(p, npc); if (npc == 0 || /* call linehook when enter a new function, */ ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ luaD_hook(L, LUA_HOOKLINE, newline); } L->oldpc = ci->u.l.savedpc; if (L->status == LUA_YIELD) { /* did hook yield? */ ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ luaD_throw(L, LUA_YIELD); } }
static void preinit_state (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->stacksize = 0; L->errorJmp = NULL; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; L->nCcalls = L->baseCcalls = 0; L->status = 0; L->base_ci = L->ci = NULL; L->savedpc = NULL; L->errfunc = 0; #if LUA_REFCOUNT L->ref = 0; setnilvalue2n(L, gt(L)); #else setnilvalue(gt(L)); #endif /* LUA_REFCOUNT */ }