Переглянути джерело

new way to control `pc' of running functions

Roberto Ierusalimschy 22 роки тому
батько
коміт
fa26d294ae
9 змінених файлів з 115 додано та 147 видалено
  1. 2 17
      ldebug.c
  2. 1 2
      ldebug.h
  3. 21 26
      ldo.c
  4. 1 2
      lgc.c
  5. 3 3
      lgc.h
  6. 3 3
      lstate.c
  7. 4 16
      lstate.h
  8. 78 76
      lvm.c
  9. 2 2
      lvm.h

+ 2 - 17
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 */

+ 1 - 2
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);

+ 21 - 26
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; 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;
     }
   } /* else it's an yield inside a hook: nothing to do */
-  ci->state |= CI_YIELD;
+  L->isSuspended = 1;
   lua_unlock(L);
   return -1;
 }

+ 1 - 2
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++)

+ 3 - 3
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);

+ 3 - 3
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));

+ 4 - 16
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;

+ 78 - 76
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;
       }
     }

+ 2 - 2
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