mirror of
https://github.com/lua/lua.git
synced 2026-10-06 08:55:29 +00:00
New conceptual model for vararg
Conceptually, all functions get their vararg arguments in a vararg table. The storing of vararg arguments in the stack is always treated as an optimization.
This commit is contained in:
66
ltm.c
66
ltm.c
@@ -242,6 +242,7 @@ static void createvarargtab (lua_State *L, StkId f, int n) {
|
||||
luaH_set(L, t, &key, &value); /* t.n = n */
|
||||
for (i = 0; i < n; i++)
|
||||
luaH_setint(L, t, i + 1, s2v(f + i));
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
|
||||
|
||||
@@ -265,11 +266,11 @@ void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
|
||||
setobjs2s(L, L->top.p++, ci->func.p + i);
|
||||
setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
|
||||
}
|
||||
if (p->flag & PF_VAVAR) { /* is there a vararg parameter? */
|
||||
if (p->flag & PF_VATAB) /* does it need a vararg table? */
|
||||
createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
|
||||
else /* no table; set parameter to nil */
|
||||
setnilvalue(s2v(L->top.p));
|
||||
if (p->flag & PF_VATAB) /* does it need a vararg table? */
|
||||
createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
|
||||
else { /* no table; set parameter to nil */
|
||||
setnilvalue(s2v(L->top.p));
|
||||
L->top.p++;
|
||||
}
|
||||
ci->func.p += totalargs + 1;
|
||||
ci->top.p += totalargs + 1;
|
||||
@@ -299,16 +300,53 @@ void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) {
|
||||
}
|
||||
|
||||
|
||||
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.p = where + nextra; /* next instruction will need top */
|
||||
/*
|
||||
** Get the number of extra arguments in a vararg function. If vararg
|
||||
** table has been optimized away, that number is in the call info.
|
||||
** Otherwise, get the field 'n' from the vararg table and check that it
|
||||
** has a proper value (non-negative integer not larger than the stack
|
||||
** limit).
|
||||
*/
|
||||
static int getnumargs (lua_State *L, CallInfo *ci, Table *h) {
|
||||
if (h == NULL) /* no vararg table? */
|
||||
return ci->u.l.nextraargs;
|
||||
else {
|
||||
TValue res;
|
||||
if (luaH_getshortstr(h, luaS_new(L, "n"), &res) != LUA_VNUMINT ||
|
||||
l_castS2U(ivalue(&res)) > cast_uint(INT_MAX/2))
|
||||
luaG_runerror(L, "vararg table has no proper 'n'");
|
||||
return cast_int(ivalue(&res));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Get 'wanted' vararg arguments and put them in 'where'. 'vatab' is
|
||||
** the register of the vararg table or -1 if there is no vararg table.
|
||||
*/
|
||||
void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted,
|
||||
int vatab) {
|
||||
Table *h = (vatab < 0) ? NULL : hvalue(s2v(ci->func.p + vatab + 1));
|
||||
int nargs = getnumargs(L, ci, h); /* number of available vararg args. */
|
||||
int i, touse; /* 'touse' is minimum between 'wanted' and 'nargs' */
|
||||
if (wanted < 0) {
|
||||
touse = wanted = nargs; /* get all extra arguments available */
|
||||
checkstackp(L, nargs, where); /* ensure stack space */
|
||||
L->top.p = where + nargs; /* next instruction will need top */
|
||||
}
|
||||
else
|
||||
touse = (nargs > wanted) ? wanted : nargs;
|
||||
if (h == NULL) { /* no vararg table? */
|
||||
for (i = 0; i < touse; i++) /* get vararg values from the stack */
|
||||
setobjs2s(L, where + i, ci->func.p - nargs + i);
|
||||
}
|
||||
else { /* get vararg values from vararg table */
|
||||
for (i = 0; i < touse; i++) {
|
||||
lu_byte tag = luaH_getint(h, i + 1, s2v(where + i));
|
||||
if (tagisempty(tag))
|
||||
setnilvalue(s2v(where + i));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < wanted && i < nextra; i++)
|
||||
setobjs2s(L, where + i, ci->func.p - nextra + i);
|
||||
for (; i < wanted; i++) /* complete required results with nil */
|
||||
setnilvalue(s2v(where + i));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user