From ba484b9eb16dd62a7c3a5400a66eb952b654d3f0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 10 Mar 2009 14:14:37 -0300 Subject: yielding across lua_call (first version) --- lapi.c | 22 +++++++------ lapi.h | 6 +++- lbaselib.c | 11 +++++-- ldebug.c | 4 +-- ldo.c | 103 ++++++++++++++++++++++++------------------------------------- ldo.h | 5 +-- lgc.c | 4 +-- lstate.c | 4 +-- lstate.h | 7 +++-- ltablib.c | 30 +++++++++++------- lua.h | 8 +++-- lvm.c | 72 +++++++++++++++++++++++++++++++++++------- lvm.h | 3 +- 13 files changed, 169 insertions(+), 110 deletions(-) diff --git a/lapi.c b/lapi.c index ea4d0f1f..60dc19f5 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.69 2009/02/18 17:20:56 roberto Exp roberto $ +** $Id: lapi.c,v 2.70 2009/02/19 17:15:13 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -757,21 +757,25 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { */ -#define adjustresults(L,nres) \ - { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } - - #define checkresults(L,na,nr) \ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { +LUA_API void lua_callcont (lua_State *L, int nargs, int nresults, + lua_CFunction cont) { StkId func; lua_lock(L); + /* cannot use continuations inside hooks */ + api_check(L, cont == NULL || !isLua(L->ci)); api_checknelems(L, nargs+1); checkresults(L, nargs, nresults); func = L->top - (nargs+1); - luaD_call(L, func, nresults); + if (cont) { + L->ci->u.c.cont = cont; + luaD_call(L, func, nresults, 1); + } + else + luaD_call(L, func, nresults, 0); adjustresults(L, nresults); lua_unlock(L); } @@ -789,7 +793,7 @@ struct CallS { /* data to `f_call' */ static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); + luaD_call(L, c->func, c->nresults, 0); } @@ -835,7 +839,7 @@ static void f_Ccall (lua_State *L, void *ud) { api_incr_top(L); setpvalue(L->top, c->ud); /* push only argument */ api_incr_top(L); - luaD_call(L, L->top - 2, 0); + luaD_call(L, L->top - 2, 0, 0); } diff --git a/lapi.h b/lapi.h index b9ca73bf..82ff87c6 100644 --- a/lapi.h +++ b/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.2 2005/04/25 19:24:10 roberto Exp roberto $ +** $Id: lapi.h,v 2.3 2006/07/11 15:53:29 roberto Exp roberto $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -13,4 +13,8 @@ #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top);} +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } + + #endif diff --git a/lbaselib.c b/lbaselib.c index ffa753a1..43981dc7 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.209 2009/02/06 18:38:47 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.210 2009/02/07 12:23:15 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -323,12 +323,17 @@ static int luaB_load (lua_State *L) { } +static int dofilecont (lua_State *L) { + return lua_gettop(L) - 1; +} + + static int luaB_dofile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); lua_settop(L, 1); if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L); - lua_call(L, 0, LUA_MULTRET); - return lua_gettop(L) - 1; + lua_callcont(L, 0, LUA_MULTRET, dofilecont); + return dofilecont(L); } diff --git a/ldebug.c b/ldebug.c index 6148cfcf..64ad70eb 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.42 2008/10/30 15:39:30 roberto Exp roberto $ +** $Id: ldebug.c,v 2.43 2009/03/04 13:32:29 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -628,7 +628,7 @@ void luaG_errormsg (lua_State *L) { setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top - 1, errfunc); /* push function */ incr_top(L); - luaD_call(L, L->top - 2, 1); /* call it */ + luaD_call(L, L->top - 2, 1, 0); /* call it */ } luaD_throw(L, LUA_ERRRUN); } diff --git a/ldo.c b/ldo.c index effef571..bf21e609 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.53 2009/03/03 18:51:24 roberto Exp roberto $ +** $Id: ldo.c,v 2.54 2009/03/04 13:32:29 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -14,6 +14,7 @@ #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -365,7 +366,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) { ** When returns, all the results are on the stack, starting at the original ** function position. */ -void luaD_call (lua_State *L, StkId func, int nResults) { +void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { global_State *g = G(L); if (++g->nCcalls >= LUAI_MAXCCALLS) { if (g->nCcalls == LUAI_MAXCCALLS) @@ -373,64 +374,41 @@ void luaD_call (lua_State *L, StkId func, int nResults) { else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } + if (!allowyield) L->nny++; if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ luaV_execute(L); /* call it */ + if (!allowyield) L->nny--; g->nCcalls--; luaC_checkGC(L); } +static void finishCcall (lua_State *L) { + int n; + lua_assert(L->ci->u.c.cont != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); + /* finish 'luaD_call' */ + G(L)->nCcalls--; + /* finish 'lua_callcont' */ + adjustresults(L, (L->ci + 1)->nresults); + /* call continuation function */ + lua_unlock(L); + n = (*L->ci->u.c.cont)(L); + lua_lock(L); + /* finish 'luaD_precall' */ + luaD_poscall(L, L->top - n); +} + + static void unroll (lua_State *L) { for (;;) { - Instruction inst; - luaV_execute(L); /* execute down to higher C 'boundary' */ - if (L->ci == L->base_ci) { /* stack is empty? */ - lua_assert(L->baseCcalls == G(L)->nCcalls); + if (L->ci == L->base_ci) /* stack is empty? */ return; /* coroutine finished normally */ - } - L->baseCcalls--; /* undo increment that allows yields */ - inst = *(L->savedpc - 1); /* interrupted instruction */ - switch (GET_OPCODE(inst)) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: - case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: - case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: { - setobjs2s(L, L->base + GETARG_A(inst), --L->top); - break; - } - case OP_LE: case OP_LT: case OP_EQ: { - int res = !l_isfalse(L->top - 1); - L->top--; - /* metamethod should not be called when operand is K */ - lua_assert(!ISK(GETARG_B(inst))); - if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ - ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) - res = !res; /* invert result */ - lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); - if (res != GETARG_A(inst)) /* condition failed? */ - L->savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top - 1; /* top when __concat was called */ - int last = cast_int(top - L->base) - 2; /* last element and ... */ - int b = GETARG_B(inst); /* ... first element to concatenate */ - int total = last - b + 1; /* number of elements to concatenate */ - setobj2s(L, top - 2, top); /* put TM result in proper position */ - L->top = L->ci->top; /* correct top */ - if (total > 1) /* are there elements to concat? */ - luaV_concat(L, total, last); /* concat them (may yield again) */ - /* move final result to final position */ - setobj2s(L, L->base + GETARG_A(inst), L->base + b); - continue; - } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); - L->top = L->ci->top; /* correct top */ - break; - } - case OP_SETGLOBAL: case OP_SETTABLE: - break; /* nothing to be done */ - default: lua_assert(0); + if (!isLua(L->ci)) /* C function? */ + finishCcall(L); + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ } } } @@ -441,23 +419,22 @@ static void resume (lua_State *L, void *ud) { CallInfo *ci = L->ci; if (L->status == LUA_OK) { /* start coroutine? */ lua_assert(ci == L->base_ci && firstArg > L->base); - if (luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* C function? */ - return; /* done */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ } else { /* resuming from previous yield */ lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; - if (isLua(ci)) /* yielded inside a hook? */ + if (isLua(ci)) { /* yielded inside a hook? */ L->base = L->ci->base; /* just continue its execution */ + luaV_execute(L); + } else { /* 'common' yield */ - /* finish interrupted execution of `OP_CALL' */ - lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || - GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); - if (luaD_poscall(L, firstArg)) /* complete it... */ - L->top = L->ci->top; /* and correct top if not multiple results */ + G(L)->nCcalls--; /* finish 'luaD_call' */ + luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ } + unroll(L); } - unroll(L); } @@ -484,7 +461,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) { if (G(L)->nCcalls >= LUAI_MAXCCALLS) return resume_error(L, "C stack overflow"); ++G(L)->nCcalls; /* count resume */ - L->baseCcalls += G(L)->nCcalls; + L->nny = 0; /* allow yields */ status = luaD_rawrunprotected(L, resume, L->top - nargs); if (status != LUA_OK && status != LUA_YIELD) { /* error? */ L->status = cast_byte(status); /* mark thread as `dead' */ @@ -494,7 +471,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) { else { lua_assert(status == L->status); } - L->baseCcalls -= G(L)->nCcalls; + L->nny = 1; /* do not allow yields */ --G(L)->nCcalls; lua_unlock(L); return status; @@ -504,7 +481,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) { LUA_API int lua_yield (lua_State *L, int nresults) { luai_userstateyield(L, nresults); lua_lock(L); - if (G(L)->nCcalls > L->baseCcalls) + if (L->nny > 0) luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); L->base = L->top - nresults; /* protect stack slots below */ L->status = LUA_YIELD; @@ -521,6 +498,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, int status; ptrdiff_t old_ci = saveci(L, L->ci); lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = ef; status = luaD_rawrunprotected(L, func, u); @@ -532,6 +510,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, L->base = L->ci->base; L->savedpc = L->ci->savedpc; L->allowhook = old_allowhooks; + L->nny = old_nny; restore_stack_limit(L); } L->errfunc = old_errfunc; diff --git a/ldo.h b/ldo.h index ad86a09c..c600bfe4 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.9 2008/07/03 14:24:36 roberto Exp roberto $ +** $Id: ldo.h,v 2.10 2008/08/13 17:02:42 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -34,7 +34,8 @@ typedef void (*Pfunc) (lua_State *L, void *ud); LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, + int allowyield); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); diff --git a/lgc.c b/lgc.c index 1fd19973..482375d0 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.47 2008/06/26 19:42:45 roberto Exp roberto $ +** $Id: lgc.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -601,7 +601,7 @@ static Udata *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_call(L, L->top - 2, 0); + luaD_call(L, L->top - 2, 0, 0); } diff --git a/lstate.c b/lstate.c index e1a3237b..df62f3e3 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $ +** $Id: lstate.c,v 2.49 2009/02/18 17:20:56 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -95,7 +95,7 @@ static void preinit_state (lua_State *L, global_State *g) { resethookcount(L); L->openupval = NULL; L->size_ci = 0; - L->baseCcalls = 0; + L->nny = 1; L->status = LUA_OK; L->base_ci = L->ci = NULL; L->savedpc = NULL; diff --git a/lstate.h b/lstate.h index 174446dc..f27631d0 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.37 2009/02/18 17:20:56 roberto Exp roberto $ +** $Id: lstate.h,v 2.38 2009/03/04 13:32:29 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -87,6 +87,9 @@ typedef struct CallInfo { struct { /* only for Lua functions */ int tailcalls; /* number of tail calls lost under this entry */ } l; + struct { /* only for C functions */ + lua_CFunction cont; /* continuation in case of yields */ + } c; } u; } CallInfo; @@ -160,7 +163,7 @@ struct lua_State { CallInfo *base_ci; /* array of CallInfo's */ int stacksize; int size_ci; /* size of array `base_ci' */ - unsigned short baseCcalls; /* number of nested C calls when resuming */ + unsigned short nny; /* number of non-yieldable calls in stack */ lu_byte hookmask; lu_byte allowhook; int basehookcount; diff --git a/ltablib.c b/ltablib.c index ab83c0c8..7296fb38 100644 --- a/ltablib.c +++ b/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.43 2008/02/14 16:03:27 roberto Exp roberto $ +** $Id: ltablib.c,v 1.44 2008/04/07 18:43:00 roberto Exp roberto $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -36,20 +36,28 @@ static int foreachi (lua_State *L) { } -static int foreach (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pushvalue(L, 2); /* function */ - lua_pushvalue(L, -3); /* key */ - lua_pushvalue(L, -3); /* value */ - lua_call(L, 2, 1); +static int foreachcont (lua_State *L) { + for (;;) { if (!lua_isnil(L, -1)) return 1; lua_pop(L, 2); /* remove value and result */ + if (lua_next(L, 1) == 0) /* no more elements? */ + return 0; + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_callcont(L, 2, 1, &foreachcont); } - return 0; +} + + +static int foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + lua_pushnil(L); /* first value */ + lua_pushnil(L); /* first "return" */ + return foreachcont(L); } diff --git a/lua.h b/lua.h index 82101882..13d067a5 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.231 2008/08/13 14:08:49 roberto Exp roberto $ +** $Id: lua.h,v 1.232 2009/02/18 17:20:56 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -203,7 +203,9 @@ LUA_API int (lua_setfenv) (lua_State *L, int idx); /* ** 'load' and 'call' functions (load and run Lua code) */ -LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API void (lua_callcont) (lua_State *L, int nargs, int nresults, + lua_CFunction cont); + LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, @@ -281,6 +283,8 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) +#define lua_call(L,n,r) lua_callcont(L, (n), (r), NULL); + /* diff --git a/lvm.c b/lvm.c index 2b54266f..494b40cd 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.82 2009/03/02 16:34:23 roberto Exp roberto $ +** $Id: lvm.c,v 2.83 2009/03/04 13:32:29 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -79,17 +79,14 @@ static void traceexec (lua_State *L) { static void callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, TValue *p3, int hasres) { ptrdiff_t result = savestack(L, p3); - int oldbase = L->baseCcalls; setobj2s(L, L->top++, f); /* push function */ setobj2s(L, L->top++, p1); /* 1st argument */ setobj2s(L, L->top++, p2); /* 2nd argument */ if (!hasres) /* no result? 'p3' is third argument */ setobj2s(L, L->top++, p3); /* 3th argument */ luaD_checkstack(L, 0); - if (isLua(L->ci)) /* metamethod invoked from a Lua function? */ - L->baseCcalls++; /* allow it to yield */ - luaD_call(L, L->top - (4 - hasres), hasres); - L->baseCcalls = oldbase; + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); if (hasres) { /* if has result, move it to its place */ p3 = restorestack(L, result); setobjs2s(L, p3, --L->top); @@ -356,6 +353,61 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, } +/* +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + Instruction inst = *(L->savedpc - 1); /* interrupted instruction */ + switch (GET_OPCODE(inst)) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: + case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: + case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, L->base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + /* metamethod should not be called when operand is K */ + lua_assert(!ISK(GETARG_B(inst))); + if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ + ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) + res = !res; /* invert result */ + lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + L->savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when __concat was called */ + int last = cast_int(top - L->base) - 2; /* last element and ... */ + int b = GETARG_B(inst); /* ... first element to concatenate */ + int total = last - b + 1; /* number of elements to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + L->top = L->ci->top; /* correct top */ + if (total > 1) /* are there elements to concat? */ + luaV_concat(L, total, last); /* concat them (may yield again) */ + /* move final result to final position */ + setobj2s(L, L->base + GETARG_A(inst), L->base + b); + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); + L->top = L->ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = L->ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + /* ** some macros for common tasks in `luaV_execute' @@ -672,11 +724,9 @@ void luaV_execute (lua_State *L) { setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); - L->baseCcalls++; /* allow yields */ L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i))); + Protect(luaD_call(L, cb, GETARG_C(i), 1)); L->top = L->ci->top; - L->baseCcalls--; i = *(L->savedpc++); /* go to next instruction */ ra = RA(i); lua_assert(GET_OPCODE(i) == OP_TFORLOOP); @@ -725,8 +775,8 @@ void luaV_execute (lua_State *L) { ncl = luaF_newLclosure(L, nup, cl->env); ncl->l.p = p; setclvalue(L, ra, ncl); - for (j=0; jsavedpc++) { - Instruction u = *L->savedpc; + for (j=0; jsavedpc++; if (GET_OPCODE(u) == OP_GETUPVAL) ncl->l.upvals[j] = cl->upvals[GETARG_B(u)]; else { diff --git a/lvm.h b/lvm.h index 8a3ae994..2d68f406 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.6 2007/02/09 13:04:52 roberto Exp roberto $ +** $Id: lvm.h,v 2.7 2008/08/26 13:27:42 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -32,6 +32,7 @@ LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); +LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); -- cgit v1.2.3-55-g6feb