new way to control `pc' of running functions

This commit is contained in:
Roberto Ierusalimschy 2003-07-16 17:49:02 -03:00
parent 5a761e3a15
commit fa26d294ae
9 changed files with 115 additions and 147 deletions

View File

@ -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 ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -30,14 +30,8 @@
static const char *getfuncname (CallInfo *ci, const char **name); static const char *getfuncname (CallInfo *ci, const char **name);
#define isLua(ci) (!((ci)->state & CI_C))
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->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); 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) ** 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; L->basehookcount = count;
resethookcount(L); resethookcount(L);
L->hookmask = cast(lu_byte, mask); L->hookmask = cast(lu_byte, mask);
L->hookinit = 0;
return 1; return 1;
} }
@ -97,7 +82,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
lua_lock(L); lua_lock(L);
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--; level--;
if (!(ci->state & CI_C)) /* Lua function? */ if (f_isLua(ci)) /* Lua function? */
level -= ci->u.l.tailcalls; /* skip lost tail calls */ level -= ci->u.l.tailcalls; /* skip lost tail calls */
} }
if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */

View File

@ -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 ** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -18,7 +18,6 @@
#define resethookcount(L) (L->hookcount = L->basehookcount) #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_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2);

47
ldo.c
View File

@ -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 ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -243,6 +243,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
cl = &clvalue(func)->l; cl = &clvalue(func)->l;
if (!cl->isC) { /* Lua function? prepare its call */ if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci; CallInfo *ci;
StkId st;
Proto *p = cl->p; Proto *p = cl->p;
if (p->is_vararg) /* varargs? */ if (p->is_vararg) /* varargs? */
adjust_varargs(L, p->numparams, func+1); 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->top = L->base + p->maxstacksize;
ci->u.l.savedpc = p->code; /* starting point */ ci->u.l.savedpc = p->code; /* starting point */
ci->u.l.tailcalls = 0; ci->u.l.tailcalls = 0;
ci->state = CI_SAVEDPC; for (st = L->top; st < ci->top; st++)
while (L->top < ci->top) setnilvalue(st);
setnilvalue(L->top++);
L->top = ci->top; L->top = ci->top;
return NULL; return NULL;
} }
@ -265,7 +265,6 @@ StkId luaD_precall (lua_State *L, StkId func) {
ci = ++L->ci; /* now `enter' new function */ ci = ++L->ci; /* now `enter' new function */
L->base = L->ci->base = restorestack(L, funcr) + 1; L->base = L->ci->base = restorestack(L, funcr) + 1;
ci->top = L->top + LUA_MINSTACK; ci->top = L->top + LUA_MINSTACK;
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);
lua_unlock(L); lua_unlock(L);
@ -279,7 +278,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
static StkId callrethooks (lua_State *L, StkId firstResult) { static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1); 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 */ while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1); 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) { void luaD_call (lua_State *L, StkId func, int nResults) {
StkId firstResult; StkId firstResult;
lua_assert(!(L->ci->state & CI_CALLING));
if (++L->nCcalls >= LUA_MAXCCALLS) { if (++L->nCcalls >= LUA_MAXCCALLS) {
if (L->nCcalls == LUA_MAXCCALLS) if (L->nCcalls == LUA_MAXCCALLS)
luaG_runerror(L, "C stack overflow"); 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); firstResult = luaD_precall(L, func);
if (firstResult == NULL) /* is a Lua function? */ 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); luaD_poscall(L, nResults, firstResult);
L->nCcalls--; L->nCcalls--;
luaC_checkGC(L); luaC_checkGC(L);
@ -333,29 +331,28 @@ static void resume (lua_State *L, void *ud) {
StkId firstResult; StkId firstResult;
int nargs = *cast(int *, ud); int nargs = *cast(int *, ud);
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
if (ci == L->base_ci) { /* no activation record? */ if (!L->isSuspended) {
if (nargs >= L->top - L->base) if (ci == L->base_ci) { /* no activation record? */
luaG_runerror(L, "cannot resume dead coroutine"); if (nargs >= L->top - L->base)
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ 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? */ else { /* resumming from previous yield */
if (ci->state & CI_C) { /* `common' yield? */ if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */ /* finish interrupted execution of `OP_CALL' */
int nresults; int nresults;
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;
luaD_poscall(L, nresults, L->top - nargs); /* complete it */ luaD_poscall(L, nresults, L->top - nargs); /* complete it */
if (nresults >= 0) L->top = L->ci->top; if (nresults >= 0) L->top = L->ci->top;
} } /* else yielded inside a hook: just continue its execution */
else { /* yielded inside a hook: just continue its execution */
ci->state &= ~CI_YIELD;
}
} }
else L->isSuspended = 0;
luaG_runerror(L, "cannot resume non-suspended coroutine"); firstResult = luaV_execute(L, L->ci - L->base_ci);
firstResult = luaV_execute(L);
if (firstResult != NULL) /* return? */ if (firstResult != NULL) /* return? */
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ 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; ci = L->ci;
if (L->nCcalls > 0) if (L->nCcalls > 0)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
if (ci->state & CI_C) { /* usual yield */ if (!f_isLua(ci)) { /* usual yield */
if ((ci-1)->state & CI_C)
luaG_runerror(L, "cannot yield a C function");
if (L->top - nresults > L->base) { /* is there garbage in the stack? */ if (L->top - nresults > L->base) { /* is there garbage in the stack? */
int i; int i;
for (i=0; i<nresults; i++) /* move down results */ for (i=0; i<nresults; i++) /* move down results */
@ -398,7 +393,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
L->top = L->base + nresults; L->top = L->base + nresults;
} }
} /* else it's an yield inside a hook: nothing to do */ } /* else it's an yield inside a hook: nothing to do */
ci->state |= CI_YIELD; L->isSuspended = 1;
lua_unlock(L); lua_unlock(L);
return -1; return -1;
} }

3
lgc.c
View File

@ -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 ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -232,7 +232,6 @@ static void traversestack (GCState *st, lua_State *L1) {
lim = L1->top; lim = L1->top;
for (ci = L1->base_ci; ci <= L1->ci; ci++) { for (ci = L1->base_ci; ci <= L1->ci; ci++) {
lua_assert(ci->top <= L1->stack_last); lua_assert(ci->top <= L1->stack_last);
lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC));
if (lim < ci->top) lim = ci->top; if (lim < ci->top) lim = ci->top;
} }
for (o = L1->stack; o < L1->top; o++) for (o = L1->stack; o < L1->top; o++)

6
lgc.h
View File

@ -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 ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -11,8 +11,8 @@
#include "lobject.h" #include "lobject.h"
#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \ #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \
if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); } luaC_collectgarbage(L); }
void luaC_separateudata (lua_State *L); void luaC_separateudata (lua_State *L);

View File

@ -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 ** Global State
** See Copyright Notice in lua.h ** 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->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci; L1->ci = L1->base_ci;
L1->ci->state = CI_C; /* not a Lua function */
setnilvalue(L1->top++); /* `function' entry for this `ci' */ setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top; L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK; L1->ci->top = L1->top + LUA_MINSTACK;
@ -128,13 +127,14 @@ static void preinit_state (lua_State *L) {
L->stacksize = 0; L->stacksize = 0;
L->errorJmp = NULL; L->errorJmp = NULL;
L->hook = NULL; L->hook = NULL;
L->hookmask = L->hookinit = 0; L->hookmask = 0;
L->basehookcount = 0; L->basehookcount = 0;
L->allowhook = 1; L->allowhook = 1;
resethookcount(L); resethookcount(L);
L->openupval = NULL; L->openupval = NULL;
L->size_ci = 0; L->size_ci = 0;
L->nCcalls = 0; L->nCcalls = 0;
L->isSuspended = 0;
L->base_ci = L->ci = NULL; L->base_ci = L->ci = NULL;
L->errfunc = 0; L->errfunc = 0;
setnilvalue(gt(L)); setnilvalue(gt(L));

View File

@ -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 ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -75,11 +75,9 @@ 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 */
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' */
int tailcalls; /* number of tail calls lost under this entry */ int tailcalls; /* number of tail calls lost under this entry */
} l; } l;
struct { /* for C functions */ struct { /* for C functions */
@ -89,20 +87,10 @@ typedef struct CallInfo {
} 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 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 */ unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask; lu_byte hookmask;
lu_byte allowhook; lu_byte allowhook;
lu_byte hookinit; lu_byte isSuspended;
int basehookcount; int basehookcount;
int hookcount; int hookcount;
lua_Hook hook; lua_Hook hook;

154
lvm.c
View File

@ -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 ** Lua virtual machine
** See Copyright Notice in lua.h ** 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; 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 (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) { if (L->hookcount == 0) {
resethookcount(L); resethookcount(L);
@ -74,25 +77,13 @@ static void traceexec (lua_State *L) {
} }
} }
if (mask & LUA_MASKLINE) { if (mask & LUA_MASKLINE) {
CallInfo *ci = L->ci;
Proto *p = ci_func(ci)->l.p; Proto *p = ci_func(ci)->l.p;
int pc = pcRel(*ci->u.l.pc, p); int npc = pcRel(pc, p);
int newline = getline(p, pc); int newline = getline(p, npc);
if (!L->hookinit) { /* call linehook when enter a new function, when jump back (loop),
luaG_inithooks(L); or when enter a new line */
if (pc != 0) /* not function start? */ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
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))) {
luaD_callhook(L, LUA_HOOKLINE, newline); 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, static StkId Arith (lua_State *L, StkId ra, const TObject *rb,
const TObject *rb, const TObject *rc, TMS op) { const TObject *rc, TMS op, const Instruction *pc) {
TObject tempb, tempc; TObject tempb, tempc;
const TObject *b, *c; const TObject *b, *c;
L->ci->u.l.savedpc = pc;
if ((b = luaV_tonumber(rb, &tempb)) != NULL && if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
(c = luaV_tonumber(rc, &tempc)) != NULL) { (c = luaV_tonumber(rc, &tempc)) != NULL) {
switch (op) { switch (op) {
@ -350,6 +342,7 @@ static void Arith (lua_State *L, StkId ra,
} }
else if (!call_binTM(L, rb, rc, ra, op)) else if (!call_binTM(L, rb, rc, ra, op))
luaG_aritherror(L, rb, rc); 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)) #define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */ /* 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 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 RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ #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)) #define dojump(pc, i) ((pc) += (i))
StkId luaV_execute (lua_State *L) { StkId luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl; LClosure *cl;
TObject *k; TObject *k;
StkId base;
const Instruction *pc; const Instruction *pc;
callentry: /* entry point when calling new functions */ callentry: /* entry point when calling new functions */
L->ci->u.l.pc = &pc;
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_SAVEDPC | CI_CALLING));
L->ci->state = CI_HASFRAME; /* activate frame */
pc = L->ci->u.l.savedpc; pc = L->ci->u.l.savedpc;
cl = &clvalue(L->base - 1)->l; base = L->base;
cl = &clvalue(base - 1)->l;
k = cl->p->k; k = cl->p->k;
/* main loop of interpreter */ /* main loop of interpreter */
for (;;) { for (;;) {
const Instruction i = *pc++; const Instruction i = *pc++;
StkId base, ra; StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L); traceexec(L, pc); /***/
if (L->ci->state & CI_YIELD) { /* did hook yield? */ if (L->isSuspended) { /* did hook yield? */
L->ci->u.l.savedpc = pc - 1; L->ci->u.l.savedpc = pc - 1;
L->ci->state = CI_YIELD | CI_SAVEDPC;
return NULL; return NULL;
} }
base = L->base;
} }
/* warning!! several calls may realloc the stack and invalidate `ra' */ /* warning!! several calls may realloc the stack and invalidate `ra' */
base = L->base;
ra = RA(i); ra = RA(i);
lua_assert(L->ci->state & CI_HASFRAME); lua_assert(base == L->ci->base && base == L->base);
lua_assert(base == L->ci->base);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= base); lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
lua_assert(L->top == L->ci->top || lua_assert(L->top == L->ci->top ||
GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
@ -441,16 +429,22 @@ StkId luaV_execute (lua_State *L) {
case OP_GETGLOBAL: { case OP_GETGLOBAL: {
TObject *rb = KBx(i); TObject *rb = KBx(i);
lua_assert(ttisstring(rb) && ttistable(&cl->g)); 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; break;
} }
case OP_GETTABLE: { 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; break;
} }
case OP_SETGLOBAL: { case OP_SETGLOBAL: {
lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); 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; break;
} }
case OP_SETUPVAL: { case OP_SETUPVAL: {
@ -459,20 +453,26 @@ StkId luaV_execute (lua_State *L) {
break; break;
} }
case OP_SETTABLE: { 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; break;
} }
case OP_NEWTABLE: { case OP_NEWTABLE: {
int b = GETARG_B(i); int b = GETARG_B(i);
b = fb2int(b); b = fb2int(b);
sethvalue(ra, luaH_new(L, b, GETARG_C(i))); 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; break;
} }
case OP_SELF: { case OP_SELF: {
StkId rb = RB(i); StkId rb = RB(i);
setobjs2s(ra+1, rb); 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; break;
} }
case OP_ADD: { case OP_ADD: {
@ -482,7 +482,7 @@ StkId luaV_execute (lua_State *L) {
setnvalue(ra, nvalue(rb) + nvalue(rc)); setnvalue(ra, nvalue(rb) + nvalue(rc));
} }
else else
Arith(L, ra, rb, rc, TM_ADD); base = Arith(L, ra, rb, rc, TM_ADD, pc); /***/
break; break;
} }
case OP_SUB: { case OP_SUB: {
@ -492,7 +492,7 @@ StkId luaV_execute (lua_State *L) {
setnvalue(ra, nvalue(rb) - nvalue(rc)); setnvalue(ra, nvalue(rb) - nvalue(rc));
} }
else else
Arith(L, ra, rb, rc, TM_SUB); base = Arith(L, ra, rb, rc, TM_SUB, pc); /***/
break; break;
} }
case OP_MUL: { case OP_MUL: {
@ -502,7 +502,7 @@ StkId luaV_execute (lua_State *L) {
setnvalue(ra, nvalue(rb) * nvalue(rc)); setnvalue(ra, nvalue(rb) * nvalue(rc));
} }
else else
Arith(L, ra, rb, rc, TM_MUL); base = Arith(L, ra, rb, rc, TM_MUL, pc); /***/
break; break;
} }
case OP_DIV: { case OP_DIV: {
@ -512,11 +512,11 @@ StkId luaV_execute (lua_State *L) {
setnvalue(ra, nvalue(rb) / nvalue(rc)); setnvalue(ra, nvalue(rb) / nvalue(rc));
} }
else else
Arith(L, ra, rb, rc, TM_DIV); base = Arith(L, ra, rb, rc, TM_DIV, pc); /***/
break; break;
} }
case OP_POW: { case OP_POW: {
Arith(L, ra, RKB(i), RKC(i), TM_POW); base = Arith(L, ra, RKB(i), RKC(i), TM_POW, pc); /***/
break; break;
} }
case OP_UNM: { case OP_UNM: {
@ -527,8 +527,10 @@ StkId luaV_execute (lua_State *L) {
} }
else { else {
setnilvalue(&temp); 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); luaG_aritherror(L, RB(i), &temp);
base = L->base;
} }
break; break;
} }
@ -540,10 +542,11 @@ StkId luaV_execute (lua_State *L) {
case OP_CONCAT: { case OP_CONCAT: {
int b = GETARG_B(i); int b = GETARG_B(i);
int c = GETARG_C(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; base = L->base;
setobjs2s(RA(i), base+b); setobjs2s(RA(i), base+b);
luaC_checkGC(L);
break; break;
} }
case OP_JMP: { case OP_JMP: {
@ -551,18 +554,24 @@ StkId luaV_execute (lua_State *L) {
break; break;
} }
case OP_EQ: { 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); else dojump(pc, GETARG_sBx(*pc) + 1);
base = L->base;
break; break;
} }
case OP_LT: { 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); else dojump(pc, GETARG_sBx(*pc) + 1);
base = L->base;
break; break;
} }
case OP_LE: { 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); else dojump(pc, GETARG_sBx(*pc) + 1);
base = L->base;
break; break;
} }
case OP_TEST: { case OP_TEST: {
@ -575,18 +584,16 @@ StkId luaV_execute (lua_State *L) {
break; break;
} }
case OP_CALL: case OP_CALL:
case OP_TAILCALL: { case OP_TAILCALL: { /***/
StkId firstResult; StkId firstResult;
int b = GETARG_B(i); int b = GETARG_B(i);
int nresults;
if (b != 0) L->top = ra+b; /* else previous instruction set top */ 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); firstResult = luaD_precall(L, ra);
if (firstResult) { if (firstResult) {
int nresults = GETARG_C(i) - 1;
if (firstResult > L->top) { /* yield? */ if (firstResult > L->top) { /* yield? */
lua_assert(L->ci->state == (CI_C | CI_YIELD));
(L->ci - 1)->u.l.savedpc = pc; (L->ci - 1)->u.l.savedpc = pc;
(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 */
@ -594,10 +601,8 @@ StkId luaV_execute (lua_State *L) {
if (nresults >= 0) L->top = L->ci->top; if (nresults >= 0) L->top = L->ci->top;
} }
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 */ nexeccalls++;
(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;
base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ 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 */ for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
setobjs2s(base+aux-1, ra+aux); setobjs2s(base+aux-1, ra+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)->u.l.tailcalls++; /* one more call lost */ (L->ci - 1)->u.l.tailcalls++; /* one more call lost */
(L->ci - 1)->state = CI_SAVEDPC;
L->ci--; /* remove new frame */ L->ci--; /* remove new frame */
L->base = L->ci->base; L->base = L->ci->base;
} }
goto callentry; goto callentry;
} }
base = L->base;
break; break;
} }
case OP_RETURN: { case OP_RETURN: {
CallInfo *ci = L->ci - 1; /* previous function frame */ CallInfo *ci = L->ci - 1; /* previous function frame */
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->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; L->ci->u.l.savedpc = pc;
/* previous function was running `here'? */ if (--nexeccalls == 0) /* was previous function running `here'? */
if (!(ci->state & CI_CALLING)) {
lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
return ra; /* no: return */ return ra; /* no: return */
}
else { /* yes: continue its execution */ else { /* yes: continue its execution */
int nresults; int nresults;
lua_assert(ci->u.l.pc == &pc && lua_assert(isLua(ci));
ttisfunction(ci->base - 1) &&
(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);
@ -653,10 +650,11 @@ StkId luaV_execute (lua_State *L) {
} }
break; break;
} }
case OP_FORPREP: { case OP_FORPREP: { /***/
const TObject *init = ra; const TObject *init = ra;
const TObject *plimit = ra+1; const TObject *plimit = ra+1;
const TObject *pstep = ra+2; const TObject *pstep = ra+2;
L->ci->u.l.savedpc = pc;
if (!tonumber(init, ra)) if (!tonumber(init, ra))
luaG_runerror(L, "`for' initial value must be a number"); luaG_runerror(L, "`for' initial value must be a number");
else if (!tonumber(plimit, ra+1)) else if (!tonumber(plimit, ra+1))
@ -673,9 +671,11 @@ StkId luaV_execute (lua_State *L) {
setobjs2s(cb+1, ra+1); setobjs2s(cb+1, ra+1);
setobjs2s(cb, ra); setobjs2s(cb, ra);
L->top = cb+3; /* func. + 2 args (state and index) */ 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; 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? */ if (ttisnil(cb)) /* break loop? */
pc++; /* skip jump (break loop) */ pc++; /* skip jump (break loop) */
else { else {
@ -732,7 +732,9 @@ StkId luaV_execute (lua_State *L) {
} }
} }
setclvalue(ra, ncl); setclvalue(ra, ncl);
luaC_checkGC(L); L->ci->u.l.savedpc = pc;
luaC_checkGC(L); /***/
base = L->base;
break; break;
} }
} }

4
lvm.h
View File

@ -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 ** Lua virtual machine
** See Copyright Notice in lua.h ** 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); int luaV_tostring (lua_State *L, StkId obj);
void luaV_gettable (lua_State *L, const TObject *t, TObject *key, StkId val); 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); 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); void luaV_concat (lua_State *L, int total, int last);
#endif #endif