mirror of
https://github.com/lua/lua.git
synced 2024-11-23 10:13:50 +08:00
some simplifications/optimizations in returns from Lua functions
This commit is contained in:
parent
b1379936cf
commit
0682fe8169
32
lcode.c
32
lcode.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 2.152 2018/01/28 15:13:26 roberto Exp roberto $
|
||||
** $Id: lcode.c,v 2.153 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -158,16 +158,12 @@ int luaK_jump (FuncState *fs) {
|
||||
*/
|
||||
void luaK_ret (FuncState *fs, int first, int nret) {
|
||||
OpCode op;
|
||||
if (fs->f->is_vararg)
|
||||
op = OP_RETVARARG;
|
||||
else {
|
||||
switch (nret) {
|
||||
case 0: op = OP_RETURN0; break;
|
||||
case 1: op = OP_RETURN1; break;
|
||||
default: op = OP_RETURN; break;
|
||||
}
|
||||
switch (nret) {
|
||||
case 0: op = OP_RETURN0; break;
|
||||
case 1: op = OP_RETURN1; break;
|
||||
default: op = OP_RETURN; break;
|
||||
}
|
||||
luaK_codeABC(fs, op, first, nret + 1, fs->f->numparams);
|
||||
luaK_codeABC(fs, op, first, nret + 1, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -1646,10 +1642,18 @@ void luaK_finish (FuncState *fs) {
|
||||
Instruction *pc = &p->code[i];
|
||||
lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
|
||||
switch (GET_OPCODE(*pc)) {
|
||||
case OP_RETURN: case OP_RETURN0: case OP_RETURN1:
|
||||
case OP_RETVARARG: case OP_TAILCALL: {
|
||||
if (p->sizep > 0)
|
||||
SETARG_k(*pc, 1); /* signal that they must close upvalues */
|
||||
case OP_RETURN0: case OP_RETURN1: {
|
||||
if (p->sizep == 0 && !p->is_vararg)
|
||||
break; /* no extra work */
|
||||
/* else use OP_RETURN to do the extra work */
|
||||
SET_OPCODE(*pc, OP_RETURN);
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
case OP_RETURN: case OP_TAILCALL: {
|
||||
if (p->sizep > 0 || p->is_vararg) {
|
||||
SETARG_C(*pc, p->is_vararg ? p->numparams + 1 : 0);
|
||||
SETARG_k(*pc, 1); /* signal that there is extra work */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_JMP: {
|
||||
|
24
ldo.c
24
ldo.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.c,v 2.192 2018/02/07 15:55:18 roberto Exp roberto $
|
||||
** $Id: ldo.c,v 2.193 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -310,11 +310,19 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
|
||||
|
||||
void luaD_rethook (lua_State *L, CallInfo *ci) {
|
||||
if (isLuacode(ci))
|
||||
static void rethook (lua_State *L, CallInfo *ci) {
|
||||
int delta = 0;
|
||||
if (isLuacode(ci)) {
|
||||
Proto *p = clLvalue(s2v(ci->func))->p;
|
||||
if (p->is_vararg)
|
||||
delta = ci->u.l.nextraargs + p->numparams + 1;
|
||||
L->top = ci->top; /* prepare top */
|
||||
if (L->hookmask & LUA_MASKRET) /* is return hook on? */
|
||||
}
|
||||
if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
|
||||
ci->func += delta; /* if vararg, back to virtual 'func' */
|
||||
luaD_hook(L, LUA_HOOKRET, -1); /* call it */
|
||||
ci->func -= delta;
|
||||
}
|
||||
if (isLua(ci->previous))
|
||||
L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */
|
||||
}
|
||||
@ -343,8 +351,8 @@ void luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||
** expressions, multiple results for tail calls/single parameters)
|
||||
** separated.
|
||||
*/
|
||||
void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
|
||||
int nres, int wanted) {
|
||||
static void moveresults (lua_State *L, StkId firstResult, StkId res,
|
||||
int nres, int wanted) {
|
||||
switch (wanted) { /* handle typical cases separately */
|
||||
case 0: break; /* nothing to move */
|
||||
case 1: { /* one result needed */
|
||||
@ -387,12 +395,12 @@ void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
|
||||
void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
|
||||
if (L->hookmask) {
|
||||
ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
|
||||
luaD_rethook(L, ci);
|
||||
rethook(L, ci);
|
||||
firstResult = restorestack(L, fr);
|
||||
}
|
||||
L->ci = ci->previous; /* back to caller */
|
||||
/* move results to proper place */
|
||||
luaD_moveresults(L, firstResult, ci->func, nres, ci->nresults);
|
||||
moveresults(L, firstResult, ci->func, nres, ci->nresults);
|
||||
}
|
||||
|
||||
|
||||
|
5
ldo.h
5
ldo.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.h,v 2.40 2018/02/06 19:16:56 roberto Exp roberto $
|
||||
** $Id: ldo.h,v 2.41 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -62,10 +62,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
|
||||
int nres);
|
||||
LUAI_FUNC void luaD_rethook (lua_State *L, CallInfo *ci);
|
||||
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
|
||||
LUAI_FUNC void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
|
||||
int nres, int wanted);
|
||||
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
|
||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.c,v 1.76 2018/02/07 15:18:04 roberto Exp roberto $
|
||||
** $Id: lopcodes.c,v 1.77 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -80,7 +80,6 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
|
||||
"CALL",
|
||||
"TAILCALL",
|
||||
"RETURN",
|
||||
"RETVARARG",
|
||||
"RETURN0",
|
||||
"RETURN1",
|
||||
"FORLOOP1",
|
||||
@ -162,7 +161,6 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
,opmode(1, 1, 0, 1, iABC) /* OP_CALL */
|
||||
,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */
|
||||
,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */
|
||||
,opmode(0, 1, 0, 0, iABC) /* OP_RETVARARG */
|
||||
,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */
|
||||
,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */
|
||||
,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */
|
||||
|
22
lopcodes.h
22
lopcodes.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.h,v 1.186 2018/02/07 15:18:04 roberto Exp roberto $
|
||||
** $Id: lopcodes.h,v 1.187 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -267,8 +267,7 @@ OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */
|
||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
|
||||
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
|
||||
OP_RETVARARG,/* A B return R(A), ... ,R(A+B-2) (see note) */
|
||||
OP_RETURN,/* A B C return R(A), ... ,R(A+B-2) (see note) */
|
||||
OP_RETURN0,/* return */
|
||||
OP_RETURN1,/* A return R(A) */
|
||||
|
||||
@ -302,14 +301,13 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||
/*===========================================================================
|
||||
Notes:
|
||||
(*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
|
||||
set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
|
||||
set to last_result+1, so next open instruction (OP_CALL, OP_RETURN*,
|
||||
OP_SETLIST) may use 'top'.
|
||||
|
||||
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
|
||||
set top (like in OP_CALL with C == 0).
|
||||
|
||||
(*) In OP_RETURN/OP_RETVARARG, if (B == 0) then return up to 'top'.
|
||||
(OP_RETVARARG is the return instruction for vararg functions.)
|
||||
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
|
||||
|
||||
(*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then
|
||||
next 'instruction' is EXTRAARG(real C).
|
||||
@ -326,9 +324,11 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||
|
||||
(*) All 'skips' (pc++) assume that next instruction is a jump.
|
||||
|
||||
(*) In instructions ending a function (OP_RETURN*, OP_TAILCALL), k
|
||||
specifies that the function builds upvalues, which may need to be
|
||||
closed.
|
||||
(*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
|
||||
function either builds upvalues, which may need to be closed, or is
|
||||
vararg, which must be corrected before returning. When 'k' is true,
|
||||
C > 0 means the function is vararg and (C - 1) is its number of
|
||||
fixed parameters.
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
@ -351,7 +351,9 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
|
||||
#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
|
||||
|
||||
/* "out top" (set top for next instruction) */
|
||||
#define isOT(i) (testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0)
|
||||
#define isOT(i) \
|
||||
((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \
|
||||
GET_OPCODE(i) == OP_TAILCALL)
|
||||
|
||||
/* "in top" (uses top from previous instruction) */
|
||||
#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
|
||||
|
10
ltm.c
10
ltm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltm.c,v 2.59 2018/02/07 15:18:04 roberto Exp roberto $
|
||||
** $Id: ltm.c,v 2.60 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -222,10 +222,12 @@ void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci) {
|
||||
int nextra = actual - nfixparams; /* number of extra arguments */
|
||||
ci->u.l.nextraargs = nextra;
|
||||
checkstackGC(L, nfixparams + 1);
|
||||
/* copy function and fixed parameters to the top of the stack */
|
||||
for (i = 0; i <= nfixparams; i++) {
|
||||
/* copy function to the top of the stack */
|
||||
setobjs2s(L, L->top++, ci->func);
|
||||
/* move fixed parameters to the top of the stack */
|
||||
for (i = 1; i <= nfixparams; i++) {
|
||||
setobjs2s(L, L->top++, ci->func + i);
|
||||
setnilvalue(s2v(ci->func + i)); /* erase original copy (for GC) */
|
||||
setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */
|
||||
}
|
||||
ci->func += actual + 1;
|
||||
ci->top += actual + 1;
|
||||
|
60
lvm.c
60
lvm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 2.338 2018/02/07 15:18:04 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.339 2018/02/09 15:16:06 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -1493,23 +1493,35 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
}
|
||||
vmcase(OP_TAILCALL) {
|
||||
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
||||
int delta = 0; /* virtual 'func' - real 'func' (vararg functions) */
|
||||
if (b != 0)
|
||||
L->top = ra + b;
|
||||
else /* previous instruction set top */
|
||||
b = cast_int(L->top - ra);
|
||||
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
|
||||
savepc(ci);
|
||||
if (TESTARG_k(i)) {
|
||||
int nparams1 = GETARG_C(i);
|
||||
if (nparams1) /* vararg function? */
|
||||
delta = ci->u.l.nextraargs + nparams1;
|
||||
luaF_close(L, base); /* close upvalues from current call */
|
||||
}
|
||||
if (!ttisfunction(vra)) { /* not a function? */
|
||||
ProtectNT(luaD_tryfuncTM(L, ra)); /* try '__call' metamethod */
|
||||
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||
b++; /* there is now one extra argument */
|
||||
}
|
||||
if (TESTARG_k(i))
|
||||
luaF_close(L, base); /* close upvalues from current call */
|
||||
if (!ttisLclosure(vra)) { /* C function? */
|
||||
ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */
|
||||
luaD_call(L, ra, LUA_MULTRET); /* call it */
|
||||
updatetrap(ci);
|
||||
if (trap) { /* stack may have been relocated */
|
||||
updatebase(ci);
|
||||
ra = RA(i);
|
||||
}
|
||||
ci->func -= delta;
|
||||
luaD_poscall(L, ci, ra, cast_int(L->top - ra));
|
||||
return;
|
||||
}
|
||||
else { /* Lua tail call */
|
||||
if (cl->p->is_vararg)
|
||||
ci->func -= cl->p->numparams + ci->u.l.nextraargs + 1;
|
||||
ci->func -= delta;
|
||||
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||
goto tailcall;
|
||||
}
|
||||
@ -1518,34 +1530,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
vmcase(OP_RETURN) {
|
||||
int b = GETARG_B(i);
|
||||
int n = (b != 0 ? b - 1 : cast_int(L->top - ra));
|
||||
if (TESTARG_k(i))
|
||||
luaF_close(L, base);
|
||||
if (TESTARG_k(i)) {
|
||||
int nparams1 = GETARG_C(i);
|
||||
if (nparams1) /* vararg function? */
|
||||
ci->func -= ci->u.l.nextraargs + nparams1;
|
||||
luaF_close(L, base); /* there may be open upvalues */
|
||||
}
|
||||
halfProtect(luaD_poscall(L, ci, ra, n));
|
||||
return;
|
||||
}
|
||||
vmcase(OP_RETVARARG) {
|
||||
int b = GETARG_B(i);
|
||||
int nparams = GETARG_C(i);
|
||||
int nres = (b != 0 ? b - 1 : cast_int(L->top - ra));
|
||||
int delta = ci->u.l.nextraargs + nparams + 2;
|
||||
if (TESTARG_k(i))
|
||||
luaF_close(L, base);
|
||||
savepc(L);
|
||||
/* code similar to 'luaD_poscall', but with a delta */
|
||||
if (L->hookmask) {
|
||||
luaD_rethook(L, ci);
|
||||
if (ci->u.l.trap) {
|
||||
updatebase(ci);
|
||||
ra = RA(i);
|
||||
}
|
||||
}
|
||||
L->ci = ci->previous; /* back to caller */
|
||||
luaD_moveresults(L, ra, base - delta, nres, ci->nresults);
|
||||
return;
|
||||
}
|
||||
vmcase(OP_RETURN0) {
|
||||
if (TESTARG_k(i))
|
||||
luaF_close(L, base);
|
||||
if (L->hookmask)
|
||||
halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */
|
||||
else {
|
||||
@ -1558,8 +1552,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
return;
|
||||
}
|
||||
vmcase(OP_RETURN1) {
|
||||
if (TESTARG_k(i))
|
||||
luaF_close(L, base);
|
||||
if (L->hookmask)
|
||||
halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */
|
||||
else {
|
||||
|
Loading…
Reference in New Issue
Block a user