diff --git a/ldebug.c b/ldebug.c index 11d2b6a7..80c19d31 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.148 2017/12/13 18:32:09 roberto Exp roberto $ +** $Id: ldebug.c,v 2.149 2017/12/15 13:07:10 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -189,14 +189,10 @@ static const char *upvalname (Proto *p, int uv) { static const char *findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { - const char *name = NULL; - StkId base; - if (isLua(ci)) { - base = ci->func + 1; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - else - base = ci->func + 1; + StkId base = ci->func + 1; + const char *name = (isLua(ci)) + ? luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)) + : NULL; if (name == NULL) { /* no 'standard' name? */ StkId limit = (ci == L->ci) ? L->top : ci->next->func; if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ @@ -741,6 +737,8 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { const char *msg; va_list argp; luaC_checkGC(L); /* error message uses memory */ + if (isLuacode(ci)) + L->top = ci->top; /* prepare top */ va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); @@ -764,6 +762,7 @@ static int changedline (Proto *p, int oldpc, int newpc) { void luaG_traceexec (lua_State *L) { + ptrdiff_t oldtop = savestack(L, L->top); CallInfo *ci = L->ci; lu_byte mask = L->hookmask; int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); @@ -775,6 +774,7 @@ void luaG_traceexec (lua_State *L) { ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ return; /* do not call hook again (VM yielded, so it did not move) */ } + L->top = ci->top; /* prepare top */ if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ if (mask & LUA_MASKLINE) { @@ -789,6 +789,7 @@ void luaG_traceexec (lua_State *L) { } L->oldpc = npc; } + L->top = restorestack(L, oldtop); if (L->status == LUA_YIELD) { /* did hook yield? */ if (counthook) L->hookcount = 1; /* undo decrement to zero */ diff --git a/ldo.c b/ldo.c index fa8a382b..77c408ba 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.181 2017/12/15 13:07:10 roberto Exp roberto $ +** $Id: ldo.c,v 2.182 2017/12/19 16:40:17 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -299,6 +299,7 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) { ci->u.l.trap = 1; if (!(L->hookmask & LUA_MASKCALL)) return; /* some other hook */ + L->top = ci->top; /* prepare top */ ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ if (istail) { ci->callstatus |= CIST_TAIL; @@ -312,6 +313,8 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) { static void rethook (lua_State *L, CallInfo *ci) { + if (isLuacode(ci)) + L->top = ci->top; /* prepare top */ if (L->hookmask & LUA_MASKRET) /* is return hook on? */ luaD_hook(L, LUA_HOOKRET, -1); /* call it */ if (isLua(ci->previous)) @@ -421,7 +424,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) { L->top -= (func - ci->func); /* move down top */ luaT_adjustvarargs(L, p, n - 1); } - L->top = ci->top = ci->func + 1 + fsize; /* top for new function */ + ci->top = ci->func + 1 + fsize; /* top for new function */ lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus |= CIST_TAIL; @@ -476,7 +479,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; ci->func = func; - L->top = ci->top = func + 1 + fsize; + ci->top = func + 1 + fsize; lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = 0; diff --git a/lgc.c b/lgc.c index 8d28d3bf..37bcdb8d 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.241 2017/12/01 17:38:49 roberto Exp roberto $ +** $Id: lgc.c,v 2.242 2017/12/08 17:28:25 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -569,13 +569,23 @@ static int traverseLclosure (global_State *g, LClosure *cl) { } +/* +** Traverse a thread, marking the elements in the stack up to its top +** and cleaning the rest of the stack in the last traversal. +** That ensures that the entire stack have valid (non-dead) objects. +** In an emergency collection running Lua code, 'L->top' may not be +** update. In that case, traverse at least up to 'ci->top'. +*/ static int traversethread (global_State *g, lua_State *th) { StkId o = th->stack; + StkId top = th->top; if (o == NULL) return 1; /* stack not completely built yet */ lua_assert(g->gcstate == GCSatomic || th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ + if (g->gcemergency && isLuacode(th->ci) && top < th->ci->top) + top = th->ci->top; + for (; o < top; o++) /* mark live elements in the stack */ markvalue(g, s2v(o)); if (g->gcstate == GCSatomic) { /* final traversal? */ StkId lim = th->stack + th->stacksize; /* real end of stack */ diff --git a/ltm.c b/ltm.c index 5906a2fd..d41ab98d 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.53 2017/12/15 13:07:10 roberto Exp roberto $ +** $Id: ltm.c,v 2.54 2017/12/19 16:40:17 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -101,12 +101,12 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) { void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { - StkId func = L->top; + StkId func = (isLuacode(L->ci)) ? L->ci->top : L->top; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ setobj2s(L, func + 3, p3); /* 3rd argument */ - L->top += 4; + L->top = func + 4; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 0); @@ -115,8 +115,8 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, } -void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, StkId res) { +static void reallycallTMres (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); StkId func = L->top; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ @@ -129,7 +129,15 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, else luaD_callnoyield(L, func, 1); res = restorestack(L, result); - setobjs2s(L, res, --L->top); /* more result to its place */ + setobjs2s(L, res, --L->top); /* move result to its place */ +} + + +void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, StkId res) { + if (isLuacode(L->ci)) + L->top = L->ci->top; /* prepare top */ + reallycallTMres(L, f, p1, p2, res); } @@ -139,13 +147,15 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, if (ttisnil(tm)) tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ if (ttisnil(tm)) return 0; - luaT_callTMres(L, tm, p1, p2, res); + reallycallTMres(L, tm, p1, p2, res); return 1; } void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { + if (event != TM_CONCAT && isLuacode(L->ci)) + L->top = L->ci->top; /* prepare top */ if (!callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: @@ -185,6 +195,8 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2, int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { + if (isLuacode(L->ci)) + L->top = L->ci->top; /* prepare top */ if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ return !l_isfalse(s2v(L->top)); else if (event == TM_LE) { diff --git a/lvm.c b/lvm.c index 29c6e373..8039770e 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.326 2017/12/18 17:53:50 roberto Exp roberto $ +** $Id: lvm.c,v 2.327 2017/12/19 16:18:04 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -464,6 +464,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { } if (tm == NULL) /* no TM? */ return 0; /* objects are different */ + if (isLuacode(L->ci)) + L->top = L->ci->top; /* prepare top */ luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ return !l_isfalse(s2v(L->top)); } @@ -726,20 +728,10 @@ void luaV_finishOp (lua_State *L) { } /* move final result to final position */ setobjs2s(L, ci->func + 1 + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ break; } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ - break; - } - case OP_CALL: { - if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ - break; - } - case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + case OP_TFORCALL: case OP_CALL: case OP_TAILCALL: + case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD: break; default: lua_assert(0); @@ -808,7 +800,7 @@ void luaV_finishOp (lua_State *L) { #define checkGC(L,c) \ { luaC_condGC(L, L->top = (c), /* limit of live values */ \ - (L->top = ci->top, updatetrap(ci))); /* restore top */ \ + updatetrap(ci)); \ luai_threadyield(L); } @@ -1387,7 +1379,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) { rb = base + b; setobjs2s(L, ra, rb); checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ vmbreak; } vmcase(OP_CLOSE) { @@ -1491,9 +1482,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) { L->top = ra + b; /* top signals number of arguments */ /* else previous instruction set top */ Protect(luaD_call(L, ra, nresults)); - if (nresults >= 0) /* fixed number of results? */ - L->top = ci->top; /* correct top */ - /* else leave top for next instruction */ vmbreak; } vmcase(OP_TAILCALL) { @@ -1651,7 +1639,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) { setobjs2s(L, cb, ra); L->top = cb + 3; /* func. + 2 args (state and index) */ Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = ci->top; if (trap) /* keep 'base' correct for next instruction */ updatebase(ci); i = *(pc++); /* go to next instruction */ @@ -1686,7 +1673,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) { last--; luaC_barrierback(L, h, val); } - L->top = ci->top; /* correct top (in case of previous open call) */ vmbreak; } vmcase(OP_CLOSURE) {