Переглянути джерело

new macros 'isOT'/'isIT'
(plus exchanged parameters of OP_VARARG to make it similar to other
'isOT' instructions)

Roberto Ierusalimschy 7 роки тому
батько
коміт
4676f6599e
5 змінених файлів з 104 додано та 94 видалено
  1. 7 7
      lcode.c
  2. 76 76
      lopcodes.c
  3. 15 5
      lopcodes.h
  4. 2 2
      lparser.c
  5. 4 4
      lvm.c

+ 7 - 7
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.145 2017/12/15 18:53:48 roberto Exp roberto $
+** $Id: lcode.c,v 2.146 2017/12/18 15:44:44 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -618,12 +618,11 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) {
 ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that).
 */
 void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
-  if (e->k == VCALL) {  /* expression is an open function call? */
-    SETARG_C(getinstruction(fs, e), nresults + 1);
-  }
+  Instruction *pc = &getinstruction(fs, e);
+  if (e->k == VCALL)  /* expression is an open function call? */
+    SETARG_C(*pc, nresults + 1);
   else if (e->k == VVARARG) {
-    Instruction *pc = &getinstruction(fs, e);
-    SETARG_B(*pc, nresults + 1);
+    SETARG_C(*pc, nresults + 1);
     SETARG_A(*pc, fs->freereg);
     luaK_reserveregs(fs, 1);
   }
@@ -649,7 +648,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) {
     e->u.info = GETARG_A(getinstruction(fs, e));
   }
   else if (e->k == VVARARG) {
-    SETARG_B(getinstruction(fs, e), 2);
+    SETARG_C(getinstruction(fs, e), 2);
     e->k = VRELOC;  /* can relocate its simple result */
   }
 }
@@ -1623,6 +1622,7 @@ void luaK_finish (FuncState *fs) {
   Proto *p = fs->f;
   for (i = 0; i < fs->pc; i++) {
     Instruction *pc = &p->code[i];
+    lua_assert(isOT(*pc) == isIT(*(pc + 1)));
     switch (GET_OPCODE(*pc)) {
       case OP_RETURN: case OP_RETURN0: case OP_RETURN1:
       case OP_TAILCALL: {

+ 76 - 76
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.73 2017/12/13 18:32:09 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -97,80 +97,80 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
 
 
 LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/*       T  A    mode		   opcode	*/
-  opmode(0, 1, iABC)		/* OP_MOVE */
- ,opmode(0, 1, iAsBx)		/* OP_LOADI */
- ,opmode(0, 1, iAsBx)		/* OP_LOADF */
- ,opmode(0, 1, iABx)		/* OP_LOADK */
- ,opmode(0, 1, iABx)		/* OP_LOADKX */
- ,opmode(0, 1, iABC)		/* OP_LOADBOOL */
- ,opmode(0, 1, iABC)		/* OP_LOADNIL */
- ,opmode(0, 1, iABC)		/* OP_GETUPVAL */
- ,opmode(0, 0, iABC)		/* OP_SETUPVAL */
- ,opmode(0, 1, iABC)		/* OP_GETTABUP */
- ,opmode(0, 1, iABC)		/* OP_GETTABLE */
- ,opmode(0, 1, iABC)		/* OP_GETI */
- ,opmode(0, 1, iABC)		/* OP_GETFIELD */
- ,opmode(0, 0, iABC)		/* OP_SETTABUP */
- ,opmode(0, 0, iABC)		/* OP_SETTABLE */
- ,opmode(0, 0, iABC)		/* OP_SETI */
- ,opmode(0, 0, iABC)		/* OP_SETFIELD */
- ,opmode(0, 1, iABC)		/* OP_NEWTABLE */
- ,opmode(0, 1, iABC)		/* OP_SELF */
- ,opmode(0, 1, iABC)		/* OP_ADDI */
- ,opmode(0, 1, iABC)		/* OP_SUBI */
- ,opmode(0, 1, iABC)		/* OP_MULI */
- ,opmode(0, 1, iABC)		/* OP_MODI */
- ,opmode(0, 1, iABC)		/* OP_POWI */
- ,opmode(0, 1, iABC)		/* OP_DIVI */
- ,opmode(0, 1, iABC)		/* OP_IDIVI */
- ,opmode(0, 1, iABC)		/* OP_BANDK */
- ,opmode(0, 1, iABC)		/* OP_BORK */
- ,opmode(0, 1, iABC)		/* OP_BXORK */
- ,opmode(0, 1, iABC)		/* OP_SHRI */
- ,opmode(0, 1, iABC)		/* OP_SHLI */
- ,opmode(0, 1, iABC)		/* OP_ADD */
- ,opmode(0, 1, iABC)		/* OP_SUB */
- ,opmode(0, 1, iABC)		/* OP_MUL */
- ,opmode(0, 1, iABC)		/* OP_MOD */
- ,opmode(0, 1, iABC)		/* OP_POW */
- ,opmode(0, 1, iABC)		/* OP_DIV */
- ,opmode(0, 1, iABC)		/* OP_IDIV */
- ,opmode(0, 1, iABC)		/* OP_BAND */
- ,opmode(0, 1, iABC)		/* OP_BOR */
- ,opmode(0, 1, iABC)		/* OP_BXOR */
- ,opmode(0, 1, iABC)		/* OP_SHL */
- ,opmode(0, 1, iABC)		/* OP_SHR */
- ,opmode(0, 1, iABC)		/* OP_UNM */
- ,opmode(0, 1, iABC)		/* OP_BNOT */
- ,opmode(0, 1, iABC)		/* OP_NOT */
- ,opmode(0, 1, iABC)		/* OP_LEN */
- ,opmode(0, 1, iABC)		/* OP_CONCAT */
- ,opmode(0, 0, iABC)		/* OP_CLOSE */
- ,opmode(0, 0, isJ)		/* OP_JMP */
- ,opmode(1, 0, iABC)		/* OP_EQ */
- ,opmode(1, 0, iABC)		/* OP_LT */
- ,opmode(1, 0, iABC)		/* OP_LE */
- ,opmode(1, 0, iABC)		/* OP_EQK */
- ,opmode(1, 0, iABC)		/* OP_EQI */
- ,opmode(1, 0, iABC)		/* OP_LTI */
- ,opmode(1, 0, iABC)		/* OP_LEI */
- ,opmode(1, 0, iABC)		/* OP_TEST */
- ,opmode(1, 1, iABC)		/* OP_TESTSET */
- ,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_FORLOOP1 */
- ,opmode(0, 1, iABx)		/* OP_FORPREP1 */
- ,opmode(0, 1, iABx)		/* OP_FORLOOP */
- ,opmode(0, 1, iABx)		/* OP_FORPREP */
- ,opmode(0, 0, iABC)		/* OP_TFORCALL */
- ,opmode(0, 1, iABx)		/* OP_TFORLOOP */
- ,opmode(0, 0, iABC)		/* OP_SETLIST */
- ,opmode(0, 1, iABx)		/* OP_CLOSURE */
- ,opmode(0, 1, iABC)		/* OP_VARARG */
- ,opmode(0, 0, iAx)		/* OP_EXTRAARG */
+/*       OT IT T  A  mode		   opcode  */
+  opmode(0, 0, 0, 1, iABC)		/* OP_MOVE */
+ ,opmode(0, 0, 0, 1, iAsBx)		/* OP_LOADI */
+ ,opmode(0, 0, 0, 1, iAsBx)		/* OP_LOADF */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_LOADK */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_LOADKX */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_LOADBOOL */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_LOADNIL */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_GETUPVAL */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_SETUPVAL */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_GETTABUP */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_GETTABLE */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_GETI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_GETFIELD */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_SETTABUP */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_SETTABLE */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_SETI */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_SETFIELD */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_NEWTABLE */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SELF */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_ADDI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SUBI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MULI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MODI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_POWI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_DIVI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_IDIVI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BANDK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BORK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BXORK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SHRI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SHLI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_ADD */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SUB */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MUL */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MOD */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_POW */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_DIV */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_IDIV */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BAND */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BOR */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BXOR */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SHL */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SHR */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_UNM */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_BNOT */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_NOT */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_LEN */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_CONCAT */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_CLOSE */
+ ,opmode(0, 0, 0, 0, isJ)		/* OP_JMP */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_EQ */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_LT */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_LE */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_EQK */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_EQI */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_LTI */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_LEI */
+ ,opmode(0, 0, 1, 0, iABC)		/* OP_TEST */
+ ,opmode(0, 0, 1, 1, iABC)		/* OP_TESTSET */
+ ,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, 0, 0, 0, iABC)		/* OP_RETURN0 */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_RETURN1 */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP1 */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP1 */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_TFORCALL */
+ ,opmode(0, 0, 0, 1, iABx)		/* OP_TFORLOOP */
+ ,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, 0, iAx)		/* OP_EXTRAARG */
 };
 

+ 15 - 5
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.179 2017/12/15 18:53:48 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.180 2017/12/18 17:49:31 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -282,7 +282,7 @@ OP_SETLIST,/*	A B C	R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B	*/
 
 OP_CLOSURE,/*	A Bx	R(A) := closure(KPROTO[Bx])			*/
 
-OP_VARARG,/*	A B C	R(A), R(A+1), ..., R(A+B-2) = vararg(C)		*/
+OP_VARARG,/*	A B C	R(A), R(A+1), ..., R(A+C-2) = vararg(B)		*/
 
 OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
 } OpCode;
@@ -298,8 +298,8 @@ OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
   set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
   OP_SETLIST) may use 'top'.
 
-  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
-  set top (like in OP_CALL with C == 0). C is the vararg parameter.
+  (*) In OP_VARARG, if (C == 0) then use actual number of varargs and
+  set top (like in OP_CALL with C == 0). B is the vararg parameter.
 
   (*) In OP_RETURN, if (B == 0) then return up to 'top'.
 
@@ -330,6 +330,8 @@ OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
 ** bits 0-2: op mode
 ** bit 3: instruction set register A
 ** bit 4: operator is a test (next instruction must be a jump)
+** bit 5: instruction sets 'L->top' for next instruction (when C == 0)
+** bit 6: instruction uses 'L->top' set by previous instruction (when B == 0)
 */
 
 LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
@@ -337,8 +339,16 @@ LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
 #define getOpMode(m)	(cast(enum OpMode, luaP_opmodes[m] & 7))
 #define testAMode(m)	(luaP_opmodes[m] & (1 << 3))
 #define testTMode(m)	(luaP_opmodes[m] & (1 << 4))
+#define testOTMode(m)	(luaP_opmodes[m] & (1 << 5))
+#define testITMode(m)	(luaP_opmodes[m] & (1 << 6))
 
-#define opmode(t,a,m) (((t)<<4) | ((a)<<3) | (m))
+/* "out top" (set top for next instruction) */
+#define isOT(i)		(testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0)
+
+/* "in top" (uses top from previous instruction) */
+#define isIT(i)		(testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
+
+#define opmode(ot,it,t,a,m) (((ot)<<5) | ((it)<<6) | ((t)<<4) | ((a)<<3) | (m))
 
 
 LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */

+ 2 - 2
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.173 2017/12/18 12:33:54 roberto Exp roberto $
+** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -977,7 +977,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
       int lastparam = fs->f->numparams;
       check_condition(ls, fs->f->is_vararg,
                       "cannot use '...' outside a vararg function");
-      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, lastparam));
+      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, lastparam, 1));
       break;
     }
     case '{': {  /* constructor */

+ 4 - 4
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.327 2017/12/19 16:18:04 roberto Exp roberto $
+** $Id: lvm.c,v 2.328 2017/12/20 14:58:05 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -1688,9 +1688,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         vmbreak;
       }
       vmcase(OP_VARARG) {
-        int b = GETARG_B(i) - 1;  /* required results */
-        TValue *vtab = vRC(i);  /* vararg table */
-        Protect(luaT_getvarargs(L, vtab, ra, b));
+        int n = GETARG_C(i) - 1;  /* required results */
+        TValue *vtab = vRB(i);  /* vararg table */
+        Protect(luaT_getvarargs(L, vtab, ra, n));
         vmbreak;
       }
       vmcase(OP_EXTRAARG) {