new opcode 'PREPVARARG'

(avoids test for vararg function in all function calls)
This commit is contained in:
Roberto Ierusalimschy 2018-02-07 13:18:04 -02:00
parent 73d797ce7e
commit 318a9a5859
7 changed files with 50 additions and 29 deletions

19
ldo.c
View File

@ -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;
}

View File

@ -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 */
};

View File

@ -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;

View File

@ -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, "<name> 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);

5
ltm.c
View File

@ -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 */

4
ltm.h
View File

@ -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);

23
lvm.c
View File

@ -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;