(much) cleaner way to control function states

This commit is contained in:
Roberto Ierusalimschy 2002-08-07 16:22:39 -03:00
parent c1c100a0c0
commit 5016f43aa4
6 changed files with 54 additions and 42 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 1.128 2002/08/06 18:01:50 roberto Exp roberto $ ** $Id: ldebug.c,v 1.129 2002/08/07 14:35:55 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -28,14 +28,16 @@
static const char *getfuncname (CallInfo *ci, const char **name); static const char *getfuncname (CallInfo *ci, const char **name);
static int isLua (CallInfo *ci) { #define isLua(ci) (!((ci)->state & CI_C))
return isLfunction (ci->base - 1);
}
static int currentpc (CallInfo *ci) { static int currentpc (CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */ if (!isLua(ci)) return -1; /* function is not a Lua function? */
if (ci->pc != &luaV_callingmark) /* is not calling another Lua function? */ if (!(ci->state & CI_SAVEDPC)) { /* savedpc outdated? */
ci->u.l.savedpc = *ci->pc; /* `pc' may not be saved; save it */ lua_assert(ci->state & CI_HASFRAME);
ci->u.l.savedpc = *ci->u.l.pc;
ci->state |= CI_SAVEDPC;
}
/* function's pc is saved */ /* function's pc is saved */
return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
} }

16
ldo.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 1.189 2002/08/05 17:36:24 roberto Exp roberto $ ** $Id: ldo.c,v 1.190 2002/08/06 15:32:22 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -108,7 +108,7 @@ static void correctstack (lua_State *L, TObject *oldstack) {
for (ci = L->base_ci; ci <= L->ci; ci++) { for (ci = L->base_ci; ci <= L->ci; ci++) {
ci->base = (ci->base - oldstack) + L->stack; ci->base = (ci->base - oldstack) + L->stack;
ci->top = (ci->top - oldstack) + L->stack; ci->top = (ci->top - oldstack) + L->stack;
if (ci->pc && ci->pc != &luaV_callingmark) /* function has a frame? */ if (ci->state & CI_HASFRAME) /* Lua function with active frame? */
*ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
} }
} }
@ -229,6 +229,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
ci->base = restorestack(L, funcr) + 1; ci->base = restorestack(L, funcr) + 1;
ci->top = ci->base + p->maxstacksize; ci->top = ci->base + p->maxstacksize;
ci->u.l.savedpc = p->code; /* starting point */ ci->u.l.savedpc = p->code; /* starting point */
ci->state = CI_SAVEDPC;
while (L->top < ci->top) while (L->top < ci->top)
setnilvalue(L->top++); setnilvalue(L->top++);
L->top = ci->top; L->top = ci->top;
@ -241,7 +242,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
ci = ++L->ci; /* now `enter' new function */ ci = ++L->ci; /* now `enter' new function */
ci->base = restorestack(L, funcr) + 1; ci->base = restorestack(L, funcr) + 1;
ci->top = L->top + LUA_MINSTACK; ci->top = L->top + LUA_MINSTACK;
ci->pc = NULL; /* not a Lua function */ ci->state = CI_C; /* a C function */
if (L->hookmask & LUA_MASKCALL) { if (L->hookmask & LUA_MASKCALL) {
luaD_callhook(L, LUA_HOOKCALL, -1); luaD_callhook(L, LUA_HOOKCALL, -1);
ci = L->ci; /* previous call may realocate `ci' */ ci = L->ci; /* previous call may realocate `ci' */
@ -300,7 +301,6 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
LUA_API void lua_cobegin (lua_State *L, int nargs) { LUA_API void lua_cobegin (lua_State *L, int nargs) {
lua_lock(L); lua_lock(L);
luaD_precall(L, L->top - (nargs+1)); luaD_precall(L, L->top - (nargs+1));
L->ci->pc = &luaV_callingmark; /* function is not active (yet) */
lua_unlock(L); lua_unlock(L);
} }
@ -317,10 +317,10 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
static void resume (lua_State *L, void *ud) { static void resume (lua_State *L, void *ud) {
StkId firstResult; StkId firstResult;
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
if (ci->pc == NULL) { /* not first time? */ if (ci->state & CI_C) { /* not first time (i.e. inside a yield)? */
/* finish interrupted execution of `OP_CALL' */ /* finish interrupted execution of `OP_CALL' */
int nresults; int nresults;
lua_assert((ci - 1)->pc == &luaV_callingmark); lua_assert((ci-1)->state & CI_SAVEDPC);
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
@ -363,9 +363,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
CallInfo *ci; CallInfo *ci;
lua_lock(L); lua_lock(L);
ci = L->ci; ci = L->ci;
if ((ci-1)->pc == NULL) if ((ci-1)->state & CI_C)
luaG_runerror(L, "cannot yield a C function"); luaG_runerror(L, "cannot yield a C function");
lua_assert(ci->pc == NULL); /* current function is not Lua */ lua_assert(ci->state & CI_C); /* current function is not Lua */
ci->u.c.yield_results = nresults; ci->u.c.yield_results = nresults;
lua_unlock(L); lua_unlock(L);
return -1; return -1;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 1.101 2002/08/05 18:45:45 roberto Exp roberto $ ** $Id: lstate.c,v 1.102 2002/08/06 15:32:22 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -41,7 +41,7 @@ static void stack_init (lua_State *L, lua_State *OL) {
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1; L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo); L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
L->ci = L->base_ci; L->ci = L->base_ci;
L->ci->pc = NULL; /* not a Lua function */ L->ci->state = CI_C; /* not a Lua function */
setnilvalue(L->top++); /* `function' entry for this `ci' */ setnilvalue(L->top++); /* `function' entry for this `ci' */
L->ci->base = L->top; L->ci->base = L->top;
L->ci->top = L->top + LUA_MINSTACK; L->ci->top = L->top + LUA_MINSTACK;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 1.91 2002/08/06 15:32:22 roberto Exp roberto $ ** $Id: lstate.h,v 1.92 2002/08/06 18:01:50 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -87,10 +87,11 @@ typedef struct stringtable {
typedef struct CallInfo { typedef struct CallInfo {
StkId base; /* base for called function */ StkId base; /* base for called function */
StkId top; /* top for this function */ StkId top; /* top for this function */
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ int state; /* bit fields; see below */
union { union {
struct { /* for Lua functions */ struct { /* for Lua functions */
const Instruction *savedpc; const Instruction *savedpc;
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
StkId *pb; /* points to `base' variable in `luaV_execute' */ StkId *pb; /* points to `base' variable in `luaV_execute' */
} l; } l;
struct { /* for C functions */ struct { /* for C functions */
@ -100,6 +101,17 @@ typedef struct CallInfo {
} CallInfo; } CallInfo;
/*
** bit fields for `CallInfo.state'
*/
#define CI_C 1 /* 1 if function is a C function */
/* 1 if (Lua) function has an active `luaV_execute' running it */
#define CI_HASFRAME 2
/* 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 4
#define CI_SAVEDPC 8 /* 1 if `savedpc' is updated */
#define ci_func(ci) (clvalue((ci)->base - 1)) #define ci_func(ci) (clvalue((ci)->base - 1))

37
lvm.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.c,v 1.249 2002/08/05 17:36:24 roberto Exp roberto $ ** $Id: lvm.c,v 1.250 2002/08/07 14:24:24 roberto Exp roberto $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -24,8 +24,6 @@
#include "lvm.h" #include "lvm.h"
Instruction const *luaV_callingmark = NULL;
/* function to convert a lua_Number to a string */ /* function to convert a lua_Number to a string */
#ifndef lua_number2str #ifndef lua_number2str
@ -83,16 +81,18 @@ static void traceexec (lua_State *L) {
if (mask & LUA_MASKLINE) { if (mask & LUA_MASKLINE) {
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
Proto *p = ci_func(ci)->l.p; Proto *p = ci_func(ci)->l.p;
int newline = getline(p, pcRel(*ci->pc, p)); int newline = getline(p, pcRel(*ci->u.l.pc, p));
if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */ lua_assert(ci->state & CI_HASFRAME);
ci->u.l.savedpc = *ci->pc; /* initialize `savedpc' */ if (pcRel(*ci->u.l.pc, p) == 0) /* tracing 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) */ /* calls linehook when enters a new line or jumps back (loop) */
if (*ci->pc <= ci->u.l.savedpc || if (*ci->u.l.pc <= ci->u.l.savedpc ||
newline != getline(p, pcRel(ci->u.l.savedpc, p))) { newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
luaD_callhook(L, LUA_HOOKLINE, newline); luaD_callhook(L, LUA_HOOKLINE, newline);
ci = L->ci; /* previous call may reallocate `ci' */ ci = L->ci; /* previous call may reallocate `ci' */
} }
ci->u.l.savedpc = *ci->pc; ci->u.l.savedpc = *ci->u.l.pc;
ci->state |= CI_SAVEDPC; /* `savedpc' is updated */
} }
} }
@ -374,11 +374,13 @@ StkId luaV_execute (lua_State *L) {
const Instruction *pc; const Instruction *pc;
callentry: /* entry point when calling new functions */ callentry: /* entry point when calling new functions */
L->ci->u.l.pb = &base; L->ci->u.l.pb = &base;
L->ci->pc = &pc; L->ci->u.l.pc = &pc;
pc = L->ci->u.l.savedpc;
if (L->hookmask & LUA_MASKCALL) if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1); luaD_callhook(L, LUA_HOOKCALL, -1);
retentry: /* entry point when returning to old functions */ retentry: /* entry point when returning to old functions */
lua_assert(L->ci->state & CI_SAVEDPC);
L->ci->state = CI_HASFRAME; /* activate frame */
pc = L->ci->u.l.savedpc;
base = L->ci->base; base = L->ci->base;
cl = &clvalue(base - 1)->l; cl = &clvalue(base - 1)->l;
k = cl->p->k; k = cl->p->k;
@ -599,7 +601,7 @@ StkId luaV_execute (lua_State *L) {
if (firstResult) { if (firstResult) {
if (firstResult > L->top) { /* yield? */ if (firstResult > L->top) { /* yield? */
(L->ci - 1)->u.l.savedpc = pc; (L->ci - 1)->u.l.savedpc = pc;
(L->ci - 1)->pc = &luaV_callingmark; (L->ci - 1)->state = CI_SAVEDPC;
return NULL; return NULL;
} }
/* it was a C function (`precall' called it); adjust results */ /* it was a C function (`precall' called it); adjust results */
@ -609,7 +611,7 @@ StkId luaV_execute (lua_State *L) {
else { /* it is a Lua function */ else { /* it is a Lua function */
if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ if (GET_OPCODE(i) == OP_CALL) { /* regular call? */
(L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */
(L->ci-1)->pc = &luaV_callingmark; /* function is calling */ (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
} }
else { /* tail call: put new frame in place of previous one */ else { /* tail call: put new frame in place of previous one */
int aux; int aux;
@ -618,7 +620,9 @@ StkId luaV_execute (lua_State *L) {
for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */ for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */
setobj(base+aux-1, ra1+aux); setobj(base+aux-1, ra1+aux);
(L->ci - 1)->top = L->top = base+aux; /* correct top */ (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.savedpc = L->ci->u.l.savedpc;
(L->ci - 1)->state = CI_SAVEDPC;
L->ci--; /* remove previous frame */ L->ci--; /* remove previous frame */
} }
goto callentry; goto callentry;
@ -629,20 +633,21 @@ StkId luaV_execute (lua_State *L) {
CallInfo *ci = L->ci - 1; CallInfo *ci = L->ci - 1;
int b = GETARG_B(i); int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1; if (b != 0) L->top = ra+b-1;
lua_assert(L->ci->pc == &pc); lua_assert(L->ci->state & CI_HASFRAME);
if (L->openupval) luaF_close(L, base); 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'? */ /* previous function was running `here'? */
if (ci->pc != &luaV_callingmark) if (!(ci->state & CI_CALLING))
return ra; /* no: return */ return ra; /* no: return */
else { /* yes: continue its execution (go through) */ else { /* yes: continue its execution (go through) */
int nresults; int nresults;
lua_assert(ttisfunction(ci->base - 1)); lua_assert(ttisfunction(ci->base - 1));
lua_assert(ci->state & CI_SAVEDPC);
lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, ra); luaD_poscall(L, nresults, ra);
if (nresults >= 0) L->top = L->ci->top; if (nresults >= 0) L->top = L->ci->top;
L->ci->pc = &pc; /* function is active again */
pc = L->ci->u.l.savedpc;
goto retentry; goto retentry;
} }
} }

9
lvm.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.h,v 1.44 2002/07/05 18:27:39 roberto Exp $ ** $Id: lvm.h,v 1.45 2002/08/05 17:36:24 roberto Exp roberto $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -22,13 +22,6 @@
(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
/*
** dummy addrees, to mark Lua functions calling other Lua functions (and
** therefore without a valid `pc'
*/
extern Instruction const *luaV_callingmark;
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
const TObject *luaV_tonumber (const TObject *obj, TObject *n); const TObject *luaV_tonumber (const TObject *obj, TObject *n);