Răsfoiți Sursa

new instruction 'OP_EQK' (for equality with constants)

Roberto Ierusalimschy 7 ani în urmă
părinte
comite
4c0e36a46e
4 a modificat fișierele cu 61 adăugiri și 14 ștergeri
  1. 44 11
      lcode.c
  2. 3 1
      lopcodes.c
  3. 3 1
      lopcodes.h
  4. 11 1
      lvm.c

+ 44 - 11
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.131 2017/11/07 17:20:42 roberto Exp roberto $
+** $Id: lcode.c,v 2.132 2017/11/08 14:50:23 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -1251,10 +1251,10 @@ static void codecommutative (FuncState *fs, OpCode op,
 
 
 /*
-** Emit code for comparisons.
+** Emit code for order comparisons.
 ** 'e1' was already put in register by 'luaK_infix'.
 */
-static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
+static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
   int rk1 = check_exp(e1->k == VNONRELOC, e1->u.info);
   int rk2 = luaK_exp2anyreg(fs, e2);
   freeexps(fs, e1, e2);
@@ -1279,6 +1279,30 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
 }
 
 
+/*
+** Emit code for equality comparisons ('==', '~=').
+** 'e1' was already put as RK by 'luaK_infix'.
+*/
+static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
+  int r1, rk2;
+  OpCode op = OP_EQK;  /* will try first to use a constant */
+  if (e1->k == VK) {  /* 1st expression is constant? */
+    rk2 = e1->u.info;  /* constant index */
+    r1 = luaK_exp2anyreg(fs, e2);  /* 2nd expression must be in register */
+  }
+  else {
+    lua_assert(e1->k == VNONRELOC);  /* 1st expression is in a register */
+    r1 = e1->u.info;
+    if (!luaK_exp2RK(fs, e2))  /* 2nd expression is not constant? */
+      op = OP_EQ;  /* will compare two registers */
+    rk2 = e2->u.info;  /* constant/register index */
+  }
+  freeexps(fs, e1, e2);
+  e1->u.info = condjump(fs, op, (opr == OPR_EQ), r1, rk2);
+  e1->k = VJMP;
+}
+
+
 /*
 ** Aplly prefix operation 'op' to expression 'e'.
 */
@@ -1321,12 +1345,17 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
     case OPR_MOD: case OPR_POW:
     case OPR_BAND: case OPR_BOR: case OPR_BXOR:
     case OPR_SHL: case OPR_SHR: {
-      if (tonumeral(v, NULL))
-        break;  /* keep numeral, which may be folded with 2nd operand */
-      /* else *//* FALLTHROUGH */
+      if (!tonumeral(v, NULL))
+        luaK_exp2anyreg(fs, v);
+      /* else keep numeral, which may be folded with 2nd operand */
+      break;
+    }
+    case OPR_EQ: case OPR_NE: {
+      luaK_exp2RK(fs, v);
+      break;
     }
-    case OPR_EQ: case OPR_LT: case OPR_LE:
-    case OPR_NE: case OPR_GT: case OPR_GE: {
+    case OPR_LT: case OPR_LE:
+    case OPR_GT: case OPR_GE: {
       luaK_exp2anyreg(fs, v);
       break;
     }
@@ -1390,9 +1419,13 @@ void luaK_posfix (FuncState *fs, BinOpr op,
         codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line);
       break;
     }
-    case OPR_EQ: case OPR_LT: case OPR_LE:
-    case OPR_NE: case OPR_GT: case OPR_GE: {
-      codecomp(fs, op, e1, e2);
+    case OPR_EQ: case OPR_NE: {
+      codeeq(fs, op, e1, e2);
+      break;
+    }
+    case OPR_LT: case OPR_LE:
+    case OPR_GT: case OPR_GE: {
+      codeorder(fs, op, e1, e2);
       break;
     }
     default: lua_assert(0);

+ 3 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.66 2017/10/04 15:49:24 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.67 2017/11/07 17:20:42 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -66,6 +66,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "EQ",
   "LT",
   "LE",
+  "EQK",
   "TEST",
   "TESTSET",
   "CALL",
@@ -133,6 +134,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,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_TEST */
  ,opmode(1, 1, iABC)		/* OP_TESTSET */
  ,opmode(0, 1, iABC)		/* OP_CALL */

+ 3 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.166 2017/10/04 21:56:32 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.167 2017/11/07 17:20:42 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -240,6 +240,8 @@ OP_EQ,/*	A B C	if ((R(B) == R(C)) ~= A) then pc++		*/
 OP_LT,/*	A B C	if ((R(B) <  R(C)) ~= A) then pc++		*/
 OP_LE,/*	A B C	if ((R(B) <= R(C)) ~= A) then pc++		*/
 
+OP_EQK,/*	A B C	if ((R(B) == K(C)) ~= A) then pc++		*/
+
 OP_TEST,/*	A C	if not (R(A) <=> C) then pc++			*/
 OP_TESTSET,/*	A B C	if (R(B) <=> C) then R(A) := R(B) else pc++	*/
 

+ 11 - 1
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.309 2017/11/08 19:01:02 roberto Exp roberto $
+** $Id: lvm.c,v 2.310 2017/11/13 15:36:52 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -1358,6 +1358,16 @@ void luaV_execute (lua_State *L) {
           donextjump(ci);
         vmbreak;
       }
+      vmcase(OP_EQK) {
+        TValue *rb = vRB(i);
+        TValue *rc = KC(i);
+        /* basic types do not use '__eq'; we can use raw equality */
+        if (luaV_equalobj(NULL, rb, rc) != GETARG_A(i))
+          pc++;
+        else
+          donextjump(ci);
+        vmbreak;
+      }
       vmcase(OP_TEST) {
         if (GETARG_C(i) ? l_isfalse(s2v(ra)) : !l_isfalse(s2v(ra)))
             pc++;