summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-09 13:16:06 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-09 13:16:06 -0200
commitb1379936cf35787d3ef3aab82d1607a3e1562eef (patch)
treefe47cb5c35fddab945faf731f0bc175bf5431352
parent4e0de3a43cc30a83334c272cb7575bf8412bfeae (diff)
downloadlua-github-b1379936cf35787d3ef3aab82d1607a3e1562eef.tar.gz
vararg back to '...' (but with another implementation)
new implementation should have zero overhead for non-vararg functions
-rw-r--r--lcode.c26
-rw-r--r--ldebug.c26
-rw-r--r--ldo.c37
-rw-r--r--ldo.h10
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h10
-rw-r--r--lparser.c22
-rw-r--r--lstate.h3
-rw-r--r--ltm.c55
-rw-r--r--ltm.h10
-rw-r--r--lvm.c40
11 files changed, 133 insertions, 110 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);
+ 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, 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;
+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, 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);
- halfProtect(
- luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)))
- );
+ 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);