From d3037d97ec192e7719de485f15dacb473bf96528 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 17 Apr 2009 19:00:01 -0300 Subject: [PATCH] several small improvements based on 'ci' being fixed now (including erasing savedpc from lua_State) --- lapi.c | 19 +++---- ldebug.c | 8 ++- ldo.c | 52 +++++++++---------- lstate.c | 3 +- lstate.h | 5 +- ltests.c | 26 +++++----- ltests.h | 3 +- lvm.c | 155 ++++++++++++++++++++++++++++--------------------------- 8 files changed, 133 insertions(+), 138 deletions(-) diff --git a/lapi.c b/lapi.c index 0e3ef071..69307a3c 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.74 2009/04/08 18:04:33 roberto Exp roberto $ +** $Id: lapi.c,v 2.75 2009/04/17 14:28:06 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -829,18 +829,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), func); } else { /* prepare continuation (call is already protected by 'resume') */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ /* save information for error recovery */ - L->ci->u.c.oldtop = savestack(L, c.func); - L->ci->u.c.old_allowhook = L->allowhook; - L->ci->u.c.old_errfunc = L->errfunc; + ci->u.c.oldtop = savestack(L, c.func); + ci->u.c.old_allowhook = L->allowhook; + ci->u.c.old_errfunc = L->errfunc; L->errfunc = func; /* mark that function may do error recovery */ - L->ci->callstatus |= CIST_YPCALL; + ci->callstatus |= CIST_YPCALL; luaD_call(L, c.func, nresults, 1); /* do the call */ - L->ci->callstatus &= ~CIST_YPCALL; - L->errfunc = L->ci->u.c.old_errfunc; + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->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 bcb7eaf3..629d040b 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.45 2009/03/26 12:56:38 roberto Exp roberto $ +** $Id: ldebug.c,v 2.46 2009/04/17 14:28:06 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -35,9 +35,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); static int currentpc (lua_State *L, CallInfo *ci) { if (!isLua(ci)) return -1; /* function is not a Lua function? */ - if (ci == L->ci) - ci->savedpc = L->savedpc; - return pcRel(ci->savedpc, ci_func(ci)->l.p); + return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); } @@ -58,7 +56,7 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { mask = 0; func = NULL; } - L->oldpc = L->savedpc; + L->oldpc = NULL; L->hook = func; L->basehookcount = count; resethookcount(L); diff --git a/ldo.c b/ldo.c index 1a051222..040b8cdb 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.59 2009/04/15 16:53:39 roberto Exp roberto $ +** $Id: ldo.c,v 2.60 2009/04/17 14:28:06 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -151,28 +151,29 @@ void luaD_growstack (lua_State *L, int n) { void luaD_callhook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; if (hook && L->allowhook) { + CallInfo *ci = L->ci; ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); + ptrdiff_t ci_top = savestack(L, ci->top); lua_Debug ar; ar.event = event; ar.currentline = line; if (event == LUA_HOOKTAILRET) ar.i_ci = NULL; /* tail call; no debug information about it */ else - ar.i_ci = L->ci; + ar.i_ci = ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - L->ci->top = L->top + LUA_MINSTACK; - lua_assert(L->ci->top <= L->stack_last); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ - L->ci->callstatus |= CIST_HOOKED; + ci->callstatus |= CIST_HOOKED; lua_unlock(L); (*hook)(L, &ar); lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - L->ci->top = restorestack(L, ci_top); + ci->top = restorestack(L, ci_top); L->top = restorestack(L, top); - L->ci->callstatus &= ~CIST_HOOKED; + ci->callstatus &= ~CIST_HOOKED; } } @@ -223,7 +224,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { func = tryfuncTM(L, func); /* check the `function' tag method */ funcr = savestack(L, func); cl = &clvalue(func)->l; - L->ci->savedpc = L->savedpc; L->ci->nresults = nresults; if (!cl->isC) { /* Lua function? prepare its call */ CallInfo *ci; @@ -243,16 +243,16 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { L->base = ci->base = base; ci->top = L->base + p->maxstacksize; lua_assert(ci->top <= L->stack_last); - L->savedpc = p->code; /* starting point */ + ci->u.l.savedpc = p->code; /* starting point */ ci->u.l.tailcalls = 0; ci->callstatus = CIST_LUA; for (st = L->top; st < ci->top; st++) setnilvalue(st); L->top = ci->top; if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ luaD_callhook(L, LUA_HOOKCALL, -1); - L->savedpc--; /* correct 'pc' */ + ci->u.l.savedpc--; /* correct 'pc' */ } return 0; } @@ -295,13 +295,12 @@ int luaD_poscall (lua_State *L, StkId firstResult) { if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { if (L->hookmask & LUA_MASKRET) firstResult = callrethooks(L, firstResult); - L->oldpc = L->ci->previous->savedpc; /* 'oldpc' for returning function */ + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for returning function */ } res = ci->func; /* res == final position of 1st result */ - L->ci = ci = L->ci->previous; /* back to caller */ + L->ci = ci = ci->previous; /* back to caller */ wanted = ci->nresults; L->base = ci->base; /* restore base */ - L->savedpc = ci->savedpc; /* restore savedpc */ /* move results to correct place */ for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); @@ -336,21 +335,21 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { static void finishCcall (lua_State *L) { + CallInfo *ci = L->ci; int n; - lua_assert(L->ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ lua_assert(L->nny == 0); /* finish 'luaD_call' */ G(L)->nCcalls--; /* finish 'lua_callk' */ - adjustresults(L, L->ci->nresults); + adjustresults(L, ci->nresults); /* call continuation function */ - if (!(L->ci->callstatus & CIST_STAT)) /* no call status? */ - L->ci->u.c.status = LUA_YIELD; /* 'default' status */ - lua_assert(L->ci->u.c.status != LUA_OK); - L->ci->callstatus = (L->ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) - | CIST_YIELDED; + if (!(ci->callstatus & CIST_STAT)) /* no call status? */ + ci->u.c.status = LUA_YIELD; /* 'default' status */ + lua_assert(ci->u.c.status != LUA_OK); + ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; lua_unlock(L); - n = (*L->ci->u.c.k)(L); + n = (*ci->u.c.k)(L); lua_lock(L); /* finish 'luaD_precall' */ luaD_poscall(L, L->top - n); @@ -384,7 +383,7 @@ static void resume (lua_State *L, void *ud) { lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; if (isLua(ci)) { /* yielded inside a hook? */ - L->base = L->ci->base; /* just continue its execution */ + L->base = ci->base; /* just continue its execution */ luaV_execute(L); } else { /* 'common' yield */ @@ -427,7 +426,7 @@ static int recover (lua_State *L, int status) { luaF_close(L, oldtop); luaD_seterrorobj(L, status, oldtop); L->ci = ci; - L->base = L->ci->base; + L->base = ci->base; L->allowhook = ci->u.c.old_allowhook; L->nny = 0; /* should be zero to be yieldable */ restore_stack_limit(L); @@ -499,8 +498,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, luaF_close(L, oldtop); /* close possible pending closures */ luaD_seterrorobj(L, status, oldtop); L->ci = old_ci; - L->base = L->ci->base; - L->savedpc = L->ci->savedpc; + L->base = old_ci->base; L->allowhook = old_allowhooks; L->nny = old_nny; restore_stack_limit(L); diff --git a/lstate.c b/lstate.c index e1bbd7bd..7df2ba2b 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.51 2009/04/17 14:28:06 roberto Exp roberto $ +** $Id: lstate.c,v 2.52 2009/04/17 14:40:13 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -130,7 +130,6 @@ static void preinit_state (lua_State *L, global_State *g) { L->base_ci.next = L->base_ci.previous = NULL; L->ci = &L->base_ci; L->nci = 0; - L->savedpc = NULL; L->errfunc = 0; setnilvalue(gt(L)); } diff --git a/lstate.h b/lstate.h index 0e34a54c..23d1dfb5 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.41 2009/04/08 18:04:33 roberto Exp roberto $ +** $Id: lstate.h,v 2.42 2009/04/17 14:28:06 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -81,11 +81,11 @@ typedef struct CallInfo { StkId func; /* function index in the stack */ StkId top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ - const Instruction *savedpc; short nresults; /* expected number of results from a call */ lu_byte callstatus; union { struct { /* only for Lua functions */ + const Instruction *savedpc; int tailcalls; /* number of tail calls lost under this entry */ } l; struct { /* only for C functions */ @@ -165,7 +165,6 @@ struct lua_State { global_State *l_G; CallInfo *ci; /* call info for current function */ int nci; /* number of total CallInfo structures linked */ - const Instruction *savedpc; /* `savedpc' of current function */ const Instruction *oldpc; /* last pc traced */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ diff --git a/ltests.c b/ltests.c index 9a55f6da..5e2b6d75 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.60 2009/04/14 19:10:17 roberto Exp roberto $ +** $Id: ltests.c,v 2.61 2009/04/17 14:28:06 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -285,6 +285,16 @@ static void checkclosure (global_State *g, Closure *cl) { } +static int lua_checkpc (pCallInfo ci) { + if (!isLua(ci)) return 1; + else { + Proto *p = ci_func(ci)->l.p; + return p->code <= ci->u.l.savedpc && + ci->u.l.savedpc <= p->code + p->sizecode; + } +} + + static void checkstack (global_State *g, lua_State *L1) { StkId o; CallInfo *ci; @@ -298,7 +308,7 @@ static void checkstack (global_State *g, lua_State *L1) { checkliveness(g, gt(L1)); for (ci = L1->ci; ci != NULL; ci = ci->previous) { lua_assert(ci->top <= L1->stack_last); - lua_assert(lua_checkpc(L1, ci)); + lua_assert(lua_checkpc(ci)); } if (L1->stack) { for (o = L1->stack; o < L1->top; o++) @@ -352,18 +362,6 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[gch(o)->tt], gch(o)->mar } -int lua_checkpc (lua_State *L, pCallInfo ci) { - if (!isLua(ci)) return 1; - else { - Proto *p = ci_func(ci)->l.p; - if (ci != L->ci) - return p->code <= ci->savedpc && ci->savedpc <= p->code + p->sizecode; - else - return p->code <= L->savedpc && L->savedpc <= p->code + p->sizecode; - } -} - - int lua_checkmemory (lua_State *L) { global_State *g = G(L); GCObject *o; diff --git a/ltests.h b/ltests.h index 180d067b..4a27d099 100644 --- a/ltests.h +++ b/ltests.h @@ -1,5 +1,5 @@ /* -** $Id: ltests.h,v 2.23 2008/07/18 19:58:10 roberto Exp roberto $ +** $Id: ltests.h,v 2.24 2008/08/05 19:24:46 roberto Exp roberto $ ** Internal Header for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -51,7 +51,6 @@ void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize); typedef struct CallInfo *pCallInfo; int lua_checkmemory (lua_State *L); -int lua_checkpc (lua_State *L, pCallInfo ci); /* test for lock/unlock */ diff --git a/lvm.c b/lvm.c index 0c70491d..ad3a26cd 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.84 2009/03/10 17:14:37 roberto Exp roberto $ +** $Id: lvm.c,v 2.85 2009/04/17 14:28:06 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -58,21 +58,22 @@ int luaV_tostring (lua_State *L, StkId obj) { 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_callhook(L, LUA_HOOKCOUNT, -1); } if (mask & LUA_MASKLINE) { - Proto *p = ci_func(L->ci)->l.p; - int npc = pcRel(L->savedpc, p); + Proto *p = ci_func(ci)->l.p; + int npc = pcRel(ci->u.l.savedpc, p); int newline = getline(p, npc); if (npc == 0 || /* call linehook when enter a new function, */ - L->savedpc <= L->oldpc || /* when jump back (loop), or when */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ newline != getline(p, pcRel(L->oldpc, p))) /* enter a new line */ luaD_callhook(L, LUA_HOOKLINE, newline); } - L->oldpc = L->savedpc; + L->oldpc = ci->u.l.savedpc; } @@ -357,7 +358,8 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, ** finish execution of an opcode interrupted by an yield */ void luaV_finishOp (lua_State *L) { - Instruction inst = *(L->savedpc - 1); /* interrupted instruction */ + CallInfo *ci = L->ci; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ switch (GET_OPCODE(inst)) { /* finish its execution */ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: @@ -373,9 +375,9 @@ void luaV_finishOp (lua_State *L) { if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) res = !res; /* invert result */ - lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); if (res != GETARG_A(inst)) /* condition failed? */ - L->savedpc++; /* skip jump instruction */ + ci->u.l.savedpc++; /* skip jump instruction */ break; } case OP_CONCAT: { @@ -384,7 +386,7 @@ void luaV_finishOp (lua_State *L) { int b = GETARG_B(inst); /* ... first element to concatenate */ int total = last - b + 1; /* number of elements to concatenate */ setobj2s(L, top - 2, top); /* put TM result in proper position */ - L->top = L->ci->top; /* correct top */ + L->top = ci->top; /* correct top */ if (total > 1) /* are there elements to concat? */ luaV_concat(L, total, last); /* concat them (may yield again) */ /* move final result to final position */ @@ -392,13 +394,13 @@ void luaV_finishOp (lua_State *L) { break; } case OP_TFORCALL: { - lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); - L->top = L->ci->top; /* correct top */ + 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 = L->ci->top; /* adjust results */ + L->top = ci->top; /* adjust results */ break; } case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE: @@ -413,8 +415,6 @@ void luaV_finishOp (lua_State *L) { ** some macros for common tasks in `luaV_execute' */ -#define runtime_check(L, c) { if (!(c)) break; } - #define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) @@ -426,10 +426,10 @@ void luaV_finishOp (lua_State *L) { #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) -#define dojump(L,i) { L->savedpc += (i); luai_threadyield(L);} +#define dojump(i) { ci->u.l.savedpc += (i); luai_threadyield(L);} -#define Protect(x) { {x;}; base = L->base; } +#define Protect(x) { {x;}; base = ci->base; } #define arith_op(op,tm) { \ @@ -446,32 +446,29 @@ void luaV_finishOp (lua_State *L) { void luaV_execute (lua_State *L) { - LClosure *cl; - StkId base; - TValue *k; - reentry: /* entry point */ - lua_assert(isLua(L->ci)); - cl = &curr_func(L)->l; - base = L->base; - k = cl->p->k; + CallInfo *ci = L->ci; + LClosure *cl = &clvalue(ci->func)->l; + TValue *k = cl->p->k; + StkId base = ci->base; + lua_assert(isLua(ci)); /* main loop of interpreter */ for (;;) { - Instruction i = *(L->savedpc++); + Instruction i = *(ci->u.l.savedpc++); StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L); if (L->status == LUA_YIELD) { /* did hook yield? */ - L->savedpc--; /* undo increment */ + ci->u.l.savedpc--; /* undo increment */ luaD_throw(L, LUA_YIELD); } - base = L->base; + base = ci->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); - lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base == ci->base && base == L->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); - lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); + lua_assert(L->top == ci->top || luaG_checkopenop(i)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); @@ -483,7 +480,7 @@ void luaV_execute (lua_State *L) { } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) L->savedpc++; /* skip next instruction (if C) */ + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ continue; } case OP_LOADNIL: { @@ -595,7 +592,7 @@ void luaV_execute (lua_State *L) { continue; } case OP_JMP: { - dojump(L, GETARG_sBx(i)); + dojump(GETARG_sBx(i)); continue; } case OP_EQ: { @@ -603,40 +600,40 @@ void luaV_execute (lua_State *L) { TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) - dojump(L, GETARG_sBx(*L->savedpc)); + dojump(GETARG_sBx(*ci->u.l.savedpc)); ) - L->savedpc++; + ci->u.l.savedpc++; continue; } case OP_LT: { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, GETARG_sBx(*L->savedpc)); + dojump(GETARG_sBx(*ci->u.l.savedpc)); ) - L->savedpc++; + ci->u.l.savedpc++; continue; } case OP_LE: { Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, GETARG_sBx(*L->savedpc)); + dojump(GETARG_sBx(*ci->u.l.savedpc)); ) - L->savedpc++; + ci->u.l.savedpc++; continue; } case OP_TEST: { if (GETARG_C(i) ? !l_isfalse(ra) : l_isfalse(ra)) - dojump(L, GETARG_sBx(*L->savedpc)); - L->savedpc++; + dojump(GETARG_sBx(*ci->u.l.savedpc)); + ci->u.l.savedpc++; continue; } case OP_TESTSET: { TValue *rb = RB(i); if (GETARG_C(i) ? !l_isfalse(rb) : l_isfalse(rb)) { setobjs2s(L, ra, rb); - dojump(L, GETARG_sBx(*L->savedpc)); + dojump(GETARG_sBx(*ci->u.l.savedpc)); } - L->savedpc++; + ci->u.l.savedpc++; continue; } case OP_CALL: { @@ -644,13 +641,14 @@ void luaV_execute (lua_State *L) { int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) L->top = L->ci->top; /* adjust results */ - base = L->base; + if (nresults >= 0) L->top = ci->top; /* adjust results */ + base = ci->base; continue; } else { /* Lua function */ - L->ci->callstatus |= CIST_REENTRY; - goto reentry; /* restart luaV_execute over new Lua function */ + ci = L->ci; + ci->callstatus |= CIST_REENTRY; + break; /* restart luaV_execute over new Lua function */ } } case OP_TAILCALL: { @@ -658,25 +656,26 @@ void luaV_execute (lua_State *L) { if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ - base = L->base; + base = ci->base; continue; } else { - /* tail call: put new frame in place of previous one */ - StkId pfunc = L->ci->func; /* called function index */ - CallInfo *ci = L->ci->previous; /* caller frame */ - StkId func = ci->func; + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function index */ + StkId ofunc = oci->func; int aux; - if (cl->p->sizep > 0) luaF_close(L, ci->base); - L->base = ci->base = ci->func + (L->ci->base - pfunc); - for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ - setobjs2s(L, func+aux, pfunc+aux); - ci->top = L->top = func+aux; /* correct top */ - lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); - ci->savedpc = L->savedpc; - ci->u.l.tailcalls++; /* one more call lost */ - L->ci = ci; /* remove new frame */ - goto reentry; + if (cl->p->sizep > 0) luaF_close(L, oci->base); + L->base = oci->base = ofunc + (nci->base - nfunc); + for (aux = 0; nfunc+aux < L->top; aux++) /* move frame down */ + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->top = L->top = ofunc + aux; /* correct top */ + lua_assert(L->top == L->base + clvalue(ofunc)->l.p->maxstacksize); + oci->u.l.savedpc = nci->u.l.savedpc; + oci->u.l.tailcalls++; /* one more call lost */ + ci = L->ci = oci; /* remove new frame */ + break; /* restart luaV_execute over new Lua function */ } } case OP_RETURN: { @@ -684,13 +683,14 @@ void luaV_execute (lua_State *L) { if (b != 0) L->top = ra+b-1; if (cl->p->sizep > 0) luaF_close(L, base); b = luaD_poscall(L, ra); - if (!(L->ci->next->callstatus & CIST_REENTRY)) + if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ return; /* external invocation: return */ else { /* invocation via reentry: continue execution */ - if (b) L->top = L->ci->top; - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + break; /* restart luaV_execute over new Lua function */ } } case OP_FORLOOP: { @@ -699,7 +699,7 @@ void luaV_execute (lua_State *L) { lua_Number limit = nvalue(ra+1); if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) : luai_numle(L, limit, idx)) { - dojump(L, GETARG_sBx(i)); /* jump back */ + dojump(GETARG_sBx(i)); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ } @@ -716,7 +716,7 @@ void luaV_execute (lua_State *L) { else if (!tonumber(pstep, ra+2)) luaG_runerror(L, LUA_QL("for") " step must be a number"); setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); - dojump(L, GETARG_sBx(i)); + dojump(GETARG_sBx(i)); continue; } case OP_TFORCALL: { @@ -726,8 +726,8 @@ 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), 1)); - L->top = L->ci->top; - i = *(L->savedpc++); /* go to next instruction */ + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ ra = RA(i); lua_assert(GET_OPCODE(i) == OP_TFORLOOP); /* go through */ @@ -735,7 +735,7 @@ void luaV_execute (lua_State *L) { case OP_TFORLOOP: { if (!ttisnil(ra + 1)) { /* continue loop? */ setobjs2s(L, ra, ra + 1); /* save control variable */ - dojump(L, GETARG_sBx(i)); /* jump back */ + dojump(GETARG_sBx(i)); /* jump back */ } continue; } @@ -746,10 +746,9 @@ void luaV_execute (lua_State *L) { Table *h; if (n == 0) n = cast_int(L->top - ra) - 1; if (c == 0) { - lua_assert(GET_OPCODE(*L->savedpc) == OP_EXTRAARG); - c = GETARG_Ax(*L->savedpc++); + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); } - runtime_check(L, ttistable(ra)); h = hvalue(ra); last = ((c-1)*LFIELDS_PER_FLUSH) + n; if (last > h->sizearray) /* needs more space? */ @@ -759,7 +758,7 @@ void luaV_execute (lua_State *L) { setobj2t(L, luaH_setnum(L, h, last--), val); luaC_barriert(L, h, val); } - L->top = L->ci->top; /* correct top (in case of previous open call) */ + L->top = ci->top; /* correct top (in case of previous open call) */ continue; } case OP_CLOSE: { @@ -776,7 +775,7 @@ void luaV_execute (lua_State *L) { ncl->l.p = p; setclvalue(L, ra, ncl); for (j=0; jsavedpc++; + Instruction u = *ci->u.l.savedpc++; if (GET_OPCODE(u) == OP_GETUPVAL) ncl->l.upvals[j] = cl->upvals[GETARG_B(u)]; else { @@ -790,7 +789,6 @@ void luaV_execute (lua_State *L) { case OP_VARARG: { int b = GETARG_B(i) - 1; int j; - CallInfo *ci = L->ci; int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; if (b == LUA_MULTRET) { Protect(luaD_checkstack(L, n)); @@ -813,6 +811,11 @@ void luaV_execute (lua_State *L) { return; } } + /* function changed (call/return): update pointers */ + lua_assert(ci == L->ci); + cl = &clvalue(ci->func)->l; + k = cl->p->k; + base = ci->base; } }