mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
new opcode 'PREPVARARG'
(avoids test for vararg function in all function calls)
This commit is contained in:
parent
73d797ce7e
commit
318a9a5859
19
ldo.c
19
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
22
lparser.c
22
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, "<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
5
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 */
|
||||
|
4
ltm.h
4
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);
|
||||
|
||||
|
23
lvm.c
23
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;
|
||||
|
Loading…
Reference in New Issue
Block a user