Browse Source

SETLIST extra argument now is an "instruction" (OP_EXTRAARG)

Roberto Ierusalimschy 17 years ago
parent
commit
a4d3080fe3
6 changed files with 68 additions and 36 deletions
  1. 11 3
      lcode.c
  2. 7 11
      ldebug.c
  3. 3 1
      lopcodes.c
  4. 34 18
      lopcodes.h
  5. 4 1
      ltests.c
  6. 9 2
      lvm.c

+ 11 - 3
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.33 2007/03/27 14:11:38 roberto Exp roberto $
+** $Id: lcode.c,v 2.34 2007/05/04 18:41:49 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -824,16 +824,24 @@ int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
 }
 
 
+static int luaK_codeAx (FuncState *fs, OpCode o, int a) {
+  lua_assert(getOpMode(o) == iAx);
+  return luaK_code(fs, CREATE_Ax(o, a));
+}
+
+
 void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
   int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
   int b = (tostore == LUA_MULTRET) ? 0 : tostore;
   lua_assert(tostore != 0);
   if (c <= MAXARG_C)
     luaK_codeABC(fs, OP_SETLIST, base, b, c);
-  else {
+  else if (c <= MAXARG_Ax) {
     luaK_codeABC(fs, OP_SETLIST, base, b, 0);
-    luaK_code(fs, cast(Instruction, c));
+    luaK_codeAx(fs, OP_EXTRAARG, c);
   }
+  else
+    luaX_syntaxerror(fs->ls, "constructor too long");
   fs->freereg = base + 1;  /* free registers with list values */
 }
 

+ 7 - 11
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.36 2007/05/09 15:49:36 roberto Exp roberto $
+** $Id: ldebug.c,v 2.37 2007/05/29 18:59:59 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -331,9 +331,9 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
     int b = 0;
     int c = 0;
     check(op < NUM_OPCODES);
-    checkreg(pt, a);
     switch (getOpMode(op)) {
       case iABC: {
+        checkreg(pt, a);
         b = GETARG_B(i);
         c = GETARG_C(i);
         check(checkArgMode(pt, b, getBMode(op)));
@@ -341,31 +341,27 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
         break;
       }
       case iABx: {
+        checkreg(pt, a);
         b = GETARG_Bx(i);
         if (getBMode(op) == OpArgK) check(b < pt->sizek);
         break;
       }
       case iAsBx: {
+        checkreg(pt, a);
         b = GETARG_sBx(i);
         if (getBMode(op) == OpArgR) {
           int dest = pc+1+b;
           check(0 <= dest && dest < pt->sizecode);
-          if (dest > 0) {
-            /* cannot jump to a setlist count */
-            Instruction d = pt->code[dest-1];
-            check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
-          }
         }
         break;
       }
+      case iAx: break;
     }
     if (testAMode(op)) {
       if (a == reg) last = pc;  /* change register `a' */
     }
-    if (testTMode(op)) {
-      check(pc+2 < pt->sizecode);  /* check skip */
+    if (testTMode(op))
       check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
-    }
     switch (op) {
       case OP_LOADBOOL: {
         check(c == 0 || pc+2 < pt->sizecode);  /* check its jump */
@@ -433,7 +429,7 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
       }
       case OP_SETLIST: {
         if (b > 0) checkreg(pt, a + b);
-        if (c == 0) pc++;
+        if (c == 0) check(GET_OPCODE(pt->code[pc + 1]) == OP_EXTRAARG);
         break;
       }
       case OP_CLOSURE: {

+ 3 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.37 2005/11/08 19:45:36 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.38 2006/09/11 14:07:24 roberto Exp roberto $
 ** See Copyright Notice in lua.h
 */
 
@@ -52,6 +52,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
   "CLOSE",
   "CLOSURE",
   "VARARG",
+  "EXTRAARG",
   NULL
 };
 
@@ -98,5 +99,6 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 0, OpArgN, OpArgN, iABC)		/* OP_CLOSE */
  ,opmode(0, 1, OpArgU, OpArgN, iABx)		/* OP_CLOSURE */
  ,opmode(0, 1, OpArgU, OpArgN, iABC)		/* OP_VARARG */
+ ,opmode(0, 0, OpArgU, OpArgU, iAx)		/* OP_EXTRAARG */
 };
 

+ 34 - 18
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.125 2006/03/14 19:04:44 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.126 2006/09/11 14:07:24 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -28,7 +28,7 @@
 ===========================================================================*/
 
 
-enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
+enum OpMode {iABC, iABx, iAsBx, iAx};  /* basic instruction format */
 
 
 /*
@@ -38,6 +38,7 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 #define SIZE_B		9
 #define SIZE_Bx		(SIZE_C + SIZE_B)
 #define SIZE_A		8
+#define SIZE_Ax		(SIZE_C + SIZE_B + SIZE_A)
 
 #define SIZE_OP		6
 
@@ -46,6 +47,7 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 #define POS_C		(POS_A + SIZE_A)
 #define POS_B		(POS_C + SIZE_C)
 #define POS_Bx		POS_C
+#define POS_Ax		POS_A
 
 
 /*
@@ -61,6 +63,12 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 #define MAXARG_sBx        MAX_INT
 #endif
 
+#if SIZE_Ax < LUAI_BITSINT-1
+#define MAXARG_Ax	((1<<SIZE_Ax)-1)
+#else
+#define MAXARG_Ax	MAX_INT
+#endif
+
 
 #define MAXARG_A        ((1<<SIZE_A)-1)
 #define MAXARG_B        ((1<<SIZE_B)-1)
@@ -68,7 +76,7 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 
 
 /* creates a mask with `n' 1 bits at position `p' */
-#define MASK1(n,p)	((~((~(Instruction)0)<<n))<<p)
+#define MASK1(n,p)	((~((~(Instruction)0)<<(n)))<<(p))
 
 /* creates a mask with `n' 0 bits at position `p' */
 #define MASK0(n,p)	(~MASK1(n,p))
@@ -81,21 +89,24 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 #define SET_OPCODE(i,o)	((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
 		((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
 
-#define GETARG_A(i)	(cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
-#define SETARG_A(i,u)	((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
-		((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+#define getarg(i,pos,size)	(cast(int, ((i)>>pos) & MASK1(size,0)))
+#define setarg(i,v,pos,size)	((i) = (((i)&MASK0(size,pos)) | \
+                ((cast(Instruction, v)<<pos)&MASK1(size,pos))))
+
+#define GETARG_A(i)	getarg(i, POS_A, SIZE_A)
+#define SETARG_A(i,v)	setarg(i, v, POS_A, SIZE_A)
 
-#define GETARG_B(i)	(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
-#define SETARG_B(i,b)	((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
-		((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+#define GETARG_B(i)	getarg(i, POS_B, SIZE_B)
+#define SETARG_B(i,v)	setarg(i, v, POS_B, SIZE_B)
 
-#define GETARG_C(i)	(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
-#define SETARG_C(i,b)	((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
-		((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+#define GETARG_C(i)	getarg(i, POS_C, SIZE_C)
+#define SETARG_C(i,v)	setarg(i, v, POS_C, SIZE_C)
 
-#define GETARG_Bx(i)	(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
-#define SETARG_Bx(i,b)	((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
-		((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+#define GETARG_Bx(i)	getarg(i, POS_Bx, SIZE_Bx)
+#define SETARG_Bx(i,v)	setarg(i, v, POS_Bx, SIZE_Bx)
+
+#define GETARG_Ax(i)	getarg(i, POS_Ax, SIZE_Ax)
+#define SETARG_Ax(i,v)	setarg(i, v, POS_Ax, SIZE_Ax)
 
 #define GETARG_sBx(i)	(GETARG_Bx(i)-MAXARG_sBx)
 #define SETARG_sBx(i,b)	SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
@@ -110,6 +121,9 @@ enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
 			| (cast(Instruction, a)<<POS_A) \
 			| (cast(Instruction, bc)<<POS_Bx))
 
+#define CREATE_Ax(o,a)		((cast(Instruction, o)<<POS_OP) \
+			| (cast(Instruction, a)<<POS_A))
+
 
 /*
 ** Macros to operate RK indices
@@ -204,11 +218,13 @@ OP_SETLIST,/*	A B C	R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B	*/
 OP_CLOSE,/*	A	close all variables in the stack up to (>=) R(A)*/
 OP_CLOSURE,/*	A Bx	R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/
 
-OP_VARARG/*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/
+OP_VARARG,/*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/
+
+OP_EXTRAARG/*	Ax	extra argument for previous opcode		*/
 } OpCode;
 
 
-#define NUM_OPCODES	(cast(int, OP_VARARG) + 1)
+#define NUM_OPCODES	(cast(int, OP_EXTRAARG) + 1)
 
 
 
@@ -224,7 +240,7 @@ OP_VARARG/*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/
   (*) In OP_RETURN, if (B == 0) then return up to `top'
 
   (*) In OP_SETLIST, if (B == 0) then B = `top';
-      if (C == 0) then next `instruction' is real C
+      if (C == 0) then next `instruction' is EXTRAARG(real C)
 
   (*) For comparisons, A specifies what condition the test should accept
       (true or false).

+ 4 - 1
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.46 2008/02/11 19:04:16 roberto Exp roberto $
+** $Id: ltests.c,v 2.47 2008/02/19 18:55:09 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -410,6 +410,9 @@ static char *buildop (Proto *p, int pc, char *buff) {
     case iAsBx:
       sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
       break;
+    case iAx:
+      sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i));
+      break;
   }
   return buff;
 }

+ 9 - 2
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.72 2007/06/19 19:48:15 roberto Exp roberto $
+** $Id: lvm.c,v 2.73 2007/09/10 17:59:32 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -704,7 +704,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         int last;
         Table *h;
         if (n == 0) n = cast_int(L->top - ra) - 1;
-        if (c == 0) c = cast_int(*L->savedpc++);
+        if (c == 0) {
+          lua_assert(GET_OPCODE(*L->savedpc) == OP_EXTRAARG);
+          c = GETARG_Ax(*L->savedpc++);
+        }
         runtime_check(L, ttistable(ra));
         h = hvalue(ra);
         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
@@ -764,6 +767,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         }
         continue;
       }
+      case OP_EXTRAARG: {
+        luaG_runerror(L, "bad opcode");
+        return;
+      }
     }
   }
 }