From 54eb35a8aa0f60265cf1b4764beabe1199d66f42 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 3 Nov 2017 10:12:30 -0200 Subject: more fields moved out of 'CallInfo' --- lapi.c | 45 +++++++++++++++++++---------------- lapi.h | 7 +++--- ldebug.c | 29 ++++++++++++----------- ldo.c | 80 ++++++++++++++++++++++++++++++++++----------------------------- lgc.c | 6 ++--- lobject.h | 13 ++++++++++- lstate.c | 6 ++--- lstate.h | 22 +++++++----------- ltests.c | 11 +++++---- ltm.c | 6 ++--- lvm.c | 54 ++++++++++++++++++++++-------------------- 11 files changed, 152 insertions(+), 127 deletions(-) diff --git a/lapi.c b/lapi.c index 8d4d5e7d..6b6bc565 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.272 2017/11/01 18:20:48 roberto Exp roberto $ +** $Id: lapi.c,v 2.273 2017/11/02 11:28:56 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -10,6 +10,7 @@ #include "lprefix.h" +#include #include #include @@ -60,12 +61,12 @@ const char lua_ident[] = static TValue *index2value (lua_State *L, int idx) { if (idx > 0) { StkId o = L->func + idx; - api_check(L, idx <= L->ci->top - (L->func + 1), "unacceptable index"); + api_check(L, idx < L->func->stkci.framesize, "unacceptable index"); if (o >= L->top) return NONVALIDVALUE; else return s2v(o); } else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (L->func + 1), "invalid index"); + api_check(L, idx != 0 && -idx < L->func->stkci.framesize, "invalid index"); return s2v(L->top + idx); } else if (idx == LUA_REGISTRYINDEX) @@ -109,10 +110,12 @@ static void growstack (lua_State *L, void *ud) { LUA_API int lua_checkstack (lua_State *L, int n) { int res; - CallInfo *ci = L->ci; + int frameuse = L->top - L->func; lua_lock(L); api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ + if (n >= USHRT_MAX - frameuse) + res = 0; /* frame size overflow */ + else if (L->stack_last - L->top > n) /* stack large enough? */ res = 1; /* yes; check is OK */ else { /* no; need to grow stack */ int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; @@ -121,8 +124,8 @@ LUA_API int lua_checkstack (lua_State *L, int n) { else /* try to grow stack */ res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ + if (res && L->func->stkci.framesize < frameuse + n) + L->func->stkci.framesize = frameuse + n; /* adjust frame size */ lua_unlock(L); return res; } @@ -134,7 +137,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); + api_check(from, functop(to->func) - to->top >= n, "stack overflow"); from->top -= n; for (i = 0; i < n; i++) { setobjs2s(to, to->top, from->top + i); @@ -929,15 +932,16 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ - "results from function overflow current stack size") + api_check(L, (nr) == LUA_MULTRET || \ + (functop(L->func) - L->top >= (nr) - (na)), \ + "results from function overflow current frame size") LUA_API void lua_callk (lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) { StkId func; lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), + api_check(L, k == NULL || !isLua(L->func), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); @@ -976,36 +980,37 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) { struct CallS c; int status; - ptrdiff_t func; + ptrdiff_t efunc; lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), + api_check(L, k == NULL || !isLua(L->func), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) - func = 0; + efunc = 0; else { StkId o = index2stack(L, errfunc); - func = savestack(L, o); + efunc = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + 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 */ /* save information for error recovery */ ci->u2.funcidx = savestack(L, c.func); ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ - ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + 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 */ - ci->callstatus &= ~CIST_YPCALL; + callstatus(func) &= ~CIST_YPCALL; L->errfunc = ci->u.c.old_errfunc; status = LUA_OK; /* if it is here, there were no errors */ } diff --git a/lapi.h b/lapi.h index ce64a727..d851d161 100644 --- a/lapi.h +++ b/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp roberto $ +** $Id: lapi.h,v 2.10 2017/11/01 18:20:48 roberto Exp roberto $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -11,11 +11,12 @@ #include "llimits.h" #include "lstate.h" -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ +#define api_incr_top(L) {L->top++; api_check(L, L->top <= functop(L->func), \ "stack overflow");} #define adjustresults(L,nres) \ - { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + { if ((nres) == LUA_MULTRET && functop(L->func) < L->top) \ + setfunctop(L->func, L->top); } #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->func), \ "not enough elements in the stack") diff --git a/ldebug.c b/ldebug.c index 5ca78bd1..2db0910c 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.134 2017/11/01 18:20:48 roberto Exp roberto $ +** $Id: ldebug.c,v 2.135 2017/11/02 11:28:56 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -43,7 +43,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); + lua_assert(isLua(ci->func)); return pcRel(ci->u.l.savedpc, ci_func(ci)->p); } @@ -120,7 +120,7 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { mask = 0; func = NULL; } - if (isLua(L->ci)) + if (isLua(L->func)) L->oldpc = L->ci->u.l.savedpc; L->hook = func; L->basehookcount = count; @@ -172,7 +172,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { const char *name = NULL; StkId base; - if (isLua(ci)) { + if (isLua(ci->func)) { base = ci->func + 1; name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); } @@ -277,12 +277,12 @@ static void collectvalidlines (lua_State *L, Closure *f) { static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { if (ci == NULL) /* no 'ci'? */ return NULL; /* no info */ - else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ + else if (callstatus(ci->func) & CIST_FIN) { /* is this a finalizer? */ *name = "__gc"; return "metamethod"; /* report it as such */ } /* calling function is a known Lua function? */ - else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + else if (!(callstatus(ci->func) & CIST_TAIL) && isLua(ci->previous->func)) return funcnamefromcode(L, ci->previous, name); else return NULL; /* no way to find a name */ } @@ -298,7 +298,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'l': { - ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + ar->currentline = (ci && isLua(ci->func)) ? currentline(ci) : -1; break; } case 'u': { @@ -314,7 +314,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + ar->istailcall = (ci) ? callstatus(ci->func) & CIST_TAIL : 0; break; } case 'n': { @@ -549,7 +549,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, Proto *p = ci_func(ci)->p; /* calling function */ int pc = currentpc(ci); /* calling instruction index */ Instruction i = p->code[pc]; /* calling instruction */ - if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ + if (callstatus(ci->func) & CIST_HOOKED) { /* was it called inside a hook? */ *name = "?"; return "hook"; } @@ -635,7 +635,7 @@ static const char *varinfo (lua_State *L, const TValue *o) { const char *name = NULL; /* to avoid warnings */ CallInfo *ci = L->ci; const char *kind = NULL; - if (isLua(ci)) { + if (isLua(L->func)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ if (!kind && isinstack(L, o)) /* no? try a register */ kind = getobjname(ci_func(ci)->p, currentpc(ci), @@ -719,7 +719,7 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ + if (isLua(L->func)) /* if Lua function, add source:line information */ luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); luaG_errormsg(L); } @@ -740,14 +740,15 @@ static int changedline (Proto *p, int oldpc, int newpc) { void luaG_traceexec (lua_State *L) { CallInfo *ci = L->ci; + StkId func = L->func; lu_byte mask = L->hookmask; int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); if (counthook) resethookcount(L); /* reset count */ else if (!(mask & LUA_MASKLINE)) return; /* no line hook and count != 0; nothing to be done */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + if (callstatus(func) & CIST_HOOKYIELD) { /* called hook last time? */ + callstatus(func) &= ~CIST_HOOKYIELD; /* erase mark */ return; /* do not call hook again (VM yielded, so it did not move) */ } if (counthook) @@ -767,7 +768,7 @@ void luaG_traceexec (lua_State *L) { 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 */ + callstatus(func) |= CIST_HOOKYIELD; /* mark that it yielded */ luaD_throw(L, LUA_YIELD); } } diff --git a/ldo.c b/ldo.c index 8c2fca13..cbb1e0f3 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.164 2017/11/01 18:20:48 roberto Exp roberto $ +** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -123,8 +123,8 @@ l_noret luaD_throw (lua_State *L, int errcode) { else { /* no handler at all; abort */ if (g->panic) { /* panic function? */ seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ - if (L->ci->top < L->top) - L->ci->top = L->top; /* pushing msg. can break this invariant */ + if (functop(L->func) < L->top) /* check invariant */ + setfunctop(L->func, L->top); lua_unlock(L); g->panic(L); /* call panic function (last chance to jump out) */ } @@ -164,7 +164,6 @@ static void correctstack (lua_State *L, StkId oldstack) { for (up = L->openupval; up != NULL; up = up->u.open.next) up->v = s2v((uplevel(up) - oldstack) + L->stack); for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; } } @@ -208,10 +207,11 @@ void luaD_growstack (lua_State *L, int n) { static int stackinuse (lua_State *L) { - CallInfo *ci; StkId lim = L->top; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; + StkId func = L->func; + for (; func->stkci.previous != 0; func -= func->stkci.previous) { + if (lim < functop(func)) + lim = functop(func); } lua_assert(lim <= L->stack_last); return cast_int(lim - L->stack) + 1; /* part of stack in use */ @@ -255,34 +255,38 @@ void luaD_hook (lua_State *L, int event, int line) { if (hook && L->allowhook) { /* make sure there is a hook */ CallInfo *ci = L->ci; ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, ci->top); + int origframesize = L->func->stkci.framesize; + int tmpframesize; /* frame size to run hook */ lua_Debug ar; ar.event = event; ar.currentline = line; ar.i_ci = ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); + tmpframesize = L->top - L->func + LUA_MINSTACK; + if (tmpframesize > origframesize) /* need to grow frame? */ + L->func->stkci.framesize = tmpframesize; + lua_assert(functop(L->func) <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= CIST_HOOKED; + callstatus(L->func) |= CIST_HOOKED; lua_unlock(L); (*hook)(L, &ar); lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - ci->top = restorestack(L, ci_top); + L->func->stkci.framesize = origframesize; L->top = restorestack(L, top); - ci->callstatus &= ~CIST_HOOKED; + callstatus(L->func) &= ~CIST_HOOKED; } } static void callhook (lua_State *L, CallInfo *ci) { int hook = LUA_HOOKCALL; + StkId previous = L->func - L->func->stkci.previous; ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - if (isLua(ci->previous) && + if (isLua(previous) && GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { - ci->callstatus |= CIST_TAIL; + callstatus(L->func) |= CIST_TAIL; hook = LUA_HOOKTAILCALL; } luaD_hook(L, hook, -1); @@ -358,8 +362,8 @@ static int moveresults (lua_State *L, StkId firstResult, StkId res, ** wanted multiple (variable number of) results. */ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { - StkId res; - int wanted = ci->nresults; + StkId res = L->func; /* res == final position of 1st result */ + int wanted = res->stkci.nresults; if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { if (L->hookmask & LUA_MASKRET) { ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ @@ -368,7 +372,6 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { } L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ } - res = L->func; /* res == final position of 1st result */ L->ci = ci->previous; /* back to caller */ L->func -= L->func->stkci.previous; lua_assert(L->func == L->ci->func); @@ -402,12 +405,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { int n; /* number of returns */ checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; + func->stkci.nresults = nresults; func->stkci.previous = func - L->func; L->func = ci->func = func; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; + setfunctop(func, L->top + LUA_MINSTACK); + lua_assert(functop(func) <= L->stack_last); + callstatus(func) = 0; if (L->hookmask & LUA_MASKCALL) luaD_hook(L, LUA_HOOKCALL, -1); lua_unlock(L); @@ -427,13 +430,14 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { if (p->is_vararg) luaT_adjustvarargs(L, p, n); ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; + func->stkci.nresults = nresults; func->stkci.previous = func - L->func; + func->stkci.framesize = fsize + 1; /* size includes function itself */ L->func = ci->func = func; - L->top = ci->top = func + 1 + fsize; - lua_assert(ci->top <= L->stack_last); + L->top = func + 1 + fsize; + lua_assert(functop(func) <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = CIST_LUA; + callstatus(func) = 0; if (L->hookmask & LUA_MASKCALL) callhook(L, ci); return 0; @@ -493,18 +497,19 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { */ static void finishCcall (lua_State *L, int status) { CallInfo *ci = L->ci; + 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); /* error status can only happen in a protected call */ - lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); - if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ - ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ + 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 */ } /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already handled */ - adjustresults(L, ci->nresults); + adjustresults(L, func->stkci.nresults); lua_unlock(L); n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ lua_lock(L); @@ -525,7 +530,7 @@ static void unroll (lua_State *L, void *ud) { if (ud != NULL) /* error status? */ finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ while (L->ci != &L->base_ci) { /* something in the stack */ - if (!isLua(L->ci)) /* C function? */ + if (!isLua(L->func)) /* C function? */ finishCcall(L, LUA_YIELD); /* complete its execution */ else { /* Lua function */ luaV_finishOp(L); /* finish interrupted instruction */ @@ -542,7 +547,7 @@ static void unroll (lua_State *L, void *ud) { static CallInfo *findpcall (lua_State *L) { CallInfo *ci; for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) + if (callstatus(ci->func) & CIST_YPCALL) return ci; } return NULL; /* no pending pcall */ @@ -564,7 +569,7 @@ static int recover (lua_State *L, int status) { seterrorobj(L, status, oldtop); L->ci = ci; L->func = ci->func; - L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ + 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; @@ -604,7 +609,7 @@ 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(ci)) /* yielded inside a hook? */ + if (isLua(L->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? */ @@ -649,7 +654,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, if (errorstatus(status)) { /* unrecoverable error? */ L->status = cast_byte(status); /* mark thread as 'dead' */ seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; + L->func->stkci.framesize = L->top - L->func; } else lua_assert(status == L->status); /* normal end or yield */ } @@ -671,6 +676,7 @@ 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); api_checknelems(L, nresults); @@ -681,7 +687,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, luaG_runerror(L, "attempt to yield from outside a coroutine"); } L->status = LUA_YIELD; - if (isLua(ci)) { /* inside a hook? */ + if (isLua(func)) { /* inside a hook? */ api_check(L, k == NULL, "hooks cannot continue after yielding"); ci->u2.nyield = 0; /* no results */ } @@ -691,7 +697,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, ci->u2.nyield = nresults; /* save number of results */ luaD_throw(L, LUA_YIELD); } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ lua_unlock(L); return 0; /* return to 'luaD_hook' */ } diff --git a/lgc.c b/lgc.c index d9b31958..2155b28d 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.235 2017/10/11 12:38:45 roberto Exp roberto $ +** $Id: lgc.c,v 2.236 2017/10/31 15:29:28 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -866,9 +866,9 @@ static void GCTM (lua_State *L, int propagateerrors) { setobj2s(L, L->top, tm); /* push finalizer... */ setobj2s(L, L->top + 1, &v); /* ... and its argument */ L->top += 2; /* and (next line) call the finalizer */ - L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ + callstatus(L->func) |= CIST_FIN; /* will run a finalizer */ status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); - L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ + callstatus(L->func) &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ g->gcrunning = running; /* restore state */ if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ diff --git a/lobject.h b/lobject.h index e3ae0050..66c41e6f 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.125 2017/06/29 15:06:44 roberto Exp roberto $ +** $Id: lobject.h,v 2.126 2017/10/31 17:54:35 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -313,10 +313,21 @@ typedef union StackValue { TValue val; struct { TValuefields; + lu_byte callstatus_; unsigned short previous; /* difference to previous 'func' */ + short nresults; /* expected number of results from this function */ + unsigned short framesize; /* stack space available for this function */ } stkci; } StackValue; +#define callstatus(ar) ((ar)->stkci.callstatus_) + +/* top of a function (first element after its frame) */ +#define functop(func) ((func) + (func)->stkci.framesize) + +/* set top of a function to a specific value */ +#define setfunctop(func,v) ((func)->stkci.framesize = (v) - (func)) + typedef StackValue *StkId; /* index to stack elements */ diff --git a/lstate.c b/lstate.c index c4305ed8..8e3177ca 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.142 2017/10/11 12:38:45 roberto Exp roberto $ +** $Id: lstate.c,v 2.143 2017/10/31 17:54:35 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -152,12 +152,12 @@ static void stack_init (lua_State *L1, lua_State *L) { /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; - ci->callstatus = 0; L1->func = ci->func = L1->top; L1->func->stkci.previous = 0; /* end of linked list */ + L1->func->stkci.framesize = LUA_MINSTACK + 1; + callstatus(L1->func) = 0; setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ L1->top++; - ci->top = L1->top + LUA_MINSTACK; L1->ci = ci; } diff --git a/lstate.h b/lstate.h index 8b9eb606..3d76e9b9 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.145 2017/10/31 17:54:35 roberto Exp roberto $ +** $Id: lstate.h,v 2.146 2017/11/02 11:28:56 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -86,7 +86,6 @@ typedef struct stringtable { */ typedef struct CallInfo { StkId func; /* function index in the stack */ - StkId top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ union { struct { /* only for Lua functions */ @@ -102,8 +101,6 @@ typedef struct CallInfo { ptrdiff_t funcidx; /* called-function index */ int nyield; /* number of values yielded */ } u2; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; } CallInfo; @@ -111,17 +108,16 @@ typedef struct CallInfo { ** Bits in CallInfo status */ #define CIST_OAH (1<<0) /* original value of 'allowhook' */ -#define CIST_LUA (1<<1) /* call is running a Lua function */ -#define CIST_HOOKED (1<<2) /* call is running a debug hook */ -#define CIST_FRESH (1<<3) /* call is running on a fresh invocation +#define CIST_HOOKED (1<<1) /* call is running a debug hook */ +#define CIST_FRESH (1<<2) /* call is running on a fresh invocation of luaV_execute */ -#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ -#define CIST_TAIL (1<<5) /* call was tail called */ -#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ -#define CIST_LEQ (1<<7) /* using __lt for __le */ -#define CIST_FIN (1<<8) /* call is running a finalizer */ +#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */ +#define CIST_TAIL (1<<4) /* call was tail called */ +#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */ +#define CIST_LEQ (1<<6) /* using __lt for __le */ +#define CIST_FIN (1<<7) /* call is running a finalizer */ -#define isLua(ci) ((ci)->callstatus & CIST_LUA) +#define isLua(func) isLfunction(s2v(func)) /* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) diff --git a/ltests.c b/ltests.c index d05fc3b1..71ad09ea 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.226 2017/11/01 18:20:48 roberto Exp roberto $ +** $Id: ltests.c,v 2.227 2017/11/02 11:28:56 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -310,7 +310,7 @@ static void checkLclosure (global_State *g, LClosure *cl) { static int lua_checkpc (CallInfo *ci) { - if (!isLua(ci)) return 1; + if (!isLua(ci->func)) return 1; else { StkId f = ci->func; Proto *p = clLvalue(s2v(f))->p; @@ -327,10 +327,11 @@ static void checkstack (global_State *g, lua_State *L1) { 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(ci->top <= L1->stack_last); + 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) + lua_assert(functop(o) <= L1->stack_last); + lua_assert(o == L1->stack); if (L1->stack) { /* complete thread? */ for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) checkliveness(L1, s2v(o)); /* entire stack must have valid values */ diff --git a/ltm.c b/ltm.c index 1534992b..6c13e8d1 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.44 2017/09/27 18:59:08 roberto Exp roberto $ +** $Id: ltm.c,v 2.45 2017/10/04 15:49:05 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -108,7 +108,7 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, setobj2s(L, func + 3, p3); /* 3rd argument */ L->top += 4; /* metamethod may yield only when called from Lua code */ - if (isLua(L->ci)) + if (isLua(L->func)) luaD_call(L, func, 0); else luaD_callnoyield(L, func, 0); @@ -124,7 +124,7 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, setobj2s(L, func + 2, p2); /* 2nd argument */ L->top += 3; /* metamethod may yield only when called from Lua code */ - if (isLua(L->ci)) + if (isLua(L->func)) luaD_call(L, func, 1); else luaD_callnoyield(L, func, 1); diff --git a/lvm.c b/lvm.c index 25b953a4..7acb387f 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.300 2017/10/31 17:54:35 roberto Exp roberto $ +** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -390,9 +390,9 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ return res; else { /* try 'lt': */ - L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + callstatus(L->func) |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ res = luaT_callorderTM(L, r, l, TM_LT); - L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + callstatus(L->func) ^= CIST_LEQ; /* clear mark */ if (res < 0) luaG_ordererror(L, l, r); return !res; /* result is negated */ @@ -679,9 +679,9 @@ void luaV_finishOp (lua_State *L) { case OP_LE: case OP_LT: case OP_EQ: { int res = !l_isfalse(s2v(L->top - 1)); L->top--; - if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + if (callstatus(base - 1) & CIST_LEQ) { /* "<=" using "<" ? */ lua_assert(op == OP_LE); - ci->callstatus ^= CIST_LEQ; /* clear mark */ + callstatus(base - 1) ^= CIST_LEQ; /* clear mark */ res = !res; /* negate result */ } lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); @@ -700,17 +700,17 @@ void luaV_finishOp (lua_State *L) { } /* move final result to final position */ setobjs2s(L, L->func + 1 + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ + L->top = functop(base - 1); /* restore top */ break; } case OP_TFORCALL: { lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ + L->top = functop(base - 1); /* correct top */ break; } case OP_CALL: { if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ + L->top = functop(base - 1); /* adjust results */ break; } case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: @@ -775,9 +775,9 @@ void luaV_finishOp (lua_State *L) { #define checkGC(L,c) \ - { luaC_condGC(L, L->top = (c), /* limit of live values */ \ - Protect(L->top = ci->top)); /* restore top */ \ - luai_threadyield(L); } + { luaC_condGC(L, L->top = (c), /* limit of live values */ \ + {Protect((void)0); L->top = functop(base - 1);}); /* restore top */ \ + luai_threadyield(L); } /* fetch an instruction and prepare its execution */ @@ -796,16 +796,15 @@ void luaV_execute (lua_State *L) { CallInfo *ci = L->ci; LClosure *cl; TValue *k; - StkId base; /* local copy of 'L->func + 1' */ + 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' */ - ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ + 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); - base = L->func + 1; pc = ci->u.l.savedpc; /* main loop of interpreter */ for (;;) { @@ -1276,7 +1275,7 @@ void luaV_execute (lua_State *L) { rb = base + b; setobjs2s(L, ra, rb); checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ + L->top = functop(base - 1); /* restore top */ vmbreak; } vmcase(OP_CLOSE) { @@ -1355,11 +1354,12 @@ void luaV_execute (lua_State *L) { Protect(isC = luaD_precall(L, ra, nresults)); if (isC) { /* C function? */ if (nresults >= 0) /* fixed number of results? */ - L->top = ci->top; /* correct top */ + L->top = functop(base - 1); /* correct top */ /* else leave top for next instruction */ } else { /* Lua function */ ci = L->ci; + base = L->func + 1; goto newframe; /* restart luaV_execute over new Lua function */ } vmbreak; @@ -1386,12 +1386,14 @@ void luaV_execute (lua_State *L) { /* move new frame into old one */ for (aux = 0; nfunc + aux < lim; aux++) setobjs2s(L, ofunc + aux, nfunc + aux); - oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + ofunc->stkci.framesize = L->top - nfunc; + L->top = functop(ofunc); /* correct top */ oci->u.l.savedpc = nci->u.l.savedpc; - oci->callstatus |= CIST_TAIL; /* function was tail called */ + callstatus(ofunc) |= CIST_TAIL; /* function was tail called */ ci = L->ci = oci; /* remove new frame */ + base = ofunc + 1; L->func = ofunc; - lua_assert(L->top == ofunc + 1 + getproto(s2v(ofunc))->maxstacksize); + lua_assert(L->top == base + getproto(s2v(ofunc))->maxstacksize); goto newframe; /* restart luaV_execute over new Lua function */ } vmbreak; @@ -1401,14 +1403,15 @@ void luaV_execute (lua_State *L) { if (cl->p->sizep > 0) luaF_close(L, base); savepc(L); 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 (callstatus(base - 1) & CIST_FRESH) /* local 'base' still from callee */ return; /* external invocation: return */ else { /* invocation via reentry: continue execution */ ci = L->ci; - if (b) L->top = ci->top; - lua_assert(isLua(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); - goto newframe; /* restart luaV_execute over new Lua function */ + goto newframe; /* restart luaV_execute over previous Lua function */ } } vmcase(OP_FORLOOP) { @@ -1473,7 +1476,7 @@ void luaV_execute (lua_State *L) { 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; + L->top = functop(base - 1); i = *(pc++); /* go to next instruction */ ra = RA(i); lua_assert(GET_OPCODE(i) == OP_TFORLOOP); @@ -1507,7 +1510,8 @@ void luaV_execute (lua_State *L) { last--; luaC_barrierback(L, h, val); } - L->top = ci->top; /* correct top (in case of previous open call) */ + /* correct top (in case of previous open call) */ + L->top = functop(base - 1); vmbreak; } vmcase(OP_CLOSURE) { -- cgit v1.2.3-55-g6feb