Ver código fonte

no need for field 'status' in structure 'CallInfo' (after removal
of 'lua_getctx') + field 'old_allowhook' can be packed into a single
bit

Roberto Ierusalimschy 11 anos atrás
pai
commit
542b6cfc02
3 arquivos alterados com 29 adições e 29 exclusões
  1. 3 2
      lapi.c
  2. 21 20
      ldo.c
  3. 5 7
      lstate.h

+ 3 - 2
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.214 2014/05/15 20:28:39 roberto Exp roberto $
+** $Id: lapi.c,v 2.215 2014/06/10 17:41:38 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -968,9 +968,10 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
     ci->u.c.ctx = ctx;  /* save context */
     /* save information for error recovery */
     ci->extra = savestack(L, c.func);
-    ci->u.c.old_allowhook = L->allowhook;
     ci->u.c.old_errfunc = L->errfunc;
     L->errfunc = func;
+    if (L->allowhook)
+      ci->callstatus |= CIST_OAH;  /* save original value of 'allowhook' */
     /* mark that function may do error recovery */
     ci->callstatus |= CIST_YPCALL;
     luaD_call(L, c.func, nresults, 1);  /* do the call */

+ 21 - 20
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.117 2014/06/09 16:32:18 roberto Exp roberto $
+** $Id: ldo.c,v 2.118 2014/06/10 17:41:38 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -416,7 +416,7 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
 ** Completes the execution of an interrupted C function, calling its
 ** continuation function.
 */
-static void finishCcall (lua_State *L) {
+static void finishCcall (lua_State *L, int status) {
   CallInfo *ci = L->ci;
   int n;
   lua_assert(ci->u.c.k != NULL);  /* must have a continuation */
@@ -428,12 +428,9 @@ static void finishCcall (lua_State *L) {
   /* finish 'lua_callk'/'lua_pcall' */
   adjustresults(L, ci->nresults);
   /* call continuation function */
-  if (!(ci->callstatus & CIST_STAT))  /* no call status? */
-    ci->u.c.status = LUA_YIELD;  /* 'default' status */
-  lua_assert(ci->u.c.status != LUA_OK);
-  ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
+  ci->callstatus = (ci->callstatus & ~CIST_YPCALL) | CIST_YIELDED;
   lua_unlock(L);
-  n = (*ci->u.c.k)(L, ci->u.c.status, ci->u.c.ctx);
+  n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
   lua_lock(L);
   api_checknelems(L, n);
   /* finish 'luaD_precall' */
@@ -444,13 +441,18 @@ static void finishCcall (lua_State *L) {
 /*
 ** Executes "full continuation" (everything in the stack) of a
 ** previously interrupted coroutine until the stack is empty (or another
-** interruption long-jumps out of the loop)
+** interruption long-jumps out of the loop). If the coroutine is
+** recovering from an error, 'ud' points to the error status, which must
+** be passed to the first (only the first) continuation (otherwise the
+** default status is LUA_YIELD).
 */
 static void unroll (lua_State *L, void *ud) {
-  UNUSED(ud);
+  int status = (ud) ? *(int *)ud : LUA_YIELD;
   while (L->ci != &L->base_ci) {  /* something in the stack */
-    if (!isLua(L->ci))  /* C function? */
-      finishCcall(L);  /* complete its execution */
+    if (!isLua(L->ci)) {  /* C function? */
+      finishCcall(L, status);  /* complete its execution */
+      status = LUA_YIELD;  /* back to default status */
+    }
     else {  /* Lua function */
       luaV_finishOp(L);  /* finish interrupted instruction */
       luaV_execute(L);  /* execute down to higher C 'boundary' */
@@ -487,12 +489,10 @@ static int recover (lua_State *L, int status) {
   luaF_close(L, oldtop);
   seterrorobj(L, status, oldtop);
   L->ci = ci;
-  L->allowhook = ci->u.c.old_allowhook;
+  L->allowhook = (ci->callstatus & CIST_OAH);
   L->nny = 0;  /* should be zero to be yieldable */
   luaD_shrinkstack(L);
   L->errfunc = ci->u.c.old_errfunc;
-  ci->callstatus |= CIST_STAT;  /* call has error status */
-  ci->u.c.status = status;  /* (here it is) */
   return 1;  /* continue running the coroutine */
 }
 
@@ -536,10 +536,9 @@ static void resume (lua_State *L, void *ud) {
     else {  /* 'common' yield */
       if (ci->u.c.k != NULL) {  /* does it have a continuation? */
         int n;
-        ci->u.c.status = LUA_YIELD;  /* 'default' status */
         ci->callstatus |= CIST_YIELDED;
         lua_unlock(L);
-        n = (*ci->u.c.k)(L, ci->u.c.status, ci->u.c.ctx); /* call continuation */
+        n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
         lua_lock(L);
         api_checknelems(L, n);
         firstArg = L->top - n;  /* yield results come from continuation */
@@ -563,15 +562,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
   status = luaD_rawrunprotected(L, resume, L->top - nargs);
   if (status == -1)  /* error calling 'lua_resume'? */
     status = LUA_ERRRUN;
-  else {  /* yield or regular error */
+  else {  /* yield or error running coroutine */
     while (status != LUA_OK && status != LUA_YIELD) {  /* error? */
-      if (recover(L, status))  /* recover point? */
-        status = luaD_rawrunprotected(L, unroll, NULL);  /* run continuation */
+      if (recover(L, status)) {  /* recover point? */
+        /* unroll continuation */
+        status = luaD_rawrunprotected(L, unroll, &status);
+      }
       else {  /* unrecoverable error */
         L->status = cast_byte(status);  /* mark thread as `dead' */
         seterrorobj(L, status, L->top);
         L->ci->top = L->top;
-        break;
+        break;  /* stop running it */
       }
     }
     lua_assert(status == L->status);

+ 5 - 7
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.103 2014/05/15 20:41:27 roberto Exp roberto $
+** $Id: lstate.h,v 2.104 2014/06/10 17:41:38 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -60,9 +60,9 @@ typedef struct CallInfo {
   StkId func;  /* function index in the stack */
   StkId	top;  /* top for this function */
   struct CallInfo *previous, *next;  /* dynamic call link */
+  ptrdiff_t extra;
   short nresults;  /* expected number of results from this function */
   lu_byte callstatus;
-  ptrdiff_t extra;
   union {
     struct {  /* only for Lua functions */
       StkId base;  /* base for this function */
@@ -72,8 +72,6 @@ typedef struct CallInfo {
       lua_KFunction k;  /* continuation in case of yields */
       ptrdiff_t old_errfunc;
       int ctx;  /* context info. in case of yields */
-      lu_byte old_allowhook;
-      lu_byte status;
     } c;
   } u;
 } CallInfo;
@@ -88,9 +86,9 @@ typedef struct CallInfo {
                                    luaV_execute of previous call */
 #define CIST_YIELDED	(1<<3)	/* call reentered after suspension */
 #define CIST_YPCALL	(1<<4)	/* call is a yieldable protected call */
-#define CIST_STAT	(1<<5)	/* call has an error status (pcall) */
-#define CIST_TAIL	(1<<6)	/* call was tail called */
-#define CIST_HOOKYIELD	(1<<7)	/* last hook called yielded */
+#define CIST_TAIL	(1<<5)	/* call was tail called */
+#define CIST_HOOKYIELD	(1<<6)	/* last hook called yielded */
+#define CIST_OAH	(1<<7)	/* original value of 'allowhook' */
 
 
 #define isLua(ci)	((ci)->callstatus & CIST_LUA)