From 4c0e36a46e11be2f101203ed0db66ea750bf4333 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 16 Nov 2017 10:59:14 -0200 Subject: new instruction 'OP_EQK' (for equality with constants) --- lcode.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- lopcodes.c | 4 +++- lopcodes.h | 4 +++- lvm.c | 12 +++++++++++- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/lcode.c b/lcode.c index c36a49ad..ccd25711 100644 --- a/lcode.c +++ b/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); diff --git a/lopcodes.c b/lopcodes.c index 6ea54d09..87408752 100644 --- a/lopcodes.c +++ b/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 */ diff --git a/lopcodes.h b/lopcodes.h index bc8d722f..a805ba63 100644 --- a/lopcodes.h +++ b/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++ */ diff --git a/lvm.c b/lvm.c index a8285ac6..717335d2 100644 --- a/lvm.c +++ b/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++; -- cgit v1.2.3-55-g6feb