new opcodes OP_RETURN0/OP_RETURN1

This commit is contained in:
Roberto Ierusalimschy 2017-11-29 14:57:36 -02:00
parent c766e4103d
commit 745eb41993
4 changed files with 77 additions and 17 deletions

14
lcode.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 2.137 2017/11/28 12:58:18 roberto Exp roberto $
** $Id: lcode.c,v 2.138 2017/11/28 15:26:15 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@ -152,7 +152,17 @@ int luaK_jump (FuncState *fs) {
** Code a 'return' instruction
*/
void luaK_ret (FuncState *fs, int first, int nret) {
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
switch (nret) {
case 0:
luaK_codeABC(fs, OP_RETURN0, 0, 0, 0);
break;
case 1:
luaK_codeABC(fs, OP_RETURN1, first, 0, 0);
break;
default:
luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0);
break;
}
}

View File

@ -1,5 +1,5 @@
/*
** $Id: lopcodes.c,v 1.69 2017/11/22 18:41:20 roberto Exp roberto $
** $Id: lopcodes.c,v 1.70 2017/11/27 17:44:31 roberto Exp roberto $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -75,6 +75,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"CALL",
"TAILCALL",
"RETURN",
"RETURN0",
"RETURN1",
"FORLOOP",
"FORPREP",
"TFORCALL",
@ -146,6 +148,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, iABC) /* OP_CALL */
,opmode(0, 1, iABC) /* OP_TAILCALL */
,opmode(0, 0, iABC) /* OP_RETURN */
,opmode(0, 0, iABC) /* OP_RETURN0 */
,opmode(0, 0, iABC) /* OP_RETURN1 */
,opmode(0, 1, iABx) /* OP_FORLOOP */
,opmode(0, 1, iABx) /* OP_FORPREP */
,opmode(0, 0, iABC) /* OP_TFORCALL */

View File

@ -1,5 +1,5 @@
/*
** $Id: lopcodes.h,v 1.171 2017/11/27 17:44:31 roberto Exp roberto $
** $Id: lopcodes.h,v 1.172 2017/11/28 12:58:18 roberto Exp roberto $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -252,7 +252,10 @@ 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_RETURN0,/* return */
OP_RETURN1,/* A return R(A) */
OP_FORLOOP,/* A Bx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }*/

69
lvm.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.320 2017/11/28 14:51:00 roberto Exp roberto $
** $Id: lvm.c,v 2.321 2017/11/29 13:02:17 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -798,6 +798,11 @@ void luaV_finishOp (lua_State *L) {
*/
#define Protect(exp) (savepc(L), (exp), updatetrap(ci))
/*
** Protect code that will return.
*/
#define halfProtect(exp) (savepc(L), (exp))
#define checkGC(L,c) \
{ luaC_condGC(L, L->top = (c), /* limit of live values */ \
@ -824,11 +829,16 @@ void luaV_finishOp (lua_State *L) {
void luaV_execute (lua_State *L, CallInfo *ci) {
LClosure *cl = clLvalue(s2v(ci->func));
TValue *k = cl->p->k;
StkId base = ci->func + 1;
LClosure *cl;
TValue *k;
StkId base;
const Instruction *pc;
int trap = ci->u.l.trap;
const Instruction *pc = ci->u.l.savedpc;
tailcall:
cl = clLvalue(s2v(ci->func));
k = cl->p->k;
base = ci->func + 1;
pc = ci->u.l.savedpc;
/* main loop of interpreter */
for (;;) {
int cond; /* flag for conditional jumps */
@ -1438,16 +1448,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vra = s2v(ra);
b++; /* there is now one extra argument */
}
if (!ttisLclosure(vra)) /* C function? */
if (!ttisLclosure(vra)) { /* C function? */
Protect(luaD_call(L, ra, LUA_MULTRET)); /* call it */
/* next instruction will do the return */
}
else { /* tail call */
if (cl->p->sizep > 0) /* close upvalues from previous call */
luaF_close(L, ci->func + 1);
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
cl = clLvalue(s2v(ci->func));
k = cl->p->k;
updatebase(ci);
pc = ci->u.l.savedpc;
goto tailcall;
}
vmbreak;
}
@ -1455,9 +1464,43 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
int b = GETARG_B(i);
if (cl->p->sizep > 0)
luaF_close(L, base);
savepc(L);
luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
return; /* external invocation: return */
halfProtect(
luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)))
);
return;
}
vmcase(OP_RETURN0) {
if (cl->p->sizep > 0)
luaF_close(L, base);
if (L->hookmask)
halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */
else {
int nres = ci->nresults;
L->ci = ci->previous; /* back to caller */
L->top = base - 1;
while (nres-- > 0)
setnilvalue(s2v(L->top++)); /* all results are nil */
}
return;
}
vmcase(OP_RETURN1) {
if (cl->p->sizep > 0)
luaF_close(L, base);
if (L->hookmask)
halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */
else {
int nres = ci->nresults;
L->ci = ci->previous; /* back to caller */
if (nres == 0)
L->top = base - 1; /* asked for no results */
else {
setobjs2s(L, base - 1, ra); /* at least this result */
L->top = base;
while (--nres > 0) /* complete missing results */
setnilvalue(s2v(L->top++));
}
}
return;
}
vmcase(OP_FORLOOP) {
if (ttisinteger(vra)) { /* integer loop? */