Browse Source

better way to cope with opcode variants

Roberto Ierusalimschy 28 years ago
parent
commit
d6c867ea50
3 changed files with 160 additions and 177 deletions
  1. 27 4
      lopcodes.h
  2. 60 120
      lua.stx
  3. 73 53
      lvm.c

+ 27 - 4
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.2 1997/09/19 18:40:32 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.3 1997/09/19 21:17:52 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -8,6 +8,13 @@
 #define lopcodes_h
 
 
+/*
+** NOTICE: variants of the same opcode (like PUSH0, PUSHBYTE, PUSHWORD) must
+** be consecutive: First, those with built-in parameters, then with byte
+** parameter and last with word parameter.
+*/
+
+
 typedef enum {
 /* name          parm    before          after           side effect
 -----------------------------------------------------------------------------*/
@@ -15,15 +22,19 @@ ENDCODE,
 
 PUSHNIL,/*		-		nil  */
 PUSHNILS,/*	b	-		nil_1...nil_b  */
+
 PUSH0,/*		-		0.0  */
 PUSH1,/*		-		1.0  */
 PUSH2,/*		-		2.0  */
 PUSHBYTE,/*	b	-		(float)b  */
 PUSHWORD,/*	w	-		(float)w  */
+
 PUSHCONSTANTB,/*b	-		CNST[b] */
 PUSHCONSTANT,/* w	-		CNST[w] */
+
 PUSHUPVALUE0,
 PUSHUPVALUE,/*	b	-		Closure[b] */
+
 PUSHLOCAL0,/*		-		LOC[0]  */
 PUSHLOCAL1,/*		-		LOC[1]  */
 PUSHLOCAL2,/*		-		LOC[2]  */
@@ -35,10 +46,15 @@ PUSHLOCAL7,/*		-		LOC[7]  */
 PUSHLOCAL8,/*		-		LOC[8]  */
 PUSHLOCAL9,/*		-		LOC[9]  */
 PUSHLOCAL,/*	b	-		LOC[b]  */
-PUSHGLOBALB,/*	b 	-		VAR[CNST[b]]  */
-PUSHGLOBAL,/*	w	-		VAR[CNST[w]]  */
+
+GETGLOBALB,/*	b 	-		VAR[CNST[b]]  */
+GETGLOBAL,/*	w	-		VAR[CNST[w]]  */
+
 GETTABLE,/*		i t		t[i]  */
+
+PUSHSELFB,/*	b	t		t t[CNST[b]]  */
 PUSHSELF,/*	w	t		t t[CNST[w]]  */
+
 CREATEARRAY,/*	w	-		newarray(size = w)  */
 
 SETLOCAL0,/*		x		-		LOC[0]=x  */
@@ -52,10 +68,13 @@ SETLOCAL7,/*		x		-		LOC[7]=x  */
 SETLOCAL8,/*		x		-		LOC[8]=x  */
 SETLOCAL9,/*		x		-		LOC[9]=x  */
 SETLOCAL,/*	b	x		-		LOC[b]=x  */
+
 SETGLOBALB,/*	b	x		-		VAR[CNST[b]]=x  */
 SETGLOBAL,/*	w	x		-		VAR[CNST[w]]=x  */
+
 SETTABLE0,/*		v i t		-		t[i]=v  */
 SETTABLE,/*	b	v a_b...a_1 i t	a_b...a_1 i t	t[i]=v  */
+
 SETLIST0,/*	b	v_b...v_1 t	-		t[i]=v_i  */
 SETLIST,/*	b c	v_b...v_1 t	-		t[i+c*FPF]=v_i  */
 SETMAP,/*	b	v_b k_b ...v_1 k_1 t	t	t[k_i]=v_i  */
@@ -82,10 +101,14 @@ UPJMP,/*	w	-		-		PC-=w  */
 IFFJMP,/*	w	x		-		(x==nil)? PC+=w  */
 IFFUPJMP,/*	w	x		-		(x==nil)? PC-=w  */
 
-CLOSURE,/*		f v_1...v_n	c(f) */
+CLOSUREB,/*	b	v_1...v_n	c(CNST[b]) */
+CLOSURE,/*	w	v_1...v_n	c(CNST[w]) */
+
 CALLFUNC,/*	b c	v_b...v_1 f	r_c...r_1	f(v1,...,v_b)  */
 RETCODE,/*	b	-		-  */
 SETLINE,/*	w	-		-		LINE=w  */
+POP1,/*			-		-		TOP-=1  */
+POP2,/*			-		-		TOP-=2  */
 POPS,/*		b	-		-		TOP-=b  */
 ARGS,/*		b	-		-		TOP=BASE+b  */
 VARARGS/*	b	v_x...v_1	{v_1...v_x;n=x}	TOP=BASE+b+1  */

+ 60 - 120
lua.stx

@@ -1,6 +1,6 @@
 %{
 /*
-** $Id: lua.stx,v 1.2 1997/09/19 18:40:32 roberto Exp roberto $
+** $Id: lua.stx,v 1.3 1997/09/19 21:17:52 roberto Exp roberto $
 ** Syntax analizer and code generator
 ** See Copyright Notice in lua.h
 */
@@ -94,6 +94,22 @@ static void code_byte (Byte c)
 }
 
 
+static void code_word_at (int pc, int n)
+{
+  Word w = n;
+  if (w != n)
+    luaY_error("block too big");
+  currState->f->code[pc] = n&0xFF;
+  currState->f->code[pc+1] = n>>8;
+}
+
+static void code_word (int n)
+{
+  code_byte(n&0xFF);
+  code_byte(n>>8);
+}
+
+
 static void deltastack (int delta)
 {
   currState->stacksize += delta;
@@ -112,9 +128,25 @@ static void code_opcode (OpCode op, int delta)
 }
 
 
-static void code_push (OpCode op)
+static void code_opborw(OpCode opbyte, int arg, int delta)
 {
-  code_opcode(op, 1);
+  if (arg <= 255) {
+    code_opcode(opbyte, delta);
+    code_byte(arg);
+  }
+  else {
+    code_opcode(opbyte+1, delta);
+    code_word(arg);
+  }
+}
+
+
+static void code_oparg (OpCode firstop, OpCode opbyte, int arg, int delta)
+{
+  if (firstop+arg < opbyte)
+     code_opcode(firstop+arg, delta);
+  else
+    code_opborw(opbyte, arg, delta);
 }
 
 
@@ -133,31 +165,9 @@ static void code_pop (OpCode op)
 #define code_unop(op)	code_neutralop(op)
 
 
-static void code_word_at (int pc, int n)
-{
-  Word w = n;
-  if (w != n)
-    luaY_error("block too big");
-  currState->f->code[pc] = n&0xFF;
-  currState->f->code[pc+1] = n>>8;
-}
-
-static void code_word (int n)
-{
-  code_byte(n&0xFF);
-  code_byte(n>>8);
-}
-
 static void code_constant (int c)
 {
-  if (c <= 255) {
-    code_push(PUSHCONSTANTB);
-    code_byte(c);
-  }
-  else {
-    code_push(PUSHCONSTANT);
-    code_word(c);
-  }
+  code_opborw(PUSHCONSTANTB, c, 1);
 }
 
 
@@ -216,18 +226,8 @@ static int real_constant (real r)
 static void code_number (real f)
 {
   Word i;
-  if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(Word)f) == f) {
-    /* f has an (short) integer value */
-    if (i <= 2) code_push(PUSH0 + i);
-    else if (i <= 255) {
-      code_push(PUSHBYTE);
-      code_byte(i);
-    }
-    else {
-      code_push(PUSHWORD);
-      code_word(i);
-    }
-  }
+  if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(Word)f) == f)
+    code_oparg(PUSH0, PUSHBYTE, i, 1);  /* f has an (short) integer value */
   else
     code_constant(real_constant(f));
 }
@@ -344,12 +344,7 @@ static void pushupvalue (TaggedString *n)
   if (aux_localname(n, currState) >= 0)
     luaY_syntaxerror("cannot access an upvalue in current scope", n->str);
   i = indexupvalue(n);
-  if (i == 0)
-    code_push(PUSHUPVALUE0);
-  else {
-    code_push(PUSHUPVALUE);
-    code_byte(i);
-  }
+  code_oparg(PUSHUPVALUE0, PUSHUPVALUE, i, 1);
 }
 
 
@@ -366,18 +361,10 @@ void luaY_codedebugline (int line)
 
 static void adjuststack (int n)
 {
-  if (n > 0) {
-    code_opcode(POPS, -n);
-    code_byte(n);
-  }
-  else if (n < 0) {
-    if (n == -1)
-      code_push(PUSHNIL);
-    else {
-      code_opcode(PUSHNILS, -n);
-      code_byte(-n);
-    }
-  }
+  if (n > 0)
+    code_oparg(POP1-1, POPS, n, -n);  /* POP1-1 = POP0 */
+  else if (n < 0)
+    code_oparg(PUSHNIL-1, PUSHNILS, -n, -n);  /* PUSHNIL1-1 = PUSHNIL0 */
 }
 
 
@@ -426,29 +413,12 @@ static void code_args (int dots)
 
 static void lua_pushvar (vardesc number)
 {
-  if (number > 0) {  /* global var */
-    number--;
-    if (number <= 255) {
-      code_push(PUSHGLOBALB);
-      code_byte(number);
-    }
-    else {
-      code_push(PUSHGLOBAL);
-      code_word(number);
-    }
-  }
-  else if (number < 0) {  /* local var */
-    number = (-number) - 1;
-    if (number < 10)
-      code_push(PUSHLOCAL0 + number);
-    else {
-      code_push(PUSHLOCAL);
-      code_byte(number);
-    }
-  }
-  else {
+  if (number > 0)  /* global var */
+    code_opborw(GETGLOBALB, number-1, 1);
+  else if (number < 0)  /* local var */
+    code_oparg(PUSHLOCAL0, PUSHLOCAL, (-number)-1, 1);
+  else
     code_pop(GETTABLE);
-  }
 }
 
 
@@ -456,26 +426,10 @@ static void storevar (vardesc number)
 {
   if (number == 0)  /* indexed var */
     code_opcode(SETTABLE0, -3);
-  else if (number > 0) {  /* global var */
-    number--;
-    if (number <= 255) {
-      code_pop(SETGLOBALB);
-      code_byte(number);
-    }
-    else {
-      code_pop(SETGLOBAL);
-      code_word(number);
-    }
-  }
-  else {  /* number < 0 - local var */
-    number = (-number) - 1;
-    if (number < 10)
-      code_pop(SETLOCAL0 + number);
-    else {
-      code_pop(SETLOCAL);
-      code_byte(number);
-    }
-  }
+  else if (number > 0)  /* global var */
+    code_opborw(SETGLOBALB, number-1, -1);
+  else  /* number < 0 - local var */
+    code_oparg(SETLOCAL0, SETLOCAL, (-number)-1, -1);
 }
 
 
@@ -535,8 +489,7 @@ static void func_onstack (TProtoFunc *f)
   currState->f->consts[c].value.tf = (currState+1)->f;
   for (i=0; i<nupvalues; i++)
     lua_pushvar((currState+1)->upvalues[i]);
-  code_constant(c);
-  code_opcode(CLOSURE, -nupvalues);
+  code_opborw(CLOSUREB, c, 1-nupvalues);
 }
 
 
@@ -771,7 +724,7 @@ expr :  '(' expr ')'     { $$ = $2; }
      |  varexp           { $$ = 0;}
      |  NUMBER           { code_number($1); $$ = 0; }
      |  STRING           { code_string($1); $$ = 0; }
-     |	NIL		 {code_push(PUSHNIL); $$ = 0; }
+     |	NIL		 {code_opcode(PUSHNIL, 1); $$ = 0; }
      |  functioncall     { $$ = $1; }
      |	expr1 AND PrepJumpPop expr1 { code_shortcircuit($3, ONFJMP); $$ = 0; }
      |	expr1 OR PrepJumpPop expr1  { code_shortcircuit($3, ONTJMP); $$ = 0; }
@@ -779,14 +732,9 @@ expr :  '(' expr ')'     { $$ = $2; }
      ;
 
 table :
-     {
-      code_push(CREATEARRAY);
-      $<vInt>$ = currState->pc; code_word(0);
-     }
-      '{' fieldlist '}'
-     {
-      code_word_at($<vInt>1, $3);
-     }
+     { code_opcode(CREATEARRAY, 1); $<vInt>$ = currState->pc; code_word(0); }
+       '{' fieldlist '}'
+     { code_word_at($<vInt>1, $3); }
          ;
 
 functioncall : funcvalue funcParams
@@ -801,8 +749,7 @@ functioncall : funcvalue funcParams
 funcvalue    : varexp { $$ = 0; }
 	     | varexp ':' NAME
 	     {
-               code_push(PUSHSELF);
-	       code_word(string_constant($3, currState));
+               code_opborw(PUSHSELFB, string_constant($3, currState), 1);
                $$ = 1;
 	     }
 	     ;
@@ -909,15 +856,8 @@ varlist1  :	var
 	  ;
 		
 var	  :	singlevar { $$ = $1; }
-	  |	varexp '[' expr1 ']'
-	  {
-	   $$ = 0;		/* indexed variable */
-	  }
-	  |	varexp '.' NAME
-	  {
-	    code_string($3);
-	    $$ = 0;		/* indexed variable */
-	  }
+	  |	varexp '[' expr1 ']' { $$ = 0; }  /* indexed variable */
+	  |	varexp '.' NAME { code_string($3); $$ = 0; }/* ind. var. */
 	  ;
 		
 singlevar :	NAME { $$ = singlevar($1, currState); }

+ 73 - 53
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.2 1997/09/19 18:40:32 roberto Exp roberto $
+** $Id: lvm.c,v 1.3 1997/09/19 21:17:52 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -28,7 +28,7 @@
 
 
 /* Extra stack to run a function: LUA_T_LINE(1), TM calls(2), ... */
-#define	EXTRA_STACK	4
+#define	EXTRA_STACK	5
 
 
 
@@ -276,14 +276,14 @@ static void adjust_varargs (StkId first_extra_arg)
 */
 StkId luaV_execute (Closure *cl, StkId base)
 {
-  TProtoFunc *func = cl->consts[0].value.tf;
-  Byte *pc = func->code;
+  Byte *pc = cl->consts[0].value.tf->code;
+  TObject *consts = cl->consts[0].value.tf->consts;
   if (lua_callhook)
     luaD_callHook(base, LUA_T_MARK, 0);
   luaD_checkstack((*pc++)+EXTRA_STACK);
   while (1) {
-    OpCode opcode;
-    switch (opcode = (OpCode)*pc++) {
+    int aux;
+    switch ((OpCode)(aux = *pc++)) {
 
       case PUSHNIL:
         ttype(luaD_stack.top++) = LUA_T_NIL;
@@ -296,89 +296,95 @@ StkId luaV_execute (Closure *cl, StkId base)
         break;
       }
 
-      case PUSH0: case PUSH1: case PUSH2:
-        ttype(luaD_stack.top) = LUA_T_NUMBER;
-        nvalue(luaD_stack.top) = opcode-PUSH0;
-        luaD_stack.top++;
-        break;
-
       case PUSHBYTE:
-        ttype(luaD_stack.top) = LUA_T_NUMBER;
-        nvalue(luaD_stack.top) = *pc++;
-        luaD_stack.top++;
-        break;
+        aux = *pc++; goto pushnumber;
 
       case PUSHWORD:
+        aux = get_word(pc); goto pushnumber;
+
+      case PUSH0: case PUSH1: case PUSH2:
+        aux -= PUSH0;
+      pushnumber:
         ttype(luaD_stack.top) = LUA_T_NUMBER;
-        nvalue(luaD_stack.top) = get_word(pc);
+        nvalue(luaD_stack.top) = aux;
         luaD_stack.top++;
         break;
 
+      case PUSHLOCAL:
+        aux = *pc++; goto pushlocal;
+
       case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2:
       case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5:
       case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8:
       case PUSHLOCAL9:
-        *luaD_stack.top++ =
-                  *((luaD_stack.stack+base) + (int)(opcode-PUSHLOCAL0));
-        break;
-
-      case PUSHLOCAL:
-        *luaD_stack.top++ = *((luaD_stack.stack+base) + (*pc++));
+        aux -= PUSHLOCAL0;
+      pushlocal:
+        *luaD_stack.top++ = *((luaD_stack.stack+base) + aux);
         break;
 
-      case PUSHGLOBALB:
-        luaV_getglobal(luaG_findsymbol(tsvalue(&func->consts[*pc++])));
-        break;
+      case GETGLOBAL:
+        aux = get_word(pc); goto getglobal;
 
-      case PUSHGLOBAL:
-        luaV_getglobal(luaG_findsymbol(tsvalue(&func->consts[get_word(pc)])));
+      case GETGLOBALB:
+        aux = *pc++;
+      getglobal:
+        luaV_getglobal(luaG_findsymbol(tsvalue(&consts[aux])));
         break;
 
       case GETTABLE:
        luaV_gettable();
        break;
 
-      case PUSHSELF: {
+      case PUSHSELF:
+        aux = get_word(pc); goto pushself;
+
+      case PUSHSELFB:
+        aux = *pc++;
+      pushself: {
         TObject receiver = *(luaD_stack.top-1);
-        *luaD_stack.top++ = func->consts[get_word(pc)];
+        *luaD_stack.top++ = consts[aux];
         luaV_gettable();
         *luaD_stack.top++ = receiver;
         break;
       }
 
+      case PUSHCONSTANT:
+        aux = get_word(pc); goto pushconstant;
+
       case PUSHCONSTANTB:
-        *luaD_stack.top++ = func->consts[*pc++];
+        aux = *pc++;
+      pushconstant:
+        *luaD_stack.top++ = consts[aux];
         break;
 
-      case PUSHCONSTANT:
-        *luaD_stack.top++ = func->consts[get_word(pc)];
-        break;
+      case PUSHUPVALUE:
+        aux = *pc++; goto pushupvalue;
 
       case PUSHUPVALUE0:
-        *luaD_stack.top++ = cl->consts[1];
+        aux = 0;
+      pushupvalue:
+        *luaD_stack.top++ = cl->consts[aux+1];
         break;
 
-      case PUSHUPVALUE:
-        *luaD_stack.top++ = cl->consts[(*pc++)+1];
-        break;
+      case SETLOCAL:
+        aux = *pc++; goto setlocal;
 
       case SETLOCAL0: case SETLOCAL1: case SETLOCAL2:
       case SETLOCAL3: case SETLOCAL4: case SETLOCAL5:
       case SETLOCAL6: case SETLOCAL7: case SETLOCAL8:
       case SETLOCAL9:
-        *((luaD_stack.stack+base) + (int)(opcode-SETLOCAL0)) =
-                                                      *(--luaD_stack.top);
+        aux -= SETLOCAL0;
+      setlocal:
+        *((luaD_stack.stack+base) + aux) = *(--luaD_stack.top);
         break;
 
-      case SETLOCAL:
-        *((luaD_stack.stack+base) + (*pc++)) = *(--luaD_stack.top); break;
+      case SETGLOBAL:
+        aux = get_word(pc); goto setglobal;
 
       case SETGLOBALB:
-        luaV_setglobal(luaG_findsymbol(tsvalue(&func->consts[*pc++])));
-        break;
-
-      case SETGLOBAL:
-        luaV_setglobal(luaG_findsymbol(tsvalue(&func->consts[get_word(pc)])));
+        aux = *pc++;
+      setglobal:
+        luaV_setglobal(luaG_findsymbol(tsvalue(&consts[aux])));
         break;
 
       case SETTABLE0:
@@ -389,14 +395,17 @@ StkId luaV_execute (Closure *cl, StkId base)
         luaV_settable(luaD_stack.top-3-(*pc++), 2);
         break;
 
+      case SETLIST:
+        aux = *(pc++) * LFIELDS_PER_FLUSH; goto setlist;
+
       case SETLIST0:
-      case SETLIST: {
-        int m = (opcode == SETLIST0) ? 0 : *(pc++) * LFIELDS_PER_FLUSH;
+        aux = 0;
+      setlist: {
         int n = *(pc++);
         TObject *arr = luaD_stack.top-n-1;
         for (; n; n--) {
           ttype(luaD_stack.top) = LUA_T_NUMBER;
-          nvalue(luaD_stack.top) = n+m;
+          nvalue(luaD_stack.top) = n+aux;
           *(luaH_set (avalue(arr), luaD_stack.top)) = *(luaD_stack.top-1);
           luaD_stack.top--;
         }
@@ -414,7 +423,12 @@ StkId luaV_execute (Closure *cl, StkId base)
       }
 
       case POPS:
-        luaD_stack.top -= *(pc++);
+        aux = *pc++; goto pop;
+
+      case POP1: case POP2:
+        aux -= (POP1-1);
+      pop:
+        luaD_stack.top -= aux;
         break;
 
       case ARGS:
@@ -436,7 +450,7 @@ StkId luaV_execute (Closure *cl, StkId base)
       case EQOP: case NEQOP: {
         int res = luaO_equalObj(luaD_stack.top-2, luaD_stack.top-1);
         luaD_stack.top--;
-        if (opcode == NEQOP) res = !res;
+        if (aux == NEQOP) res = !res;
         ttype(luaD_stack.top-1) = res ? LUA_T_NUMBER : LUA_T_NIL;
         nvalue(luaD_stack.top-1) = 1;
         break;
@@ -578,6 +592,12 @@ StkId luaV_execute (Closure *cl, StkId base)
         break;
 
       case CLOSURE:
+        aux = get_word(pc); goto closure;
+
+      case CLOSUREB:
+        aux = *pc++;
+      closure:
+        *luaD_stack.top++ = consts[aux];
         luaV_closure();
         luaC_checkGC();
         break;
@@ -594,7 +614,7 @@ StkId luaV_execute (Closure *cl, StkId base)
       case RETCODE:
         if (lua_callhook)
           luaD_callHook(base, LUA_T_MARK, 1);
-        return (base + ((opcode==RETCODE) ? *pc : 0));
+        return (base + ((aux==RETCODE) ? *pc : 0));
 
       case SETLINE: {
         int line = get_word(pc);