From 318a9a5859826d7af0294664e206236fc8814319 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 7 Feb 2018 13:18:04 -0200 Subject: new opcode 'PREPVARARG' (avoids test for vararg function in all function calls) --- ldo.c | 19 +++++-------------- lopcodes.c | 4 +++- lopcodes.h | 2 ++ lparser.c | 22 ++++++++++++++++------ ltm.c | 5 +++-- ltm.h | 4 ++-- lvm.c | 23 +++++++++++++++++++---- 7 files changed, 50 insertions(+), 29 deletions(-) diff --git a/ldo.c b/ldo.c index d627941c..89c63350 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.189 2018/01/29 16:21:35 roberto Exp roberto $ +** $Id: ldo.c,v 2.190 2018/02/06 19:16:56 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -297,15 +297,11 @@ void luaD_hook (lua_State *L, int event, int line) { /* ** Executes a call hook for Lua functions. This function is called ** whenever 'hookmask' is not zero, so it checks whether call hooks are -** active. Also, this function can be called when resuming a function, -** so it checks whether the function is in its first instruction. +** active. */ void luaD_hookcall (lua_State *L, CallInfo *ci) { - Proto *p = clLvalue(s2v(ci->func))->p; int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL; - ci->u.l.trap = 1; /* there may be other hooks */ - if (!(L->hookmask & LUA_MASKCALL) || /* some other hook? */ - ci->u.l.savedpc != p->code) /* not 1st instruction? */ + if (!(L->hookmask & LUA_MASKCALL)) /* some other hook? */ return; /* don't call hook */ L->top = ci->top; /* prepare top */ ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ @@ -417,7 +413,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { int i; for (i = 0; i < narg1; i++) /* move down function and arguments */ setobjs2s(L, ci->func + i, func + i); - checkstackp(L, fsize, func); + luaD_checkstackaux(L, fsize, (void)0, luaC_checkGC(L)); func = ci->func; /* moved-down function */ for (; narg1 <= nfixparams; narg1++) setnilvalue(s2v(func + narg1)); /* complete missing arguments */ @@ -425,10 +421,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus |= CIST_TAIL; - if (p->is_vararg) { - L->top = func + narg1; /* set top */ - luaT_adjustvarargs(L, nfixparams, narg1 - 1); - } + L->top = func + narg1; /* set top */ } @@ -481,8 +474,6 @@ void luaD_call (lua_State *L, StkId func, int nresults) { lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = 0; - if (p->is_vararg) - luaT_adjustvarargs(L, nfixparams, narg); /* may invoke GC */ luaV_execute(L, ci); /* run the function */ break; } diff --git a/lopcodes.c b/lopcodes.c index a5867d23..cd85f1a9 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $ +** $Id: lopcodes.c,v 1.75 2017/12/22 14:16:46 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -91,6 +91,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "SETLIST", "CLOSURE", "VARARG", + "PREPVARARG", "EXTRAARG", NULL }; @@ -171,6 +172,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */ ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */ ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */ + ,opmode(0, 0, 0, 1, iABC) /* OP_PREPVARARG */ ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */ }; diff --git a/lopcodes.h b/lopcodes.h index 31bd12f8..47c72c69 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -288,6 +288,8 @@ 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_PREPVARARG,/*A (adjust vararg parameters) */ + OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ } OpCode; diff --git a/lparser.c b/lparser.c index e99b33ff..aab03dc8 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $ +** $Id: lparser.c,v 2.175 2017/12/22 14:16:46 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -759,12 +759,18 @@ static void constructor (LexState *ls, expdesc *t) { /* }====================================================================== */ +static void setvararg (FuncState *fs, int nparams) { + fs->f->is_vararg = 1; + luaK_codeABC(fs, OP_PREPVARARG, nparams, 0, 0); +} + static void parlist (LexState *ls) { /* parlist -> [ param { ',' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; + int isvararg = 0; if (ls->t.token != ')') { /* is 'parlist' not empty? */ do { switch (ls->t.token) { @@ -779,17 +785,21 @@ static void parlist (LexState *ls) { new_localvar(ls, str_checkname(ls)); else new_localvarliteral(ls, "_ARG"); - f->is_vararg = 1; /* declared vararg */ nparams++; + isvararg = 1; break; } default: luaX_syntaxerror(ls, " or '...' expected"); } - } while (!f->is_vararg && testnext(ls, ',')); + } while (!isvararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar) - f->is_vararg; - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ + f->numparams = cast_byte(fs->nactvar); + if (isvararg) { + f->numparams--; /* exclude vararg parameter */ + setvararg(fs, f->numparams); /* declared vararg */ + } + luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ } @@ -1692,7 +1702,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { BlockCnt bl; expdesc v; open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always declared vararg */ + setvararg(fs, 0); /* main function is always declared vararg */ fs->f->numparams = 0; new_localvarliteral(ls, "_ARG"); adjustlocalvars(ls, 1); diff --git a/ltm.c b/ltm.c index 64622f20..f36f4625 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.57 2018/01/28 12:08:04 roberto Exp roberto $ +** $Id: ltm.c,v 2.58 2018/01/28 13:39:52 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -216,10 +216,11 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, } -void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual) { +void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) { int i; Table *vtab; TValue nname; + int actual = cast_int(L->top - base); /* 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 */ diff --git a/ltm.h b/ltm.h index fbba067a..a0f4f92e 100644 --- a/ltm.h +++ b/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.28 2017/12/13 18:32:09 roberto Exp roberto $ +** $Id: ltm.h,v 2.29 2018/01/28 13:39:52 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -77,7 +77,7 @@ 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, int actual); +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); diff --git a/lvm.c b/lvm.c index d9814b62..7f2e2492 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.336 2018/01/29 16:21:35 roberto Exp roberto $ +** $Id: lvm.c,v 2.337 2018/02/06 19:16:56 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -835,12 +835,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { int trap; tailcall: trap = L->hookmask; - if (trap) - luaD_hookcall(L, ci); cl = clLvalue(s2v(ci->func)); k = cl->p->k; - base = ci->func + 1; pc = ci->u.l.savedpc; + if (trap) { + if (cl->p->is_vararg) + trap = 0; /* hooks will start with PREPVARARG instruction */ + else if (pc == cl->p->code) /* first instruction (not resuming)? */ + luaD_hookcall(L, ci); + ci->u.l.trap = 1; /* there may be other hooks */ + } + base = ci->func + 1; /* main loop of interpreter */ for (;;) { int cond; /* flag for conditional jumps */ @@ -1701,6 +1706,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) { Protect(luaT_getvarargs(L, vtab, ra, n)); vmbreak; } + vmcase(OP_PREPVARARG) { + luaT_adjustvarargs(L, GETARG_A(i), base); + updatetrap(ci); + if (trap) { + luaD_hookcall(L, ci); + L->oldpc = pc + 1; /* next opcode will be seen as a new line */ + } + updatebase(ci); + vmbreak; + } vmcase(OP_EXTRAARG) { lua_assert(0); vmbreak; -- cgit v1.2.3-55-g6feb