浏览代码

new API for 'lua_resume' + cleaning the uses of the 'extra' field in
'CallInfo'

Roberto Ierusalimschy 7 年之前
父节点
当前提交
ba36180fd7
共有 7 个文件被更改,包括 31 次插入58 次删除
  1. 3 4
      lapi.c
  2. 3 4
      lcorolib.c
  3. 1 24
      ldebug.c
  4. 8 6
      ldo.c
  5. 5 8
      lstate.h
  6. 8 10
      ltests.c
  7. 3 2
      lua.h

+ 3 - 4
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.271 2017/10/11 12:38:45 roberto Exp roberto $
+** $Id: lapi.c,v 2.272 2017/11/01 18:20:48 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -58,10 +58,9 @@ const char lua_ident[] =
 
 
 static TValue *index2value (lua_State *L, int idx) {
-  CallInfo *ci = L->ci;
   if (idx > 0) {
     StkId o = L->func + idx;
-    api_check(L, idx <= ci->top - (L->func + 1), "unacceptable index");
+    api_check(L, idx <= L->ci->top - (L->func + 1), "unacceptable index");
     if (o >= L->top) return NONVALIDVALUE;
     else return s2v(o);
   }
@@ -1000,7 +999,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
     ci->u.c.k = k;  /* save continuation */
     ci->u.c.ctx = ctx;  /* save context */
     /* save information for error recovery */
-    ci->extra = savestack(L, c.func);
+    ci->u2.funcidx = savestack(L, c.func);
     ci->u.c.old_errfunc = L->errfunc;
     L->errfunc = func;
     setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */

+ 3 - 4
lcorolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp roberto $
+** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp roberto $
 ** Coroutine Library
 ** See Copyright Notice in lua.h
 */
@@ -26,7 +26,7 @@ static lua_State *getco (lua_State *L) {
 
 
 static int auxresume (lua_State *L, lua_State *co, int narg) {
-  int status;
+  int status, nres;
   if (!lua_checkstack(co, narg)) {
     lua_pushliteral(L, "too many arguments to resume");
     return -1;  /* error flag */
@@ -36,9 +36,8 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
     return -1;  /* error flag */
   }
   lua_xmove(L, co, narg);
-  status = lua_resume(co, L, narg);
+  status = lua_resume(co, L, narg, &nres);
   if (status == LUA_OK || status == LUA_YIELD) {
-    int nres = lua_gettop(co);
     if (!lua_checkstack(L, nres + 1)) {
       lua_pop(co, nres);  /* remove results anyway */
       lua_pushliteral(L, "too many results to resume");

+ 1 - 24
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.133 2017/10/31 17:14:02 roberto Exp roberto $
+** $Id: ldebug.c,v 2.134 2017/11/01 18:20:48 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -106,22 +106,6 @@ static int currentline (CallInfo *ci) {
 }
 
 
-/*
-** If function yielded, its 'func' can be in the 'extra' field. The
-** next function restores 'func' to its correct value for debugging
-** purposes. (It exchanges 'func' and 'extra'; so, when called again,
-** after debugging, it also "re-restores" ** 'func' to its altered value.
-*/
-static void swapextra (lua_State *L) {
-  if (L->status == LUA_YIELD) {
-    CallInfo *ci = L->ci;  /* get function that yielded */
-    StkId temp = ci->func;  /* exchange its 'func' and 'extra' values */
-    L->func = ci->func = restorestack(L, ci->extra);
-    ci->extra = savestack(L, temp);
-  }
-}
-
-
 /*
 ** This function can be called asynchronously (e.g. during a signal).
 ** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
@@ -209,7 +193,6 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n,
 LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
   const char *name;
   lua_lock(L);
-  swapextra(L);
   if (ar == NULL) {  /* information about non-active function? */
     if (!isLfunction(s2v(L->top - 1)))  /* not a Lua function? */
       name = NULL;
@@ -224,7 +207,6 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
       api_incr_top(L);
     }
   }
-  swapextra(L);
   lua_unlock(L);
   return name;
 }
@@ -234,13 +216,11 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
   StkId pos = NULL;  /* to avoid warnings */
   const char *name;
   lua_lock(L);
-  swapextra(L);
   name = findlocal(L, ar->i_ci, n, &pos);
   if (name) {
     setobjs2s(L, pos, L->top - 1);
     L->top--;  /* pop value */
   }
-  swapextra(L);
   lua_unlock(L);
   return name;
 }
@@ -361,7 +341,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
   CallInfo *ci;
   TValue *func;
   lua_lock(L);
-  swapextra(L);
   if (*what == '>') {
     ci = NULL;
     func = s2v(L->top - 1);
@@ -380,7 +359,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
     setobj2s(L, L->top, func);
     api_incr_top(L);
   }
-  swapextra(L);  /* correct before option 'L', which can raise a mem. error */
   if (strchr(what, 'L'))
     collectvalidlines(L, cl);
   lua_unlock(L);
@@ -790,7 +768,6 @@ void luaG_traceexec (lua_State *L) {
       L->hookcount = 1;  /* undo decrement to zero */
     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
-    L->func = ci->func = L->top - 1;  /* protect stack below results */
     luaD_throw(L, LUA_YIELD);
   }
 }

+ 8 - 6
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.163 2017/10/31 17:54:35 roberto Exp roberto $
+** $Id: ldo.c,v 2.164 2017/11/01 18:20:48 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -559,7 +559,7 @@ static int recover (lua_State *L, int status) {
   CallInfo *ci = findpcall(L);
   if (ci == NULL) return 0;  /* no recovery point */
   /* "finish" luaD_pcall */
-  oldtop = restorestack(L, ci->extra);
+  oldtop = restorestack(L, ci->u2.funcidx);
   luaF_close(L, oldtop);
   seterrorobj(L, status, oldtop);
   L->ci = ci;
@@ -604,7 +604,6 @@ static void resume (lua_State *L, void *ud) {
   else {  /* resuming from previous yield */
     lua_assert(L->status == LUA_YIELD);
     L->status = LUA_OK;  /* mark that it is running (again) */
-    L->func = ci->func = restorestack(L, ci->extra);
     if (isLua(ci))  /* yielded inside a hook? */
       luaV_execute(L);  /* just continue running Lua code */
     else {  /* 'common' yield */
@@ -622,7 +621,8 @@ static void resume (lua_State *L, void *ud) {
 }
 
 
-LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
+LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
+                                      int *nresults) {
   int status;
   unsigned short oldnny = L->nny;  /* save "number of non-yieldable" calls */
   lua_lock(L);
@@ -653,6 +653,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
     }
     else lua_assert(status == L->status);  /* normal end or yield */
   }
+  *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
+                                    : L->top - (L->func + 1);
   L->nny = oldnny;  /* restore 'nny' */
   L->nCcalls--;
   lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
@@ -679,14 +681,14 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
       luaG_runerror(L, "attempt to yield from outside a coroutine");
   }
   L->status = LUA_YIELD;
-  ci->extra = savestack(L, L->func);  /* save current 'func' */
   if (isLua(ci)) {  /* inside a hook? */
     api_check(L, k == NULL, "hooks cannot continue after yielding");
+    ci->u2.nyield = 0;  /* no results */
   }
   else {
     if ((ci->u.c.k = k) != NULL)  /* is there a continuation? */
       ci->u.c.ctx = ctx;  /* save context */
-    L->func = ci->func = L->top - nresults - 1;  /* protect stack below results */
+    ci->u2.nyield = nresults;  /* save number of results */
     luaD_throw(L, LUA_YIELD);
   }
   lua_assert(ci->callstatus & CIST_HOOKED);  /* must be inside a hook */

+ 5 - 8
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.144 2017/07/27 13:50:16 roberto Exp roberto $
+** $Id: lstate.h,v 2.145 2017/10/31 17:54:35 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -83,12 +83,6 @@ typedef struct stringtable {
 
 /*
 ** Information about a call.
-** When a thread yields, 'func' is adjusted to pretend that the
-** top function has only the yielded values in its stack; in that
-** case, the actual 'func' value is saved in field 'extra'.
-** When a function calls another with a continuation, 'extra' keeps
-** the function index so that, in case of errors, the continuation
-** function can be called with the correct top.
 */
 typedef struct CallInfo {
   StkId func;  /* function index in the stack */
@@ -104,7 +98,10 @@ typedef struct CallInfo {
       lua_KContext ctx;  /* context info. in case of yields */
     } c;
   } u;
-  ptrdiff_t extra;
+  union {
+    ptrdiff_t funcidx;  /* called-function index */
+    int nyield;  /* number of values yielded */
+  } u2;
   short nresults;  /* expected number of results from this function */
   unsigned short callstatus;
 } CallInfo;

+ 8 - 10
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.225 2017/10/04 21:56:32 roberto Exp roberto $
+** $Id: ltests.c,v 2.226 2017/11/01 18:20:48 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -309,13 +309,10 @@ static void checkLclosure (global_State *g, LClosure *cl) {
 }
 
 
-static int lua_checkpc (lua_State *L, CallInfo *ci) {
+static int lua_checkpc (CallInfo *ci) {
   if (!isLua(ci)) return 1;
   else {
-    /* if function yielded (inside a hook), real 'func' is in 'extra' field */
-    StkId f = (L->status != LUA_YIELD || ci != L->ci)
-              ? ci->func
-              : restorestack(L, ci->extra);
+    StkId f = ci->func;
     Proto *p = clLvalue(s2v(f))->p;
     return p->code <= ci->u.l.savedpc &&
            ci->u.l.savedpc <= p->code + p->sizecode;
@@ -332,7 +329,7 @@ static void checkstack (global_State *g, lua_State *L1) {
     lua_assert(upisopen(uv));  /* must be open */
   for (ci = L1->ci; ci != NULL; ci = ci->previous) {
     lua_assert(ci->top <= L1->stack_last);
-    lua_assert(lua_checkpc(L1, ci));
+    lua_assert(lua_checkpc(ci));
   }
   if (L1->stack) {  /* complete thread? */
     for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++)
@@ -1411,7 +1408,8 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
     }
     else if EQ("resume") {
       int i = getindex;
-      status = lua_resume(lua_tothread(L1, i), L, getnum);
+      int nres;
+      status = lua_resume(lua_tothread(L1, i), L, getnum, &nres);
     }
     else if EQ("return") {
       int n = getnum;
@@ -1616,10 +1614,10 @@ static int sethook (lua_State *L) {
 
 
 static int coresume (lua_State *L) {
-  int status;
+  int status, nres;
   lua_State *co = lua_tothread(L, 1);
   luaL_argcheck(L, co, 1, "coroutine expected");
-  status = lua_resume(co, L, 0);
+  status = lua_resume(co, L, 0, &nres);
   if (status != LUA_OK && status != LUA_YIELD) {
     lua_pushboolean(L, 0);
     lua_insert(L, -2);

+ 3 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.335 2017/05/26 19:14:29 roberto Exp roberto $
+** $Id: lua.h,v 1.336 2017/07/27 13:36:54 roberto Exp roberto $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -288,7 +288,8 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
 */
 LUA_API int  (lua_yieldk)     (lua_State *L, int nresults, lua_KContext ctx,
                                lua_KFunction k);
-LUA_API int  (lua_resume)     (lua_State *L, lua_State *from, int narg);
+LUA_API int  (lua_resume)     (lua_State *L, lua_State *from, int narg,
+                               int *nres);
 LUA_API int  (lua_status)     (lua_State *L);
 LUA_API int (lua_isyieldable) (lua_State *L);