From b1379936cf35787d3ef3aab82d1607a3e1562eef Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 9 Feb 2018 13:16:06 -0200 Subject: [PATCH] vararg back to '...' (but with another implementation) new implementation should have zero overhead for non-vararg functions --- lcode.c | 26 +++++++++++------------ ldebug.c | 26 ++++++++++++++++++----- ldo.c | 37 +++++++++++++++------------------ ldo.h | 10 ++++++++- lopcodes.c | 4 +++- lopcodes.h | 10 +++++---- lparser.c | 22 ++++++-------------- lstate.h | 3 ++- ltm.c | 61 +++++++++++++++++++++++------------------------------- ltm.h | 10 +++++---- lvm.c | 40 +++++++++++++++++++++++------------ 11 files changed, 136 insertions(+), 113 deletions(-) diff --git a/lcode.c b/lcode.c index 7f240580..25fb0770 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.151 2018/01/27 16:56:33 roberto Exp roberto $ +** $Id: lcode.c,v 2.152 2018/01/28 15:13:26 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -31,7 +31,7 @@ /* Maximum number of registers in a Lua function (must fit in 8 bits) */ -#define MAXREGS 255 +#define MAXREGS 254 #define hasjumps(e) ((e)->t != (e)->f) @@ -157,17 +157,17 @@ int luaK_jump (FuncState *fs) { ** Code a 'return' instruction */ void luaK_ret (FuncState *fs, int first, int nret) { - switch (nret) { - case 0: - luaK_codeABC(fs, OP_RETURN0, 0, 0, 0); - break; - case 1: - luaK_codeABC(fs, OP_RETURN1, first, 0, 0); - break; - default: - luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0); - break; + OpCode op; + if (fs->f->is_vararg) + op = OP_RETVARARG; + else { + switch (nret) { + case 0: op = OP_RETURN0; break; + case 1: op = OP_RETURN1; break; + default: op = OP_RETURN; break; + } } + luaK_codeABC(fs, op, first, nret + 1, fs->f->numparams); } @@ -1647,7 +1647,7 @@ void luaK_finish (FuncState *fs) { lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); switch (GET_OPCODE(*pc)) { case OP_RETURN: case OP_RETURN0: case OP_RETURN1: - case OP_TAILCALL: { + case OP_RETVARARG: case OP_TAILCALL: { if (p->sizep > 0) SETARG_k(*pc, 1); /* signal that they must close upvalues */ break; diff --git a/ldebug.c b/ldebug.c index 93a935a5..3ddac547 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.152 2018/01/10 12:02:35 roberto Exp roberto $ +** $Id: ldebug.c,v 2.153 2018/02/06 19:16:56 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -187,12 +187,28 @@ static const char *upvalname (Proto *p, int uv) { } +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + if (clLvalue(s2v(ci->func))->p->is_vararg) { + int nextra = ci->u.l.nextraargs; + if (n <= nextra) { + *pos = ci->func - nextra + (n - 1); + return "(*vararg)"; /* generic name for any vararg */ + } + } + return NULL; /* no such vararg */ +} + + static const char *findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { StkId base = ci->func + 1; - const char *name = (isLua(ci)) - ? luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)) - : NULL; + const char *name = NULL; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } if (name == NULL) { /* no 'standard' name? */ StkId limit = (ci == L->ci) ? L->top : ci->next->func; if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ @@ -324,7 +340,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, } else { ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams + f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; } break; } diff --git a/ldo.c b/ldo.c index 402b3703..64512487 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.191 2018/02/07 15:18:04 roberto Exp roberto $ +** $Id: ldo.c,v 2.192 2018/02/07 15:55:18 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -310,7 +310,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { } -static void rethook (lua_State *L, CallInfo *ci) { +void luaD_rethook (lua_State *L, CallInfo *ci) { if (isLuacode(ci)) L->top = ci->top; /* prepare top */ if (L->hookmask & LUA_MASKRET) /* is return hook on? */ @@ -343,8 +343,8 @@ void luaD_tryfuncTM (lua_State *L, StkId func) { ** expressions, multiple results for tail calls/single parameters) ** separated. */ -static void moveresults (lua_State *L, StkId firstResult, StkId res, - int nres, int wanted) { +void luaD_moveresults (lua_State *L, StkId firstResult, StkId res, + int nres, int wanted) { switch (wanted) { /* handle typical cases separately */ case 0: break; /* nothing to move */ case 1: { /* one result needed */ @@ -382,27 +382,22 @@ static void moveresults (lua_State *L, StkId firstResult, StkId res, /* ** Finishes a function call: calls hook if necessary, removes CallInfo, -** moves current number of results to proper place; returns 0 iff call -** wanted multiple (variable number of) results. +** moves current number of results to proper place. */ void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { if (L->hookmask) { ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ - rethook(L, ci); + luaD_rethook(L, ci); firstResult = restorestack(L, fr); } L->ci = ci->previous; /* back to caller */ /* move results to proper place */ - moveresults(L, firstResult, ci->func, nres, ci->nresults); + luaD_moveresults(L, firstResult, ci->func, nres, ci->nresults); } -#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) - - -#define checkstackGC(L,fsize) \ - luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) /* @@ -438,8 +433,6 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { void luaD_call (lua_State *L, StkId func, int nresults) { lua_CFunction f; TValue *funcv = s2v(func); - CallInfo *ci = next_ci(L); - ci->nresults = nresults; switch (ttype(funcv)) { case LUA_TCCL: /* C closure */ f = clCvalue(funcv)->f; @@ -448,12 +441,14 @@ void luaD_call (lua_State *L, StkId func, int nresults) { f = fvalue(funcv); Cfunc: { int n; /* number of returns */ + CallInfo *ci; checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + ci = next_ci(L); + ci->nresults = nresults; ci->callstatus = CIST_C; ci->top = L->top + LUA_MINSTACK; ci->func = func; lua_assert(ci->top <= L->stack_last); - L->ci = ci; /* now 'enter' new function */ if (L->hookmask & LUA_MASKCALL) luaD_hook(L, LUA_HOOKCALL, -1); lua_unlock(L); @@ -464,18 +459,20 @@ void luaD_call (lua_State *L, StkId func, int nresults) { break; } case LUA_TLCL: { /* Lua function */ + CallInfo *ci; Proto *p = clLvalue(funcv)->p; int narg = cast_int(L->top - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ - ci->u.l.savedpc = p->code; /* starting point */ checkstackp(L, fsize, func); - for (; narg < nfixparams; narg++) - setnilvalue(s2v(L->top++)); /* complete missing arguments */ + ci = next_ci(L); + ci->nresults = nresults; + ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = 0; ci->top = func + 1 + fsize; ci->func = func; - L->ci = ci; /* now 'enter' new function */ + for (; narg < nfixparams; narg++) + setnilvalue(s2v(L->top++)); /* complete missing arguments */ lua_assert(ci->top <= L->stack_last); luaV_execute(L, ci); /* run the function */ break; diff --git a/ldo.h b/ldo.h index 44e3af20..864cf3e6 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.39 2018/01/10 19:19:27 roberto Exp roberto $ +** $Id: ldo.h,v 2.40 2018/02/06 19:16:56 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -42,6 +42,11 @@ p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ +/* macro to check stack size and GC */ +#define checkstackGC(L,fsize) \ + luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) + + /* type of protected functions, to be ran by 'runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); @@ -57,7 +62,10 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres); +LUAI_FUNC void luaD_rethook (lua_State *L, CallInfo *ci); LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); +LUAI_FUNC void luaD_moveresults (lua_State *L, StkId firstResult, StkId res, + int nres, int wanted); LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); LUAI_FUNC void luaD_shrinkstack (lua_State *L); LUAI_FUNC void luaD_inctop (lua_State *L); diff --git a/lopcodes.c b/lopcodes.c index cd85f1a9..d04e707f 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.75 2017/12/22 14:16:46 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.76 2018/02/07 15:18:04 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -80,6 +80,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "CALL", "TAILCALL", "RETURN", + "RETVARARG", "RETURN0", "RETURN1", "FORLOOP1", @@ -161,6 +162,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ + ,opmode(0, 1, 0, 0, iABC) /* OP_RETVARARG */ ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */ ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */ ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */ diff --git a/lopcodes.h b/lopcodes.h index 47c72c69..3c7a9573 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.184 2018/01/28 15:13:26 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.186 2018/02/07 15:18:04 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -268,6 +268,7 @@ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ +OP_RETVARARG,/* A B return R(A), ... ,R(A+B-2) (see note) */ OP_RETURN0,/* return */ OP_RETURN1,/* A return R(A) */ @@ -286,7 +287,7 @@ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ -OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ +OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg */ OP_PREPVARARG,/*A (adjust vararg parameters) */ @@ -305,9 +306,10 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ OP_SETLIST) may use 'top'. (*) In OP_VARARG, if (C == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). B is the vararg parameter. + set top (like in OP_CALL with C == 0). - (*) In OP_RETURN, if (B == 0) then return up to 'top'. + (*) In OP_RETURN/OP_RETVARARG, if (B == 0) then return up to 'top'. + (OP_RETVARARG is the return instruction for vararg functions.) (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then next 'instruction' is EXTRAARG(real C). diff --git a/lparser.c b/lparser.c index aab03dc8..802c64bd 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.175 2017/12/22 14:16:46 roberto Exp roberto $ +** $Id: lparser.c,v 2.176 2018/02/07 15:18:04 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -568,6 +568,7 @@ static void close_func (LexState *ls) { Proto *f = fs->f; luaK_ret(fs, 0, 0); /* final return */ leaveblock(fs); + lua_assert(fs->bl == NULL); luaK_finish(fs); luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction); luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); @@ -577,7 +578,8 @@ static void close_func (LexState *ls) { luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - lua_assert(fs->bl == NULL); + if (f->is_vararg) + f->maxstacksize++; /* ensure space to copy the function */ ls->fs = fs->prev; luaC_checkGC(L); } @@ -781,11 +783,6 @@ static void parlist (LexState *ls) { } case TK_DOTS: { /* param -> '...' */ luaX_next(ls); - if (testnext(ls, '=')) - new_localvar(ls, str_checkname(ls)); - else - new_localvarliteral(ls, "_ARG"); - nparams++; isvararg = 1; break; } @@ -795,10 +792,8 @@ static void parlist (LexState *ls) { } adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar); - if (isvararg) { - f->numparams--; /* exclude vararg parameter */ + if (isvararg) setvararg(fs, f->numparams); /* declared vararg */ - } luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ } @@ -984,10 +979,9 @@ static void simpleexp (LexState *ls, expdesc *v) { } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; - int lastparam = fs->f->numparams; check_condition(ls, fs->f->is_vararg, "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, lastparam, 1)); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); break; } case '{': { /* constructor */ @@ -1703,10 +1697,6 @@ static void mainfunc (LexState *ls, FuncState *fs) { expdesc v; open_func(ls, fs, &bl); setvararg(fs, 0); /* main function is always declared vararg */ - fs->f->numparams = 0; - new_localvarliteral(ls, "_ARG"); - adjustlocalvars(ls, 1); - luaK_reserveregs(fs, 1); /* reserve register for vararg */ init_exp(&v, VLOCAL, 0); /* create and... */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaX_next(ls); /* read first token */ diff --git a/lstate.h b/lstate.h index bc4df4e5..2cce8e4f 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.152 2017/11/23 16:35:54 roberto Exp roberto $ +** $Id: lstate.h,v 2.153 2017/12/19 16:40:17 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -92,6 +92,7 @@ typedef struct CallInfo { struct { /* only for Lua functions */ const Instruction *savedpc; l_signalT trap; + int nextraargs; /* # of extra arguments in vararg functions */ } l; struct { /* only for C functions */ lua_KFunction k; /* continuation in case of yields */ diff --git a/ltm.c b/ltm.c index f36f4625..d88b636b 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.58 2018/01/28 13:39:52 roberto Exp roberto $ +** $Id: ltm.c,v 2.59 2018/02/07 15:18:04 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -216,41 +216,32 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, } -void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) { +void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci) { int i; - Table *vtab; - TValue nname; - int actual = cast_int(L->top - base); /* number of arguments */ + int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ int nextra = actual - nfixparams; /* number of extra arguments */ - vtab = luaH_new(L); /* create vararg table */ - sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ - L->top++; /* space ensured by caller */ - luaH_resize(L, vtab, nextra, 1); - for (i = 0; i < nextra; i++) /* put extra arguments into vararg table */ - setobj2n(L, &vtab->array[i], s2v(L->top - nextra + i - 1)); - setsvalue(L, &nname, G(L)->nfield); /* get field 'n' */ - setivalue(luaH_set(L, vtab, &nname), nextra); /* store counter there */ - L->top -= nextra; /* remove extra elements from the stack */ - sethvalue2s(L, L->top - 1, vtab); /* move table to new top */ - luaC_checkGC(L); -} - - -void luaT_getvarargs (lua_State *L, TValue *t, StkId where, int wanted) { - if (!ttistable(t)) - luaG_runerror(L, "'vararg' parameter is not a table"); - else { - int i; - Table *h = hvalue(t); - if (wanted < 0) { /* get all? */ - const TValue *ns = luaH_getstr(h, G(L)->nfield); - int n = (ttisinteger(ns)) ? cast_int(ivalue(ns)) : 0; - wanted = n; - checkstackp(L, n, where); - L->top = where + n; - } - for (i = 0; i < wanted; i++) /* get what is available */ - setobj2s(L, where + i, luaH_getint(h, i + 1)); - return; + ci->u.l.nextraargs = nextra; + checkstackGC(L, nfixparams + 1); + /* copy function and fixed parameters to the top of the stack */ + for (i = 0; i <= nfixparams; i++) { + setobjs2s(L, L->top++, ci->func + i); + setnilvalue(s2v(ci->func + i)); /* erase original copy (for GC) */ } + ci->func += actual + 1; + ci->top += actual + 1; +} + + +void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { + int i; + int nextra = ci->u.l.nextraargs; + if (wanted < 0) { + wanted = nextra; /* get all extra arguments available */ + checkstackp(L, nextra, where); /* ensure stack space */ + L->top = where + nextra; /* next instruction will need top */ + } + for (i = 0; i < wanted && i < nextra; i++) + setobjs2s(L, where + i, ci->func - nextra + i); + for (; i < wanted; i++) /* complete required results with nil */ + setnilvalue(s2v(where + i)); } diff --git a/ltm.h b/ltm.h index a0f4f92e..54cece9e 100644 --- a/ltm.h +++ b/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.29 2018/01/28 13:39:52 roberto Exp roberto $ +** $Id: ltm.h,v 2.30 2018/02/07 15:18:04 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -9,6 +9,7 @@ #include "lobject.h" +#include "lstate.h" /* @@ -77,9 +78,10 @@ LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, int inv, TMS event); -LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base); -LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, - int wanted); +LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, + struct CallInfo *ci); +LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, + StkId where, int wanted); #endif diff --git a/lvm.c b/lvm.c index 7f2e2492..2d01e4c1 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.337 2018/02/06 19:16:56 roberto Exp roberto $ +** $Id: lvm.c,v 2.338 2018/02/07 15:18:04 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1506,14 +1506,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { luaF_close(L, base); /* close upvalues from current call */ if (!ttisLclosure(vra)) { /* C function? */ ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ - if (trap) { - updatebase(ci); - ra = RA(i); - } - luaD_poscall(L, ci, ra, cast_int(L->top - ra)); - return; } else { /* Lua tail call */ + if (cl->p->is_vararg) + ci->func -= cl->p->numparams + ci->u.l.nextraargs + 1; luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ goto tailcall; } @@ -1521,11 +1517,30 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_RETURN) { int b = GETARG_B(i); + int n = (b != 0 ? b - 1 : cast_int(L->top - ra)); if (TESTARG_k(i)) luaF_close(L, base); - halfProtect( - luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) - ); + halfProtect(luaD_poscall(L, ci, ra, n)); + return; + } + vmcase(OP_RETVARARG) { + int b = GETARG_B(i); + int nparams = GETARG_C(i); + int nres = (b != 0 ? b - 1 : cast_int(L->top - ra)); + int delta = ci->u.l.nextraargs + nparams + 2; + if (TESTARG_k(i)) + luaF_close(L, base); + savepc(L); + /* code similar to 'luaD_poscall', but with a delta */ + if (L->hookmask) { + luaD_rethook(L, ci); + if (ci->u.l.trap) { + updatebase(ci); + ra = RA(i); + } + } + L->ci = ci->previous; /* back to caller */ + luaD_moveresults(L, ra, base - delta, nres, ci->nresults); return; } vmcase(OP_RETURN0) { @@ -1702,12 +1717,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_VARARG) { int n = GETARG_C(i) - 1; /* required results */ - TValue *vtab = vRB(i); /* vararg table */ - Protect(luaT_getvarargs(L, vtab, ra, n)); + ProtectNT(luaT_getvarargs(L, ci, ra, n)); vmbreak; } vmcase(OP_PREPVARARG) { - luaT_adjustvarargs(L, GETARG_A(i), base); + luaT_adjustvarargs(L, GETARG_A(i), ci); updatetrap(ci); if (trap) { luaD_hookcall(L, ci);