mirror of
https://github.com/lua/lua.git
synced 2025-01-14 05:43:00 +08:00
vararg back to '...' (but with another implementation)
new implementation should have zero overhead for non-vararg functions
This commit is contained in:
parent
4e0de3a43c
commit
b1379936cf
26
lcode.c
26
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;
|
||||
|
26
ldebug.c
26
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;
|
||||
}
|
||||
|
37
ldo.c
37
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;
|
||||
|
10
ldo.h
10
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);
|
||||
|
@ -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 */
|
||||
|
10
lopcodes.h
10
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).
|
||||
|
22
lparser.c
22
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 */
|
||||
|
3
lstate.h
3
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 */
|
||||
|
61
ltm.c
61
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));
|
||||
}
|
||||
|
10
ltm.h
10
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
|
||||
|
40
lvm.c
40
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user