mirror of https://github.com/rusefi/lua.git
using 'trap' to stop 'luaV_execute' when necessary (tracing and
to update its copy of 'base' when the stack is reallocated)
This commit is contained in:
parent
7d4828cc9f
commit
5440b42f43
23
ldebug.c
23
ldebug.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldebug.c,v 2.142 2017/11/08 14:50:23 roberto Exp roberto $
|
** $Id: ldebug.c,v 2.143 2017/11/13 12:20:51 roberto Exp roberto $
|
||||||
** Debug Interface
|
** Debug Interface
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -107,7 +107,24 @@ static int currentline (CallInfo *ci) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function can be called asynchronously (e.g. during a signal).
|
** This function can be called asynchronously (e.g. during a signal),
|
||||||
|
** under "reasonable" assumptions. A new 'ci' is completely linked
|
||||||
|
** in the list before it becomes part of the "active" list, and
|
||||||
|
** we assume that pointers are atomic (see comment in next function).
|
||||||
|
** (If we traverse one more item, there is no problem. If we traverse
|
||||||
|
** one less item, the worst that can happen is that the signal will
|
||||||
|
** not interrupt the script.)
|
||||||
|
*/
|
||||||
|
static void settraps (CallInfo *ci) {
|
||||||
|
for (; ci != NULL; ci = ci->previous)
|
||||||
|
if (isLua(ci))
|
||||||
|
ci->u.l.trap = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function can be called asynchronously (e.g. during a signal),
|
||||||
|
** under "reasonable" assumptions.
|
||||||
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
||||||
** 'resethookcount') are for debug only, and it is no problem if they
|
** 'resethookcount') are for debug only, and it is no problem if they
|
||||||
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
|
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
|
||||||
|
@ -126,6 +143,8 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||||
L->basehookcount = count;
|
L->basehookcount = count;
|
||||||
resethookcount(L);
|
resethookcount(L);
|
||||||
L->hookmask = cast_byte(mask);
|
L->hookmask = cast_byte(mask);
|
||||||
|
if (mask & (LUA_MASKLINE | LUA_MASKCOUNT))
|
||||||
|
settraps(L->ci); /* to trace inside 'luaV_execute' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
15
ldo.c
15
ldo.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.170 2017/11/07 13:25:26 roberto Exp roberto $
|
** $Id: ldo.c,v 2.171 2017/11/13 12:26:30 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -159,12 +159,16 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||||
static void correctstack (lua_State *L, StkId oldstack) {
|
static void correctstack (lua_State *L, StkId oldstack) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
UpVal *up;
|
UpVal *up;
|
||||||
|
if (L->stack == oldstack)
|
||||||
|
return; /* stack address did not change */
|
||||||
L->top = (L->top - oldstack) + L->stack;
|
L->top = (L->top - oldstack) + L->stack;
|
||||||
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
||||||
up->v = s2v((uplevel(up) - oldstack) + L->stack);
|
up->v = s2v((uplevel(up) - oldstack) + L->stack);
|
||||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||||
ci->top = (ci->top - oldstack) + L->stack;
|
ci->top = (ci->top - oldstack) + L->stack;
|
||||||
ci->func = (ci->func - oldstack) + L->stack;
|
ci->func = (ci->func - oldstack) + L->stack;
|
||||||
|
if (isLua(ci))
|
||||||
|
ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,13 +281,18 @@ void luaD_hook (lua_State *L, int event, int line) {
|
||||||
|
|
||||||
|
|
||||||
static void callhook (lua_State *L, CallInfo *ci) {
|
static void callhook (lua_State *L, CallInfo *ci) {
|
||||||
int hook = LUA_HOOKCALL;
|
int hook;
|
||||||
|
ci->u.l.trap = 1;
|
||||||
|
if (!(L->hookmask & LUA_MASKCALL))
|
||||||
|
return; /* some other hook */
|
||||||
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
|
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
|
||||||
if (isLua(ci->previous) &&
|
if (isLua(ci->previous) &&
|
||||||
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
|
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
|
||||||
ci->callstatus |= CIST_TAIL;
|
ci->callstatus |= CIST_TAIL;
|
||||||
hook = LUA_HOOKTAILCALL;
|
hook = LUA_HOOKTAILCALL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
hook = LUA_HOOKCALL;
|
||||||
luaD_hook(L, hook, -1);
|
luaD_hook(L, hook, -1);
|
||||||
ci->u.l.savedpc--; /* correct 'pc' */
|
ci->u.l.savedpc--; /* correct 'pc' */
|
||||||
}
|
}
|
||||||
|
@ -430,7 +439,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
lua_assert(ci->top <= L->stack_last);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->callstatus = CIST_LUA;
|
ci->callstatus = CIST_LUA;
|
||||||
if (L->hookmask & LUA_MASKCALL)
|
if (L->hookmask)
|
||||||
callhook(L, ci);
|
callhook(L, ci);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
3
lstate.c
3
lstate.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 2.143 2017/10/31 17:54:35 roberto Exp $
|
** $Id: lstate.c,v 2.146 2017/11/07 13:25:26 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -103,6 +103,7 @@ CallInfo *luaE_extendCI (lua_State *L) {
|
||||||
L->ci->next = ci;
|
L->ci->next = ci;
|
||||||
ci->previous = L->ci;
|
ci->previous = L->ci;
|
||||||
ci->next = NULL;
|
ci->next = NULL;
|
||||||
|
ci->u.l.trap = 0;
|
||||||
L->nci++;
|
L->nci++;
|
||||||
return ci;
|
return ci;
|
||||||
}
|
}
|
||||||
|
|
3
lstate.h
3
lstate.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 2.146 2017/11/02 11:28:56 roberto Exp $
|
** $Id: lstate.h,v 2.150 2017/11/07 13:25:26 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +91,7 @@ typedef struct CallInfo {
|
||||||
union {
|
union {
|
||||||
struct { /* only for Lua functions */
|
struct { /* only for Lua functions */
|
||||||
const Instruction *savedpc;
|
const Instruction *savedpc;
|
||||||
|
l_signalT trap;
|
||||||
} l;
|
} l;
|
||||||
struct { /* only for C functions */
|
struct { /* only for C functions */
|
||||||
lua_KFunction k; /* continuation in case of yields */
|
lua_KFunction k; /* continuation in case of yields */
|
||||||
|
|
47
lvm.c
47
lvm.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.308 2017/11/08 14:50:23 roberto Exp roberto $
|
** $Id: lvm.c,v 2.309 2017/11/08 19:01:02 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -756,14 +756,16 @@ void luaV_finishOp (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define updatemask(L) (mask = L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))
|
#define updatetrap(ci) (trap = ci->u.l.trap)
|
||||||
|
|
||||||
|
#define updatebase(ci) (base = ci->func + 1)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Execute a jump instruction. The 'updatemask' allows signals to stop
|
** Execute a jump instruction. The 'updatetrap' allows signals to stop
|
||||||
** tight loops. (Without it, the local copy of 'mask' could never change.)
|
** tight loops. (Without it, the local copy of 'trap' could never change.)
|
||||||
*/
|
*/
|
||||||
#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatemask(L); }
|
#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatetrap(ci); }
|
||||||
|
|
||||||
|
|
||||||
/* for test instructions, execute the jump instruction that follows it */
|
/* for test instructions, execute the jump instruction that follows it */
|
||||||
|
@ -780,19 +782,24 @@ void luaV_finishOp (lua_State *L) {
|
||||||
** Protect code that, in general, can raise errors, reallocate the
|
** Protect code that, in general, can raise errors, reallocate the
|
||||||
** stack, and change the hooks.
|
** stack, and change the hooks.
|
||||||
*/
|
*/
|
||||||
#define Protect(exp) (savepc(L), (exp), base = ci->func + 1, updatemask(L))
|
#define Protect(exp) (savepc(L), (exp), updatetrap(ci))
|
||||||
|
|
||||||
|
|
||||||
#define checkGC(L,c) \
|
#define checkGC(L,c) \
|
||||||
{ luaC_condGC(L, L->top = (c), /* limit of live values */ \
|
{ luaC_condGC(L, L->top = (c), /* limit of live values */ \
|
||||||
Protect(L->top = ci->top)); /* restore top */ \
|
(L->top = ci->top, updatetrap(ci))); /* restore top */ \
|
||||||
luai_threadyield(L); }
|
luai_threadyield(L); }
|
||||||
|
|
||||||
|
|
||||||
/* fetch an instruction and prepare its execution */
|
/* fetch an instruction and prepare its execution */
|
||||||
#define vmfetch() { \
|
#define vmfetch() { \
|
||||||
i = *(pc++); \
|
i = *(pc++); \
|
||||||
if (mask) Protect(luaG_traceexec(L)); \
|
if (trap) { \
|
||||||
|
if (!(L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))) \
|
||||||
|
trap = ci->u.l.trap = 0; /* no need to stop again */ \
|
||||||
|
else { savepc(L); luaG_traceexec(L); } \
|
||||||
|
updatebase(ci); /* the trap may be just for that */ \
|
||||||
|
} \
|
||||||
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
|
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,19 +809,19 @@ void luaV_finishOp (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
void luaV_execute (lua_State *L) {
|
void luaV_execute (lua_State *L) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci; /* local copy of 'L->ci' */
|
||||||
LClosure *cl;
|
LClosure *cl;
|
||||||
TValue *k;
|
TValue *k;
|
||||||
StkId base; /* local copy of 'ci->func + 1' */
|
StkId base; /* local copy of 'ci->func + 1' */
|
||||||
int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */
|
int trap;
|
||||||
const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */
|
const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */
|
||||||
ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */
|
ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */
|
||||||
newframe: /* reentry point when frame changes (call/return) */
|
newframe: /* reentry point when frame changes (call/return) */
|
||||||
lua_assert(ci == L->ci);
|
lua_assert(ci == L->ci);
|
||||||
cl = clLvalue(s2v(ci->func)); /* local reference to function's closure */
|
cl = clLvalue(s2v(ci->func)); /* local reference to function's closure */
|
||||||
k = cl->p->k; /* local reference to function's constant table */
|
k = cl->p->k; /* local reference to function's constant table */
|
||||||
updatemask(L);
|
updatetrap(ci);
|
||||||
base = ci->func + 1;
|
updatebase(ci);
|
||||||
pc = ci->u.l.savedpc;
|
pc = ci->u.l.savedpc;
|
||||||
/* main loop of interpreter */
|
/* main loop of interpreter */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1294,7 +1301,10 @@ void luaV_execute (lua_State *L) {
|
||||||
StkId rb;
|
StkId rb;
|
||||||
L->top = base + c + 1; /* mark the end of concat operands */
|
L->top = base + c + 1; /* mark the end of concat operands */
|
||||||
Protect(luaV_concat(L, c - b + 1));
|
Protect(luaV_concat(L, c - b + 1));
|
||||||
ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */
|
if (trap) { /* 'luaV_concat' may move the stack */
|
||||||
|
updatebase(ci);
|
||||||
|
ra = RA(i);
|
||||||
|
}
|
||||||
rb = base + b;
|
rb = base + b;
|
||||||
setobjs2s(L, ra, rb);
|
setobjs2s(L, ra, rb);
|
||||||
checkGC(L, (ra >= rb ? ra + 1 : rb));
|
checkGC(L, (ra >= rb ? ra + 1 : rb));
|
||||||
|
@ -1390,7 +1400,7 @@ void luaV_execute (lua_State *L) {
|
||||||
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
|
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
|
||||||
savepc(L);
|
savepc(L);
|
||||||
if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */
|
if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */
|
||||||
Protect((void)0); /* update 'base' */
|
updatetrap(ci);
|
||||||
else {
|
else {
|
||||||
/* tail call: put called frame (n) in place of caller one (o) */
|
/* tail call: put called frame (n) in place of caller one (o) */
|
||||||
CallInfo *nci = L->ci; /* called frame (new) */
|
CallInfo *nci = L->ci; /* called frame (new) */
|
||||||
|
@ -1416,7 +1426,8 @@ void luaV_execute (lua_State *L) {
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN) {
|
vmcase(OP_RETURN) {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
if (cl->p->sizep > 0) luaF_close(L, base);
|
if (cl->p->sizep > 0)
|
||||||
|
luaF_close(L, base);
|
||||||
savepc(L);
|
savepc(L);
|
||||||
b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
|
b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
|
||||||
if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
|
if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
|
||||||
|
@ -1452,7 +1463,7 @@ void luaV_execute (lua_State *L) {
|
||||||
setfltvalue(s2v(ra + 3), idx); /* ...and external index */
|
setfltvalue(s2v(ra + 3), idx); /* ...and external index */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatemask(L);
|
updatetrap(ci);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_FORPREP) {
|
vmcase(OP_FORPREP) {
|
||||||
|
@ -1492,8 +1503,10 @@ void luaV_execute (lua_State *L) {
|
||||||
L->top = cb + 3; /* func. + 2 args (state and index) */
|
L->top = cb + 3; /* func. + 2 args (state and index) */
|
||||||
Protect(luaD_call(L, cb, GETARG_C(i)));
|
Protect(luaD_call(L, cb, GETARG_C(i)));
|
||||||
L->top = ci->top;
|
L->top = ci->top;
|
||||||
|
if (trap) /* keep 'base' correct for next instruction */
|
||||||
|
updatebase(ci);
|
||||||
i = *(pc++); /* go to next instruction */
|
i = *(pc++); /* go to next instruction */
|
||||||
ra = RA(i);
|
ra = RA(i); /* get its 'ra' */
|
||||||
lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
|
lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
|
||||||
goto l_tforloop;
|
goto l_tforloop;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue