Browse Source

(much) cleaner way to control function states

Roberto Ierusalimschy 23 years ago
parent
commit
5016f43aa4
6 changed files with 54 additions and 42 deletions
  1. 8 6
      ldebug.c
  2. 8 8
      ldo.c
  3. 2 2
      lstate.c
  4. 14 2
      lstate.h
  5. 21 16
      lvm.c
  6. 1 8
      lvm.h

+ 8 - 6
ldebug.c

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -28,14 +28,16 @@
 static const char *getfuncname (CallInfo *ci, const char **name);
 
 
-static int isLua (CallInfo *ci) {
-  return isLfunction (ci->base - 1);
-}
+#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->pc != &luaV_callingmark)  /* is not calling another Lua function? */
-    ci->u.l.savedpc = *ci->pc;  /* `pc' may not be saved; save it */
+  if (!(ci->state & CI_SAVEDPC)) {  /* savedpc outdated? */
+    lua_assert(ci->state & CI_HASFRAME);
+    ci->u.l.savedpc = *ci->u.l.pc;
+    ci->state |= CI_SAVEDPC;
+  }
   /* function's pc is saved */
   return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
 }

+ 8 - 8
ldo.c

@@ -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
 ** 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++) {
     ci->base = (ci->base - 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 */
   }
 }
@@ -229,6 +229,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
     ci->base = restorestack(L, funcr) + 1;
     ci->top = ci->base + p->maxstacksize;
     ci->u.l.savedpc = p->code;  /* starting point */
+    ci->state = CI_SAVEDPC;
     while (L->top < ci->top)
       setnilvalue(L->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->base = restorestack(L, funcr) + 1;
     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) {
       luaD_callhook(L, LUA_HOOKCALL, -1);
       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_lock(L);
   luaD_precall(L, L->top - (nargs+1));
-  L->ci->pc = &luaV_callingmark;  /* function is not active (yet) */
   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) {
   StkId firstResult;
   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' */
     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 ||
                GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
     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;
   lua_lock(L);
   ci = L->ci;
-  if ((ci-1)->pc == NULL)
+  if ((ci-1)->state & CI_C)
     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;
   lua_unlock(L);
   return -1;

+ 2 - 2
lstate.c

@@ -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
 ** 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->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
   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' */
   L->ci->base = L->top;
   L->ci->top = L->top + LUA_MINSTACK;

+ 14 - 2
lstate.h

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -87,10 +87,11 @@ typedef struct stringtable {
 typedef struct CallInfo {
   StkId base;  /* base for called function */
   StkId	top;  /* top for this function */
-  const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
+  int state;  /* bit fields; see below */
   union {
     struct {  /* for Lua functions */
       const Instruction *savedpc;
+      const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
       StkId *pb;  /* points to `base' variable in `luaV_execute' */
     } l;
     struct {  /* for C functions */
@@ -100,6 +101,17 @@ typedef struct 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))
 

+ 21 - 16
lvm.c

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -24,8 +24,6 @@
 #include "lvm.h"
 
 
-Instruction const *luaV_callingmark = NULL;
-
 
 /* function to convert a lua_Number to a string */
 #ifndef lua_number2str
@@ -83,16 +81,18 @@ static void traceexec (lua_State *L) {
   if (mask & LUA_MASKLINE) {
     CallInfo *ci = L->ci;
     Proto *p = ci_func(ci)->l.p;
-    int newline = getline(p, pcRel(*ci->pc, p));
-    if (pcRel(*ci->pc, p) == 0)  /* tracing may be starting now? */
-      ci->u.l.savedpc = *ci->pc;  /* initialize `savedpc' */
+    int newline = getline(p, pcRel(*ci->u.l.pc, p));
+    lua_assert(ci->state & CI_HASFRAME);
+    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) */
-    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))) {
       luaD_callhook(L, LUA_HOOKLINE, newline);
       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;
  callentry:  /* entry point when calling new functions */
   L->ci->u.l.pb = &base;
-  L->ci->pc = &pc;
-  pc = L->ci->u.l.savedpc;
+  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_HASFRAME;  /* activate frame */
+  pc = L->ci->u.l.savedpc;
   base = L->ci->base;
   cl = &clvalue(base - 1)->l;
   k = cl->p->k;
@@ -599,7 +601,7 @@ StkId luaV_execute (lua_State *L) {
         if (firstResult) {
           if (firstResult > L->top) {  /* yield? */
             (L->ci - 1)->u.l.savedpc = pc;
-            (L->ci - 1)->pc = &luaV_callingmark;
+            (L->ci - 1)->state = CI_SAVEDPC;
             return NULL;
           }
           /* 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 */
           if (GET_OPCODE(i) == OP_CALL) {  /* regular call? */
             (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 */
             int aux;
@@ -618,7 +620,9 @@ StkId luaV_execute (lua_State *L) {
             for (aux = 0; ra1+aux < L->top; aux++)  /* move frame down */
               setobj(base+aux-1, ra1+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)->state = CI_SAVEDPC;
             L->ci--;  /* remove previous frame */
           }
           goto callentry;
@@ -629,20 +633,21 @@ StkId luaV_execute (lua_State *L) {
         CallInfo *ci = L->ci - 1;
         int b = GETARG_B(i);
         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);
+        L->ci->state = CI_SAVEDPC;  /* deactivate current function */
+        L->ci->u.l.savedpc = pc;
         /* previous function was running `here'? */
-        if (ci->pc != &luaV_callingmark)
+        if (!(ci->state & CI_CALLING))
           return ra;  /* no: return */
         else {  /* yes: continue its execution (go through) */
           int nresults;
           lua_assert(ttisfunction(ci->base - 1));
+          lua_assert(ci->state & CI_SAVEDPC);
           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);
           if (nresults >= 0) L->top = L->ci->top;
-          L->ci->pc = &pc;  /* function is active again */
-          pc = L->ci->u.l.savedpc;
           goto retentry;
         }
       }

+ 1 - 8
lvm.h

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -22,13 +22,6 @@
 	(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_equalval (lua_State *L, const TObject *t1, const TObject *t2);
 const TObject *luaV_tonumber (const TObject *obj, TObject *n);