diff --git a/lapi.c b/lapi.c index 6b6bc565..8750cefa 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.273 2017/11/02 11:28:56 roberto Exp roberto $ +** $Id: lapi.c,v 2.274 2017/11/03 12:12:30 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -948,8 +948,8 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, checkresults(L, nargs, nresults); func = L->top - (nargs+1); if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ + L->func->stkci.u.c.k = k; /* save continuation */ + L->func->stkci.u.c.ctx = ctx; /* save context */ luaD_call(L, func, nresults); /* do the call */ } else /* no continuation or no yieldable */ @@ -999,19 +999,19 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, status = luaD_pcall(L, f_call, &c, savestack(L, c.func), efunc); } else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; StkId func = L->func; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ + func->stkci.u.c.k = k; /* save continuation */ + func->stkci.u.c.ctx = ctx; /* save context */ /* save information for error recovery */ - ci->u2.funcidx = savestack(L, c.func); - ci->u.c.old_errfunc = L->errfunc; + func->stkci.u2.funcidx = c.func - func; + func->stkci.u.c.old_errfunc = L->errfunc; L->errfunc = efunc; setoah(callstatus(func), L->allowhook); /* save value of 'allowhook' */ callstatus(func) |= CIST_YPCALL; /* function can do error recovery */ luaD_call(L, c.func, nresults); /* do the call */ + func = L->func; /* previous call can reallocate stack */ callstatus(func) &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; + L->errfunc = func->stkci.u.c.old_errfunc; status = LUA_OK; /* if it is here, there were no errors */ } adjustresults(L, nresults); diff --git a/ldebug.c b/ldebug.c index 2db0910c..b212d875 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.135 2017/11/02 11:28:56 roberto Exp roberto $ +** $Id: ldebug.c,v 2.136 2017/11/03 12:12:30 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -44,7 +44,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, static int currentpc (CallInfo *ci) { lua_assert(isLua(ci->func)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); + return pcRel(ci->func->stkci.u.l.savedpc, ci_func(ci)->p); } @@ -121,7 +121,7 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { func = NULL; } if (isLua(L->func)) - L->oldpc = L->ci->u.l.savedpc; + L->oldpc = L->func->stkci.u.l.savedpc; L->hook = func; L->basehookcount = count; resethookcount(L); @@ -755,19 +755,21 @@ void luaG_traceexec (lua_State *L) { 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 npc = pcRel(func->stkci.u.l.savedpc, p); if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - changedline(p, pcRel(L->oldpc, p), npc)) { /* enter new line */ + func->stkci.u.l.savedpc <= L->oldpc || /* when jump back (loop), */ + changedline(p, pcRel(L->oldpc, p), npc)) { /* when enter new line */ int newline = luaG_getfuncline(p, npc); /* new line */ luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ } } - L->oldpc = ci->u.l.savedpc; + func = L->func; /* previous calls can reallocate stack */ + L->oldpc = func->stkci.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) */ + /* undo increment (resume will increment it again) */ + func->stkci.u.l.savedpc--; callstatus(func) |= CIST_HOOKYIELD; /* mark that it yielded */ luaD_throw(L, LUA_YIELD); } diff --git a/ldo.c b/ldo.c index cbb1e0f3..3b01c8fb 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 roberto Exp roberto $ +** $Id: ldo.c,v 2.166 2017/11/03 12:12:30 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -280,17 +280,19 @@ void luaD_hook (lua_State *L, int event, int line) { } -static void callhook (lua_State *L, CallInfo *ci) { +static void callhook (lua_State *L) { int hook = LUA_HOOKCALL; - StkId previous = L->func - L->func->stkci.previous; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + StkId func = L->func; + StkId previous = func - L->func->stkci.previous; + func->stkci.u.l.savedpc++; /* hooks assume 'pc' is already incremented */ if (isLua(previous) && - GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + GET_OPCODE(*(previous->stkci.u.l.savedpc - 1)) == OP_TAILCALL) { callstatus(L->func) |= CIST_TAIL; hook = LUA_HOOKTAILCALL; } luaD_hook(L, hook, -1); - ci->u.l.savedpc--; /* correct 'pc' */ + func = L->func; /* previous call can change stack */ + func->stkci.u.l.savedpc--; /* correct 'pc' */ } @@ -369,11 +371,13 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ luaD_hook(L, LUA_HOOKRET, -1); firstResult = restorestack(L, fr); + res = L->func; } - L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + /* 'oldpc' for caller function */ + L->oldpc = (res - res->stkci.previous)->stkci.u.l.savedpc; } L->ci = ci->previous; /* back to caller */ - L->func -= L->func->stkci.previous; + L->func = res - res->stkci.previous; lua_assert(L->func == L->ci->func); /* move results to proper place */ return moveresults(L, firstResult, res, nres, wanted); @@ -436,10 +440,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { L->func = ci->func = func; L->top = func + 1 + fsize; lua_assert(functop(func) <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ + func->stkci.u.l.savedpc = p->code; /* starting point */ callstatus(func) = 0; if (L->hookmask & LUA_MASKCALL) - callhook(L, ci); + callhook(L); return 0; } default: { /* not a function */ @@ -500,18 +504,19 @@ static void finishCcall (lua_State *L, int status) { StkId func = L->func; int n; /* must have a continuation and must be able to call it */ - lua_assert(ci->u.c.k != NULL && L->nny == 0); + lua_assert(func->stkci.u.c.k != NULL && L->nny == 0); /* error status can only happen in a protected call */ lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD); if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */ callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */ - L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ + L->errfunc = func->stkci.u.c.old_errfunc; /* with same error function */ } /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already handled */ adjustresults(L, func->stkci.nresults); lua_unlock(L); - n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ + /* call continuation function */ + n = (*func->stkci.u.c.k)(L, status, func->stkci.u.c.ctx); lua_lock(L); api_checknelems(L, n); luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ @@ -564,7 +569,7 @@ static int recover (lua_State *L, int status) { CallInfo *ci = findpcall(L); if (ci == NULL) return 0; /* no recovery point */ /* "finish" luaD_pcall */ - oldtop = restorestack(L, ci->u2.funcidx); + oldtop = ci->func + ci->func->stkci.u2.funcidx; luaF_close(L, oldtop); seterrorobj(L, status, oldtop); L->ci = ci; @@ -572,7 +577,7 @@ static int recover (lua_State *L, int status) { L->allowhook = getoah(callstatus(L->func)); /* restore original 'allowhook' */ L->nny = 0; /* should be zero to be yieldable */ luaD_shrinkstack(L); - L->errfunc = ci->u.c.old_errfunc; + L->errfunc = ci->func->stkci.u.c.old_errfunc; return 1; /* continue running the coroutine */ } @@ -602,6 +607,7 @@ static void resume (lua_State *L, void *ud) { int n = *(cast(int*, ud)); /* number of arguments */ StkId firstArg = L->top - n; /* first argument */ CallInfo *ci = L->ci; + StkId func = L->func; if (L->status == LUA_OK) { /* starting a coroutine? */ if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ luaV_execute(L); /* call it */ @@ -609,12 +615,13 @@ static void resume (lua_State *L, void *ud) { else { /* resuming from previous yield */ lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ - if (isLua(L->func)) /* yielded inside a hook? */ + if (isLua(func)) /* yielded inside a hook? */ luaV_execute(L); /* just continue running Lua code */ else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation function? */ + if (func->stkci.u.c.k != NULL) { /* does it have a continuation? */ lua_unlock(L); - n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + /* call continuation */ + n = (*func->stkci.u.c.k)(L, LUA_YIELD, func->stkci.u.c.ctx); lua_lock(L); api_checknelems(L, n); firstArg = L->top - n; /* yield results come from continuation */ @@ -658,7 +665,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, } else lua_assert(status == L->status); /* normal end or yield */ } - *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield + *nresults = (status == LUA_YIELD) ? L->func->stkci.u2.nyield : L->top - (L->func + 1); L->nny = oldnny; /* restore 'nny' */ L->nCcalls--; @@ -675,7 +682,6 @@ LUA_API int lua_isyieldable (lua_State *L) { LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k) { - CallInfo *ci = L->ci; StkId func = L->func; luai_userstateyield(L, nresults); lua_lock(L); @@ -689,12 +695,12 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, L->status = LUA_YIELD; if (isLua(func)) { /* inside a hook? */ api_check(L, k == NULL, "hooks cannot continue after yielding"); - ci->u2.nyield = 0; /* no results */ + func->stkci.u2.nyield = 0; /* no results */ } else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - ci->u2.nyield = nresults; /* save number of results */ + if ((func->stkci.u.c.k = k) != NULL) /* is there a continuation? */ + func->stkci.u.c.ctx = ctx; /* save context */ + func->stkci.u2.nyield = nresults; /* save number of results */ luaD_throw(L, LUA_YIELD); } lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ diff --git a/lobject.h b/lobject.h index 66c41e6f..925f958c 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.126 2017/10/31 17:54:35 roberto Exp roberto $ +** $Id: lobject.h,v 2.127 2017/11/03 12:12:30 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -314,9 +314,23 @@ typedef union StackValue { struct { TValuefields; lu_byte callstatus_; - unsigned short previous; /* difference to previous 'func' */ short nresults; /* expected number of results from this function */ + unsigned short previous; /* difference to previous 'func' */ unsigned short framesize; /* stack space available for this function */ + union { + unsigned short funcidx; /* called-function index */ + unsigned short nyield; /* number of values yielded */ + } u2; + union { + struct { /* only for Lua functions */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + lua_KFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lua_KContext ctx; /* context info. in case of yields */ + } c; + } u; } stkci; } StackValue; diff --git a/lstate.h b/lstate.h index 3d76e9b9..df1630ea 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.146 2017/11/02 11:28:56 roberto Exp roberto $ +** $Id: lstate.h,v 2.147 2017/11/03 12:12:30 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -87,20 +87,6 @@ typedef struct stringtable { typedef struct CallInfo { StkId func; /* function index in the stack */ struct CallInfo *previous, *next; /* dynamic call link */ - union { - struct { /* only for Lua functions */ - const Instruction *savedpc; - } l; - struct { /* only for C functions */ - lua_KFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lua_KContext ctx; /* context info. in case of yields */ - } c; - } u; - union { - ptrdiff_t funcidx; /* called-function index */ - int nyield; /* number of values yielded */ - } u2; } CallInfo; diff --git a/ltests.c b/ltests.c index 71ad09ea..ebf73840 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.227 2017/11/02 11:28:56 roberto Exp roberto $ +** $Id: ltests.c,v 2.228 2017/11/03 12:12:30 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -309,28 +309,26 @@ static void checkLclosure (global_State *g, LClosure *cl) { } -static int lua_checkpc (CallInfo *ci) { - if (!isLua(ci->func)) return 1; +static int lua_checkpc (StkId func) { + if (!isLua(func)) return 1; else { - StkId f = ci->func; - Proto *p = clLvalue(s2v(f))->p; - return p->code <= ci->u.l.savedpc && - ci->u.l.savedpc <= p->code + p->sizecode; + Proto *p = clLvalue(s2v(func))->p; + return p->code <= func->stkci.u.l.savedpc && + func->stkci.u.l.savedpc <= p->code + p->sizecode; } } static void checkstack (global_State *g, lua_State *L1) { StkId o; - CallInfo *ci; UpVal *uv; lua_assert(!isdead(g, L1)); for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) lua_assert(upisopen(uv)); /* must be open */ - for (ci = L1->ci; ci != NULL; ci = ci->previous) - lua_assert(lua_checkpc(ci)); - for (o = L1->func; o->stkci.previous != 0; o -= o->stkci.previous) + for (o = L1->func; o->stkci.previous != 0; o -= o->stkci.previous) { lua_assert(functop(o) <= L1->stack_last); + lua_assert(lua_checkpc(o)); + } lua_assert(o == L1->stack); if (L1->stack) { /* complete thread? */ for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) diff --git a/lvm.c b/lvm.c index 7acb387f..ce15d61b 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 roberto Exp roberto $ +** $Id: lvm.c,v 2.302 2017/11/03 12:12:30 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -654,13 +654,14 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, } +#define basepc(base) ((base - 1)->stkci.u.l.savedpc) + /* ** finish execution of an opcode interrupted by an yield */ void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; StkId base = L->func + 1; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + Instruction inst = *(basepc(base) - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ case OP_ADDI: case OP_SUBI: @@ -684,9 +685,9 @@ void luaV_finishOp (lua_State *L) { callstatus(base - 1) ^= CIST_LEQ; /* clear mark */ res = !res; /* negate result */ } - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + lua_assert(GET_OPCODE(*basepc(base)) == OP_JMP); if (res != GETARG_A(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ + basepc(base)++; /* skip jump instruction */ break; } case OP_CONCAT: { @@ -704,7 +705,7 @@ void luaV_finishOp (lua_State *L) { break; } case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + lua_assert(GET_OPCODE(*basepc(base)) == OP_TFORLOOP); L->top = functop(base - 1); /* correct top */ break; } @@ -763,20 +764,22 @@ void luaV_finishOp (lua_State *L) { ** Whenever code can raise errors (including memory errors), the global ** 'pc' must be correct to report occasional errors. */ -#define savepc(L) (ci->u.l.savedpc = pc) +#define savepc(base) (basepc(base) = pc) +/* update internal copies to its correct values */ +#define updatestate() (base = L->func + 1, updatemask(L)) + /* ** Protect code that, in general, can raise errors, reallocate the ** stack, and change the hooks. */ -#define Protect(code) \ - { savepc(L); {code;}; base = L->func + 1; updatemask(L); } +#define Protect(code) { savepc(base); {code;}; updatestate(); } #define checkGC(L,c) \ { luaC_condGC(L, L->top = (c), /* limit of live values */ \ - {Protect((void)0); L->top = functop(base - 1);}); /* restore top */ \ + {updatestate(); L->top = functop(base - 1);}); /* restore top */ \ luai_threadyield(L); } @@ -798,14 +801,14 @@ void luaV_execute (lua_State *L) { TValue *k; StkId base = L->func + 1; /* local copy of 'L->func + 1' */ int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ - const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ + const Instruction *pc; /* local copy of 'basepc(base)' */ callstatus(base - 1) |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ newframe: /* reentry point when frame changes (call/return) */ lua_assert(ci == L->ci); cl = clLvalue(s2v(L->func)); /* local reference to function's closure */ k = cl->p->k; /* local reference to function's constant table */ updatemask(L); - pc = ci->u.l.savedpc; + pc = basepc(base); /* main loop of interpreter */ for (;;) { Instruction i; @@ -969,7 +972,7 @@ void luaV_execute (lua_State *L) { int b = GETARG_B(i); int c = GETARG_C(i); Table *t; - savepc(L); /* in case of allocation errors */ + savepc(base); /* in case of allocation errors */ t = luaH_new(L); sethvalue2s(L, ra, t); if (b != 0 || c != 0) @@ -1368,9 +1371,9 @@ void luaV_execute (lua_State *L) { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - savepc(L); + savepc(base); if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ - Protect((void)0); /* update 'base' */ + updatestate(); /* update 'base' */ } else { /* tail call: put called frame (n) in place of caller one (o) */ @@ -1388,7 +1391,7 @@ void luaV_execute (lua_State *L) { setobjs2s(L, ofunc + aux, nfunc + aux); ofunc->stkci.framesize = L->top - nfunc; L->top = functop(ofunc); /* correct top */ - oci->u.l.savedpc = nci->u.l.savedpc; + ofunc->stkci.u.l.savedpc = nfunc->stkci.u.l.savedpc; callstatus(ofunc) |= CIST_TAIL; /* function was tail called */ ci = L->ci = oci; /* remove new frame */ base = ofunc + 1; @@ -1401,7 +1404,7 @@ void luaV_execute (lua_State *L) { vmcase(OP_RETURN) { int b = GETARG_B(i); if (cl->p->sizep > 0) luaF_close(L, base); - savepc(L); + savepc(base); b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); if (callstatus(base - 1) & CIST_FRESH) /* local 'base' still from callee */ return; /* external invocation: return */ @@ -1409,8 +1412,8 @@ void luaV_execute (lua_State *L) { ci = L->ci; base = L->func + 1; if (b) L->top = functop(base - 1); - lua_assert(isLua(L->func)); - lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + lua_assert(isLua(base - 1)); + lua_assert(GET_OPCODE(*(basepc(base) - 1)) == OP_CALL); goto newframe; /* restart luaV_execute over previous Lua function */ } } @@ -1455,7 +1458,7 @@ void luaV_execute (lua_State *L) { } else { /* try making all values floats */ lua_Number ninit; lua_Number nlimit; lua_Number nstep; - savepc(L); /* in case of errors */ + savepc(base); /* in case of errors */ if (!tonumber(plimit, &nlimit)) luaG_runerror(L, "'for' limit must be a number"); setfltvalue(plimit, nlimit); @@ -1501,7 +1504,7 @@ void luaV_execute (lua_State *L) { } h = hvalue(s2v(ra)); last = ((c-1)*LFIELDS_PER_FLUSH) + n; - savepc(L); /* in case of allocation errors */ + savepc(base); /* in case of allocation errors */ if (last > h->sizearray) /* needs more space? */ luaH_resizearray(L, h, last); /* preallocate it at once */ for (; n > 0; n--) { @@ -1518,7 +1521,7 @@ void luaV_execute (lua_State *L) { Proto *p = cl->p->p[GETARG_Bx(i)]; LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ if (ncl == NULL) { /* no match? */ - savepc(L); /* in case of allocation errors */ + savepc(base); /* in case of allocation errors */ pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ } else