From fa26d294aef136aa4ec48c23b4b87b853df0e3da Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 16 Jul 2003 17:49:02 -0300 Subject: [PATCH] new way to control `pc' of running functions --- ldebug.c | 19 +------ ldebug.h | 3 +- ldo.c | 47 ++++++++--------- lgc.c | 3 +- lgc.h | 6 +-- lstate.c | 6 +-- lstate.h | 20 ++------ lvm.c | 154 ++++++++++++++++++++++++++++--------------------------- lvm.h | 4 +- 9 files changed, 115 insertions(+), 147 deletions(-) diff --git a/ldebug.c b/ldebug.c index bc7f9237..e7413507 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.153 2003/05/14 12:09:12 roberto Exp roberto $ +** $Id: ldebug.c,v 1.154 2003/07/10 11:59:06 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -30,14 +30,8 @@ static const char *getfuncname (CallInfo *ci, const char **name); -#define isLua(ci) (!((ci)->state & CI_C)) - - static int currentpc (CallInfo *ci) { if (!isLua(ci)) return -1; /* function is not a Lua function? */ - if (ci->state & CI_HASFRAME) /* function has a frame? */ - ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */ - /* function's pc is saved */ return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); } @@ -51,14 +45,6 @@ static int currentline (CallInfo *ci) { } -void luaG_inithooks (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */ - currentpc(ci); - L->hookinit = 1; -} - - /* ** this function can be called asynchronous (e.g. during a signal) */ @@ -71,7 +57,6 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { L->basehookcount = count; resethookcount(L); L->hookmask = cast(lu_byte, mask); - L->hookinit = 0; return 1; } @@ -97,7 +82,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { lua_lock(L); for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { level--; - if (!(ci->state & CI_C)) /* Lua function? */ + if (f_isLua(ci)) /* Lua function? */ level -= ci->u.l.tailcalls; /* skip lost tail calls */ } if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ diff --git a/ldebug.h b/ldebug.h index 417bd47d..03baaaee 100644 --- a/ldebug.h +++ b/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 1.31 2002/08/20 20:03:05 roberto Exp roberto $ +** $Id: ldebug.h,v 1.32 2002/11/18 11:01:55 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -18,7 +18,6 @@ #define resethookcount(L) (L->hookcount = L->basehookcount) -void luaG_inithooks (lua_State *L); void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); diff --git a/ldo.c b/ldo.c index 93e2aa0a..f462353f 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.218 2003/05/13 19:22:19 roberto Exp roberto $ +** $Id: ldo.c,v 1.219 2003/05/14 21:02:39 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -243,6 +243,7 @@ StkId luaD_precall (lua_State *L, StkId func) { cl = &clvalue(func)->l; if (!cl->isC) { /* Lua function? prepare its call */ CallInfo *ci; + StkId st; Proto *p = cl->p; if (p->is_vararg) /* varargs? */ adjust_varargs(L, p->numparams, func+1); @@ -252,9 +253,8 @@ StkId luaD_precall (lua_State *L, StkId func) { ci->top = L->base + p->maxstacksize; ci->u.l.savedpc = p->code; /* starting point */ ci->u.l.tailcalls = 0; - ci->state = CI_SAVEDPC; - while (L->top < ci->top) - setnilvalue(L->top++); + for (st = L->top; st < ci->top; st++) + setnilvalue(st); L->top = ci->top; return NULL; } @@ -265,7 +265,6 @@ StkId luaD_precall (lua_State *L, StkId func) { ci = ++L->ci; /* now `enter' new function */ L->base = L->ci->base = restorestack(L, funcr) + 1; ci->top = L->top + LUA_MINSTACK; - ci->state = CI_C; /* a C function */ if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); lua_unlock(L); @@ -279,7 +278,7 @@ StkId luaD_precall (lua_State *L, StkId func) { static StkId callrethooks (lua_State *L, StkId firstResult) { ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ luaD_callhook(L, LUA_HOOKRET, -1); - if (!(L->ci->state & CI_C)) { /* Lua function? */ + if (f_isLua(L->ci)) { /* Lua function? */ while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ luaD_callhook(L, LUA_HOOKTAILRET, -1); } @@ -313,7 +312,6 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { */ void luaD_call (lua_State *L, StkId func, int nResults) { StkId firstResult; - lua_assert(!(L->ci->state & CI_CALLING)); if (++L->nCcalls >= LUA_MAXCCALLS) { if (L->nCcalls == LUA_MAXCCALLS) luaG_runerror(L, "C stack overflow"); @@ -322,7 +320,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { } firstResult = luaD_precall(L, func); if (firstResult == NULL) /* is a Lua function? */ - firstResult = luaV_execute(L); /* call it */ + firstResult = luaV_execute(L, 1); /* call it */ luaD_poscall(L, nResults, firstResult); L->nCcalls--; luaC_checkGC(L); @@ -333,29 +331,28 @@ static void resume (lua_State *L, void *ud) { StkId firstResult; int nargs = *cast(int *, ud); CallInfo *ci = L->ci; - if (ci == L->base_ci) { /* no activation record? */ - if (nargs >= L->top - L->base) - luaG_runerror(L, "cannot resume dead coroutine"); - luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ + if (!L->isSuspended) { + if (ci == L->base_ci) { /* no activation record? */ + if (nargs >= L->top - L->base) + luaG_runerror(L, "cannot resume dead coroutine"); + luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ + } + else + luaG_runerror(L, "cannot resume non-suspended coroutine"); } - else if (ci->state & CI_YIELD) { /* inside a yield? */ - if (ci->state & CI_C) { /* `common' yield? */ + else { /* resumming from previous yield */ + if (!f_isLua(ci)) { /* `common' yield? */ /* finish interrupted execution of `OP_CALL' */ int nresults; - lua_assert((ci-1)->state & CI_SAVEDPC); lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; luaD_poscall(L, nresults, L->top - nargs); /* complete it */ if (nresults >= 0) L->top = L->ci->top; - } - else { /* yielded inside a hook: just continue its execution */ - ci->state &= ~CI_YIELD; - } + } /* else yielded inside a hook: just continue its execution */ } - else - luaG_runerror(L, "cannot resume non-suspended coroutine"); - firstResult = luaV_execute(L); + L->isSuspended = 0; + firstResult = luaV_execute(L, L->ci - L->base_ci); if (firstResult != NULL) /* return? */ luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ } @@ -388,9 +385,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { ci = L->ci; if (L->nCcalls > 0) luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - if (ci->state & CI_C) { /* usual yield */ - if ((ci-1)->state & CI_C) - luaG_runerror(L, "cannot yield a C function"); + if (!f_isLua(ci)) { /* usual yield */ if (L->top - nresults > L->base) { /* is there garbage in the stack? */ int i; for (i=0; itop = L->base + nresults; } } /* else it's an yield inside a hook: nothing to do */ - ci->state |= CI_YIELD; + L->isSuspended = 1; lua_unlock(L); return -1; } diff --git a/lgc.c b/lgc.c index a0e1bcdb..c28ea8b9 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.173 2003/05/16 18:58:39 roberto Exp roberto $ +** $Id: lgc.c,v 1.174 2003/07/07 13:32:19 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -232,7 +232,6 @@ static void traversestack (GCState *st, lua_State *L1) { lim = L1->top; for (ci = L1->base_ci; ci <= L1->ci; ci++) { lua_assert(ci->top <= L1->stack_last); - lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC)); if (lim < ci->top) lim = ci->top; } for (o = L1->stack; o < L1->top; o++) diff --git a/lgc.h b/lgc.h index 8e3a3257..4e66eaa8 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 1.18 2003/02/10 17:32:50 roberto Exp roberto $ +** $Id: lgc.h,v 1.19 2003/02/28 19:45:15 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -11,8 +11,8 @@ #include "lobject.h" -#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \ - if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); } +#define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ + luaC_collectgarbage(L); } void luaC_separateudata (lua_State *L); diff --git a/lstate.c b/lstate.c index 008955e4..2153d3d9 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.122 2003/03/18 12:50:04 roberto Exp roberto $ +** $Id: lstate.c,v 1.123 2003/04/03 13:35:34 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -68,7 +68,6 @@ static void stack_init (lua_State *L1, lua_State *L) { L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); L1->ci = L1->base_ci; - L1->ci->state = CI_C; /* not a Lua function */ setnilvalue(L1->top++); /* `function' entry for this `ci' */ L1->base = L1->ci->base = L1->top; L1->ci->top = L1->top + LUA_MINSTACK; @@ -128,13 +127,14 @@ static void preinit_state (lua_State *L) { L->stacksize = 0; L->errorJmp = NULL; L->hook = NULL; - L->hookmask = L->hookinit = 0; + L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; L->nCcalls = 0; + L->isSuspended = 0; L->base_ci = L->ci = NULL; L->errfunc = 0; setnilvalue(gt(L)); diff --git a/lstate.h b/lstate.h index 37de2372..009ea790 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.109 2003/02/27 11:52:30 roberto Exp roberto $ +** $Id: lstate.h,v 1.110 2003/04/28 19:26:16 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -75,11 +75,9 @@ typedef struct stringtable { typedef struct CallInfo { StkId base; /* base for called function */ StkId top; /* top for this function */ - int state; /* bit fields; see below */ union { struct { /* for Lua functions */ const Instruction *savedpc; - const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ int tailcalls; /* number of tail calls lost under this entry */ } l; struct { /* for C functions */ @@ -89,20 +87,10 @@ typedef struct CallInfo { } CallInfo; -/* -** bit fields for `CallInfo.state' -*/ -#define CI_C (1<<0) /* 1 if function is a C function */ -/* 1 if (Lua) function has an active `luaV_execute' running it */ -#define CI_HASFRAME (1<<1) -/* 1 if Lua function is calling another Lua function (and therefore its - `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */ -#define CI_CALLING (1<<2) -#define CI_SAVEDPC (1<<3) /* 1 if `savedpc' is updated */ -#define CI_YIELD (1<<4) /* 1 if thread is suspended */ - #define ci_func(ci) (clvalue((ci)->base - 1)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->base - 1) && f_isLua(ci)) /* @@ -143,7 +131,7 @@ struct lua_State { unsigned short nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; - lu_byte hookinit; + lu_byte isSuspended; int basehookcount; int hookcount; lua_Hook hook; diff --git a/lvm.c b/lvm.c index b8ac9ec8..e10763d6 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.287 2003/05/14 12:09:12 roberto Exp roberto $ +** $Id: lvm.c,v 1.288 2003/07/07 13:37:56 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -64,8 +64,11 @@ int luaV_tostring (lua_State *L, StkId obj) { } -static void traceexec (lua_State *L) { +static void traceexec (lua_State *L, const Instruction *pc) { lu_byte mask = L->hookmask; + CallInfo *ci = L->ci; + const Instruction *oldpc = ci->u.l.savedpc; + ci->u.l.savedpc = pc; if (mask > LUA_MASKLINE) { /* instruction-hook set? */ if (L->hookcount == 0) { resethookcount(L); @@ -74,25 +77,13 @@ static void traceexec (lua_State *L) { } } if (mask & LUA_MASKLINE) { - CallInfo *ci = L->ci; Proto *p = ci_func(ci)->l.p; - int pc = pcRel(*ci->u.l.pc, p); - int newline = getline(p, pc); - if (!L->hookinit) { - luaG_inithooks(L); - if (pc != 0) /* not function start? */ - return; /* begin tracing on next line */ - } - lua_assert(ci->state & CI_HASFRAME); - if (pc == 0) /* function may be starting now? */ - ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ - /* calls linehook when enters a new line or jumps back (loop) */ - if (*ci->u.l.pc <= ci->u.l.savedpc || - newline != getline(p, pcRel(ci->u.l.savedpc, p))) { + int npc = pcRel(pc, p); + int newline = getline(p, npc); + /* call linehook when enter a new function, when jump back (loop), + or when enter a new line */ + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) luaD_callhook(L, LUA_HOOKLINE, newline); - ci = L->ci; /* previous call may reallocate `ci' */ - } - ci->u.l.savedpc = *ci->u.l.pc; } } @@ -327,10 +318,11 @@ void luaV_concat (lua_State *L, int total, int last) { } -static void Arith (lua_State *L, StkId ra, - const TObject *rb, const TObject *rc, TMS op) { +static StkId Arith (lua_State *L, StkId ra, const TObject *rb, + const TObject *rc, TMS op, const Instruction *pc) { TObject tempb, tempc; const TObject *b, *c; + L->ci->u.l.savedpc = pc; if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { switch (op) { @@ -350,6 +342,7 @@ static void Arith (lua_State *L, StkId ra, } else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); + return L->base; } @@ -362,7 +355,6 @@ static void Arith (lua_State *L, StkId ra, #define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ -#define XRA(i) (L->base+GETARG_A(i)) #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ @@ -375,39 +367,35 @@ static void Arith (lua_State *L, StkId ra, #define dojump(pc, i) ((pc) += (i)) -StkId luaV_execute (lua_State *L) { +StkId luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; TObject *k; + StkId base; const Instruction *pc; callentry: /* entry point when calling new functions */ - L->ci->u.l.pc = &pc; if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); retentry: /* entry point when returning to old functions */ - lua_assert(L->ci->state == CI_SAVEDPC || - L->ci->state == (CI_SAVEDPC | CI_CALLING)); - L->ci->state = CI_HASFRAME; /* activate frame */ pc = L->ci->u.l.savedpc; - cl = &clvalue(L->base - 1)->l; + base = L->base; + cl = &clvalue(base - 1)->l; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; - StkId base, ra; + StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - traceexec(L); - if (L->ci->state & CI_YIELD) { /* did hook yield? */ + traceexec(L, pc); /***/ + if (L->isSuspended) { /* did hook yield? */ L->ci->u.l.savedpc = pc - 1; - L->ci->state = CI_YIELD | CI_SAVEDPC; return NULL; } + base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ - base = L->base; ra = RA(i); - lua_assert(L->ci->state & CI_HASFRAME); - lua_assert(base == L->ci->base); + lua_assert(base == L->ci->base && base == L->base); lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || @@ -441,16 +429,22 @@ StkId luaV_execute (lua_State *L) { case OP_GETGLOBAL: { TObject *rb = KBx(i); lua_assert(ttisstring(rb) && ttistable(&cl->g)); - luaV_gettable(L, &cl->g, rb, ra); + L->ci->u.l.savedpc = pc; + luaV_gettable(L, &cl->g, rb, ra); /***/ + base = L->base; break; } case OP_GETTABLE: { - luaV_gettable(L, RB(i), RKC(i), ra); + L->ci->u.l.savedpc = pc; + luaV_gettable(L, RB(i), RKC(i), ra); /***/ + base = L->base; break; } case OP_SETGLOBAL: { lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); - luaV_settable(L, &cl->g, KBx(i), ra); + L->ci->u.l.savedpc = pc; + luaV_settable(L, &cl->g, KBx(i), ra); /***/ + base = L->base; break; } case OP_SETUPVAL: { @@ -459,20 +453,26 @@ StkId luaV_execute (lua_State *L) { break; } case OP_SETTABLE: { - luaV_settable(L, ra, RKB(i), RKC(i)); + L->ci->u.l.savedpc = pc; + luaV_settable(L, ra, RKB(i), RKC(i)); /***/ + base = L->base; break; } case OP_NEWTABLE: { int b = GETARG_B(i); b = fb2int(b); sethvalue(ra, luaH_new(L, b, GETARG_C(i))); - luaC_checkGC(L); + L->ci->u.l.savedpc = pc; + luaC_checkGC(L); /***/ + base = L->base; break; } case OP_SELF: { StkId rb = RB(i); setobjs2s(ra+1, rb); - luaV_gettable(L, rb, RKC(i), ra); + L->ci->u.l.savedpc = pc; + luaV_gettable(L, rb, RKC(i), ra); /***/ + base = L->base; break; } case OP_ADD: { @@ -482,7 +482,7 @@ StkId luaV_execute (lua_State *L) { setnvalue(ra, nvalue(rb) + nvalue(rc)); } else - Arith(L, ra, rb, rc, TM_ADD); + base = Arith(L, ra, rb, rc, TM_ADD, pc); /***/ break; } case OP_SUB: { @@ -492,7 +492,7 @@ StkId luaV_execute (lua_State *L) { setnvalue(ra, nvalue(rb) - nvalue(rc)); } else - Arith(L, ra, rb, rc, TM_SUB); + base = Arith(L, ra, rb, rc, TM_SUB, pc); /***/ break; } case OP_MUL: { @@ -502,7 +502,7 @@ StkId luaV_execute (lua_State *L) { setnvalue(ra, nvalue(rb) * nvalue(rc)); } else - Arith(L, ra, rb, rc, TM_MUL); + base = Arith(L, ra, rb, rc, TM_MUL, pc); /***/ break; } case OP_DIV: { @@ -512,11 +512,11 @@ StkId luaV_execute (lua_State *L) { setnvalue(ra, nvalue(rb) / nvalue(rc)); } else - Arith(L, ra, rb, rc, TM_DIV); + base = Arith(L, ra, rb, rc, TM_DIV, pc); /***/ break; } case OP_POW: { - Arith(L, ra, RKB(i), RKC(i), TM_POW); + base = Arith(L, ra, RKB(i), RKC(i), TM_POW, pc); /***/ break; } case OP_UNM: { @@ -527,8 +527,10 @@ StkId luaV_execute (lua_State *L) { } else { setnilvalue(&temp); - if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) + L->ci->u.l.savedpc = pc; + if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) /***/ luaG_aritherror(L, RB(i), &temp); + base = L->base; } break; } @@ -540,10 +542,11 @@ StkId luaV_execute (lua_State *L) { case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); - luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ + L->ci->u.l.savedpc = pc; + luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ /***/ + luaC_checkGC(L); /***/ base = L->base; setobjs2s(RA(i), base+b); - luaC_checkGC(L); break; } case OP_JMP: { @@ -551,18 +554,24 @@ StkId luaV_execute (lua_State *L) { break; } case OP_EQ: { - if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + L->ci->u.l.savedpc = pc; + if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/ else dojump(pc, GETARG_sBx(*pc) + 1); + base = L->base; break; } case OP_LT: { - if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + L->ci->u.l.savedpc = pc; + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/ else dojump(pc, GETARG_sBx(*pc) + 1); + base = L->base; break; } case OP_LE: { - if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; + L->ci->u.l.savedpc = pc; + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/ else dojump(pc, GETARG_sBx(*pc) + 1); + base = L->base; break; } case OP_TEST: { @@ -575,18 +584,16 @@ StkId luaV_execute (lua_State *L) { break; } case OP_CALL: - case OP_TAILCALL: { + case OP_TAILCALL: { /***/ StkId firstResult; int b = GETARG_B(i); - int nresults; if (b != 0) L->top = ra+b; /* else previous instruction set top */ - nresults = GETARG_C(i) - 1; + L->ci->u.l.savedpc = pc; firstResult = luaD_precall(L, ra); if (firstResult) { + int nresults = GETARG_C(i) - 1; if (firstResult > L->top) { /* yield? */ - lua_assert(L->ci->state == (CI_C | CI_YIELD)); (L->ci - 1)->u.l.savedpc = pc; - (L->ci - 1)->state = CI_SAVEDPC; return NULL; } /* it was a C function (`precall' called it); adjust results */ @@ -594,10 +601,8 @@ StkId luaV_execute (lua_State *L) { if (nresults >= 0) L->top = L->ci->top; } else { /* it is a Lua function */ - if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ - (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ - (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); - } + if (GET_OPCODE(i) == OP_CALL) /* regular call? */ + nexeccalls++; else { /* tail call: put new frame in place of previous one */ int aux; base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ @@ -606,35 +611,27 @@ StkId luaV_execute (lua_State *L) { for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ setobjs2s(base+aux-1, ra+aux); (L->ci - 1)->top = L->top = base+aux; /* correct top */ - lua_assert(L->ci->state & CI_SAVEDPC); (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ - (L->ci - 1)->state = CI_SAVEDPC; L->ci--; /* remove new frame */ L->base = L->ci->base; } goto callentry; } + base = L->base; break; } case OP_RETURN: { CallInfo *ci = L->ci - 1; /* previous function frame */ int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; - lua_assert(L->ci->state & CI_HASFRAME); if (L->openupval) luaF_close(L, base); - L->ci->state = CI_SAVEDPC; /* deactivate current function */ L->ci->u.l.savedpc = pc; - /* previous function was running `here'? */ - if (!(ci->state & CI_CALLING)) { - lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc); + if (--nexeccalls == 0) /* was previous function running `here'? */ return ra; /* no: return */ - } else { /* yes: continue its execution */ int nresults; - lua_assert(ci->u.l.pc == &pc && - ttisfunction(ci->base - 1) && - (ci->state & CI_SAVEDPC)); + lua_assert(isLua(ci)); lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; luaD_poscall(L, nresults, ra); @@ -653,10 +650,11 @@ StkId luaV_execute (lua_State *L) { } break; } - case OP_FORPREP: { + case OP_FORPREP: { /***/ const TObject *init = ra; const TObject *plimit = ra+1; const TObject *pstep = ra+2; + L->ci->u.l.savedpc = pc; if (!tonumber(init, ra)) luaG_runerror(L, "`for' initial value must be a number"); else if (!tonumber(plimit, ra+1)) @@ -673,9 +671,11 @@ StkId luaV_execute (lua_State *L) { setobjs2s(cb+1, ra+1); setobjs2s(cb, ra); L->top = cb+3; /* func. + 2 args (state and index) */ - luaD_call(L, cb, GETARG_C(i)); + L->ci->u.l.savedpc = pc; + luaD_call(L, cb, GETARG_C(i)); /***/ L->top = L->ci->top; - cb = XRA(i) + 3; /* previous call may change the stack */ + base = L->base; + cb = RA(i) + 3; /* previous call may change the stack */ if (ttisnil(cb)) /* break loop? */ pc++; /* skip jump (break loop) */ else { @@ -732,7 +732,9 @@ StkId luaV_execute (lua_State *L) { } } setclvalue(ra, ncl); - luaC_checkGC(L); + L->ci->u.l.savedpc = pc; + luaC_checkGC(L); /***/ + base = L->base; break; } } diff --git a/lvm.h b/lvm.h index 667b25bb..b2d9f8d5 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 1.47 2002/11/14 16:16:21 roberto Exp roberto $ +** $Id: lvm.h,v 1.48 2003/05/05 18:39:57 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -28,7 +28,7 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n); int luaV_tostring (lua_State *L, StkId obj); void luaV_gettable (lua_State *L, const TObject *t, TObject *key, StkId val); void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val); -StkId luaV_execute (lua_State *L); +StkId luaV_execute (lua_State *L, int nexeccalls); void luaV_concat (lua_State *L, int total, int last); #endif