diff --git a/lapi.c b/lapi.c index 0f88e8de..8d4d5e7d 100644 --- a/lapi.c +++ b/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' */ diff --git a/lcorolib.c b/lcorolib.c index 95467264..49a3cf28 100644 --- a/lcorolib.c +++ b/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"); diff --git a/ldebug.c b/ldebug.c index 9b6f3bbe..5ca78bd1 100644 --- a/ldebug.c +++ b/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); } } diff --git a/ldo.c b/ldo.c index 46d6dcec..8c2fca13 100644 --- a/ldo.c +++ b/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 */ diff --git a/lstate.h b/lstate.h index 76ce110f..8b9eb606 100644 --- a/lstate.h +++ b/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; diff --git a/ltests.c b/ltests.c index 94b4cd31..d05fc3b1 100644 --- a/ltests.c +++ b/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); diff --git a/lua.h b/lua.h index eb76a27f..be99e14c 100644 --- a/lua.h +++ b/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);