Browse Source

new opcodes OP_RETURN0/OP_RETURN1

Roberto Ierusalimschy 7 years ago
parent
commit
745eb41993
4 changed files with 77 additions and 17 deletions
  1. 12 2
      lcode.c
  2. 5 1
      lopcodes.c
  3. 4 1
      lopcodes.h
  4. 56 13
      lvm.c

+ 12 - 2
lcode.c

@@ -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
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -152,7 +152,17 @@ int luaK_jump (FuncState *fs) {
 ** Code a 'return' instruction
 ** Code a 'return' instruction
 */
 */
 void luaK_ret (FuncState *fs, int first, int nret) {
 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;
+  }
 }
 }
 
 
 
 

+ 5 - 1
lopcodes.c

@@ -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
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -75,6 +75,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "CALL",
   "CALL",
   "TAILCALL",
   "TAILCALL",
   "RETURN",
   "RETURN",
+  "RETURN0",
+  "RETURN1",
   "FORLOOP",
   "FORLOOP",
   "FORPREP",
   "FORPREP",
   "TFORCALL",
   "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_CALL */
  ,opmode(0, 1, iABC)		/* OP_TAILCALL */
  ,opmode(0, 1, iABC)		/* OP_TAILCALL */
  ,opmode(0, 0, iABC)		/* OP_RETURN */
  ,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_FORLOOP */
  ,opmode(0, 1, iABx)		/* OP_FORPREP */
  ,opmode(0, 1, iABx)		/* OP_FORPREP */
  ,opmode(0, 0, iABC)		/* OP_TFORCALL */
  ,opmode(0, 0, iABC)		/* OP_TFORCALL */

+ 4 - 1
lopcodes.h

@@ -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
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** 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_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_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_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);
 OP_FORLOOP,/*	A Bx	R(A)+=R(A+2);
 			if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }*/
 			if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }*/

+ 56 - 13
lvm.c

@@ -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
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -798,6 +798,11 @@ void luaV_finishOp (lua_State *L) {
 */
 */
 #define Protect(exp)  (savepc(L), (exp), updatetrap(ci))
 #define Protect(exp)  (savepc(L), (exp), updatetrap(ci))
 
 
+/*
+** Protect code that will return.
+*/
+#define halfProtect(exp)  (savepc(L), (exp))
+
 
 
 #define checkGC(L,c)  \
 #define checkGC(L,c)  \
 	{ luaC_condGC(L, L->top = (c),  /* limit of live values */ \
 	{ 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) {
 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;
   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 */
   /* main loop of interpreter */
   for (;;) {
   for (;;) {
     int cond;  /* flag for conditional jumps */
     int cond;  /* flag for conditional jumps */
@@ -1438,16 +1448,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           vra = s2v(ra);
           vra = s2v(ra);
           b++;  /* there is now one extra argument */
           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 */
           Protect(luaD_call(L, ra, LUA_MULTRET));  /* call it */
+          /* next instruction will do the return */
+        }
         else {  /* tail call */
         else {  /* tail call */
           if (cl->p->sizep > 0) /* close upvalues from previous call */
           if (cl->p->sizep > 0) /* close upvalues from previous call */
             luaF_close(L, ci->func + 1);
             luaF_close(L, ci->func + 1);
           luaD_pretailcall(L, ci, ra, b);  /* prepare call frame */
           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;
         vmbreak;
       }
       }
@@ -1455,9 +1464,43 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         int b = GETARG_B(i);
         int b = GETARG_B(i);
         if (cl->p->sizep > 0)
         if (cl->p->sizep > 0)
           luaF_close(L, base);
           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) {
       vmcase(OP_FORLOOP) {
         if (ttisinteger(vra)) {  /* integer loop? */
         if (ttisinteger(vra)) {  /* integer loop? */