From c5363a1b58573162ef13ba4a345bd48ad3c355d9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 2 Nov 2015 12:06:01 -0200 Subject: [PATCH] in 'luaD_precall', in vararg functions, complete missing parameters only after moving them to final place (avoids checking the stack again) --- ldo.c | 28 +++++++++++++--------------- lvm.c | 18 ++++++++---------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/ldo.c b/ldo.c index 528f19e9..524c1e57 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.144 2015/10/28 17:28:40 roberto Exp roberto $ +** $Id: ldo.c,v 2.145 2015/11/02 11:48:59 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -273,15 +273,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; StkId base, fixed; - lua_assert(actual >= nfixargs); /* move fixed parameters to final position */ - luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ fixed = L->top - actual; /* first fixed argument */ base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed + i); - setnilvalue(fixed + i); + setnilvalue(fixed + i); /* erase original copy (for GC) */ } + for (; i < nfixargs; i++) + setnilvalue(L->top++); /* complete missing arguments */ return base; } @@ -354,25 +354,23 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { StkId base; Proto *p = clLvalue(func)->p; int n = cast_int(L->top - func) - 1; /* number of real arguments */ - checkstackp(L, p->maxstacksize, func); - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - if (p->is_vararg != 1) /* do not use vararg? */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + if (p->is_vararg != 1) { /* do not use vararg? */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ base = func + 1; - else { - ptrdiff_t funcr = savestack(L, func); - base = adjust_varargs(L, p, n); - func = restorestack(L, funcr); /* previous call can change stack */ } + else + base = adjust_varargs(L, p, n); ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; ci->func = func; ci->u.l.base = base; - ci->top = base + p->maxstacksize; + L->top = ci->top = base + fsize; lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_LUA; - L->top = ci->top; if (L->hookmask & LUA_MASKCALL) callhook(L, ci); return 0; diff --git a/lvm.c b/lvm.c index 051b948c..27ade135 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.257 2015/10/28 14:50:09 roberto Exp roberto $ +** $Id: lvm.c,v 2.258 2015/11/02 11:43:17 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1274,23 +1274,21 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_VARARG) { - int b = GETARG_B(i) - 1; + int b = GETARG_B(i) - 1; /* required results */ int j; int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (n < 0) /* less arguments than parameters? */ + n = 0; /* no vararg arguments */ if (b < 0) { /* B == 0? */ b = n; /* get all var. arguments */ Protect(luaD_checkstack(L, n)); ra = RA(i); /* previous call may change the stack */ L->top = ra + n; } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, base - n + j); - } - else { - setnilvalue(ra + j); - } - } + for (j = 0; j < b && j < n; j++) + setobjs2s(L, ra + j, base - n + j); + for (; j < b; j++) /* complete required results with nil */ + setnilvalue(ra + j); vmbreak; } vmcase(OP_EXTRAARG) {