new opcode 'PREPVARARG'
(avoids test for vararg function in all function calls)
This commit is contained in:
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
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** 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
|
** Executes a call hook for Lua functions. This function is called
|
||||||
** whenever 'hookmask' is not zero, so it checks whether call hooks are
|
** whenever 'hookmask' is not zero, so it checks whether call hooks are
|
||||||
** active. Also, this function can be called when resuming a function,
|
** active.
|
||||||
** so it checks whether the function is in its first instruction.
|
|
||||||
*/
|
*/
|
||||||
void luaD_hookcall (lua_State *L, CallInfo *ci) {
|
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;
|
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? */
|
||||||
if (!(L->hookmask & LUA_MASKCALL) || /* some other hook? */
|
|
||||||
ci->u.l.savedpc != p->code) /* not 1st instruction? */
|
|
||||||
return; /* don't call hook */
|
return; /* don't call hook */
|
||||||
L->top = ci->top; /* prepare top */
|
L->top = ci->top; /* prepare top */
|
||||||
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
|
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;
|
int i;
|
||||||
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
setobjs2s(L, ci->func + i, func + i);
|
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 */
|
func = ci->func; /* moved-down function */
|
||||||
for (; narg1 <= nfixparams; narg1++)
|
for (; narg1 <= nfixparams; narg1++)
|
||||||
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
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);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->callstatus |= CIST_TAIL;
|
ci->callstatus |= CIST_TAIL;
|
||||||
if (p->is_vararg) {
|
L->top = func + narg1; /* set top */
|
||||||
L->top = func + narg1; /* set top */
|
|
||||||
luaT_adjustvarargs(L, nfixparams, narg1 - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -481,8 +474,6 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
|
|||||||
lua_assert(ci->top <= L->stack_last);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->callstatus = 0;
|
ci->callstatus = 0;
|
||||||
if (p->is_vararg)
|
|
||||||
luaT_adjustvarargs(L, nfixparams, narg); /* may invoke GC */
|
|
||||||
luaV_execute(L, ci); /* run the function */
|
luaV_execute(L, ci); /* run the function */
|
||||||
break;
|
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
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -91,6 +91,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
|
|||||||
"SETLIST",
|
"SETLIST",
|
||||||
"CLOSURE",
|
"CLOSURE",
|
||||||
"VARARG",
|
"VARARG",
|
||||||
|
"PREPVARARG",
|
||||||
"EXTRAARG",
|
"EXTRAARG",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@@ -171,6 +172,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
|||||||
,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */
|
,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */
|
||||||
,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */
|
,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */
|
||||||
,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */
|
,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */
|
||||||
|
,opmode(0, 0, 0, 1, iABC) /* OP_PREPVARARG */
|
||||||
,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
,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_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 */
|
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||||
} 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
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** 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) {
|
static void parlist (LexState *ls) {
|
||||||
/* parlist -> [ param { ',' param } ] */
|
/* parlist -> [ param { ',' param } ] */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Proto *f = fs->f;
|
Proto *f = fs->f;
|
||||||
int nparams = 0;
|
int nparams = 0;
|
||||||
|
int isvararg = 0;
|
||||||
if (ls->t.token != ')') { /* is 'parlist' not empty? */
|
if (ls->t.token != ')') { /* is 'parlist' not empty? */
|
||||||
do {
|
do {
|
||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
@@ -779,17 +785,21 @@ static void parlist (LexState *ls) {
|
|||||||
new_localvar(ls, str_checkname(ls));
|
new_localvar(ls, str_checkname(ls));
|
||||||
else
|
else
|
||||||
new_localvarliteral(ls, "_ARG");
|
new_localvarliteral(ls, "_ARG");
|
||||||
f->is_vararg = 1; /* declared vararg */
|
|
||||||
nparams++;
|
nparams++;
|
||||||
|
isvararg = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: luaX_syntaxerror(ls, "<name> or '...' expected");
|
default: luaX_syntaxerror(ls, "<name> or '...' expected");
|
||||||
}
|
}
|
||||||
} while (!f->is_vararg && testnext(ls, ','));
|
} while (!isvararg && testnext(ls, ','));
|
||||||
}
|
}
|
||||||
adjustlocalvars(ls, nparams);
|
adjustlocalvars(ls, nparams);
|
||||||
f->numparams = cast_byte(fs->nactvar) - f->is_vararg;
|
f->numparams = cast_byte(fs->nactvar);
|
||||||
luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
|
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;
|
BlockCnt bl;
|
||||||
expdesc v;
|
expdesc v;
|
||||||
open_func(ls, fs, &bl);
|
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;
|
fs->f->numparams = 0;
|
||||||
new_localvarliteral(ls, "_ARG");
|
new_localvarliteral(ls, "_ARG");
|
||||||
adjustlocalvars(ls, 1);
|
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
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** 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;
|
int i;
|
||||||
Table *vtab;
|
Table *vtab;
|
||||||
TValue nname;
|
TValue nname;
|
||||||
|
int actual = cast_int(L->top - base); /* number of arguments */
|
||||||
int nextra = actual - nfixparams; /* number of extra arguments */
|
int nextra = actual - nfixparams; /* number of extra arguments */
|
||||||
vtab = luaH_new(L); /* create vararg table */
|
vtab = luaH_new(L); /* create vararg table */
|
||||||
sethvalue2s(L, L->top, vtab); /* anchor it for resizing */
|
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
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** 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,
|
LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
|
||||||
int inv, TMS event);
|
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,
|
LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where,
|
||||||
int wanted);
|
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
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -835,12 +835,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
int trap;
|
int trap;
|
||||||
tailcall:
|
tailcall:
|
||||||
trap = L->hookmask;
|
trap = L->hookmask;
|
||||||
if (trap)
|
|
||||||
luaD_hookcall(L, ci);
|
|
||||||
cl = clLvalue(s2v(ci->func));
|
cl = clLvalue(s2v(ci->func));
|
||||||
k = cl->p->k;
|
k = cl->p->k;
|
||||||
base = ci->func + 1;
|
|
||||||
pc = ci->u.l.savedpc;
|
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 */
|
/* main loop of interpreter */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int cond; /* flag for conditional jumps */
|
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));
|
Protect(luaT_getvarargs(L, vtab, ra, n));
|
||||||
vmbreak;
|
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) {
|
vmcase(OP_EXTRAARG) {
|
||||||
lua_assert(0);
|
lua_assert(0);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
|
|||||||
Reference in New Issue
Block a user