From 41f2936d8f2ec3894e0ef013f6b9e8f6ea17c181 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 22 Nov 2017 16:41:20 -0200 Subject: new opcode 'OP_EQI' for equality with immediate numbers --- lcode.c | 73 +++++++++++++++++++++++++++++++++++++++++++------------------- lopcodes.c | 4 +++- lopcodes.h | 3 ++- lvm.c | 13 ++++++++++- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/lcode.c b/lcode.c index ccd25711..08e92ea1 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.132 2017/11/08 14:50:23 roberto Exp roberto $ +** $Id: lcode.c,v 2.133 2017/11/16 12:59:14 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -607,12 +607,17 @@ void luaK_int (FuncState *fs, int reg, lua_Integer i) { } -static void luaK_float (FuncState *fs, int reg, lua_Number f) { +static int floatI (lua_Number f, lua_Integer *fi) { TValue v; - lua_Integer fi; setfltvalue(&v, f); - if (luaV_flttointeger(&v, &fi, 0) && - l_castS2U(fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)) + return (luaV_flttointeger(&v, fi, 0) && + l_castS2U(*fi) + MAXARG_sBx <= l_castS2U(MAXARG_Bx)); +} + + +static void luaK_float (FuncState *fs, int reg, lua_Number f) { + lua_Integer fi; + if (floatI(f, &fi)) luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi)); else luaK_codek(fs, reg, luaK_numberK(fs, f)); @@ -1106,6 +1111,20 @@ static int isSCint (expdesc *e) { } +/* +** Check whether expression 'e' is a literal integer or float in +** proper range to fit in register sC +*/ +static int isSCnumber (expdesc *e, lua_Integer *i) { + if (e->k == VKINT) + *i = e->u.ival; + else if (!(e->k == VKFLT && floatI(e->u.nval, i))) + return 0; /* not a number */ + *i += MAXARG_sC; + return (!hasjumps(e) && l_castS2U(*i) <= l_castS2U(MAXARG_C)); +} + + /* ** Create expression 't[k]'. 't' must have its final result already in a ** register or upvalue. Upvalues can only be indexed by literal strings. @@ -1235,6 +1254,11 @@ static void codearith (FuncState *fs, OpCode op, } +static void swapexps (expdesc *e1, expdesc *e2) { + expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ +} + + /* ** Code commutative operators ('+', '*'). If first operand is a ** constant, change order of operands to use immediate operator. @@ -1243,7 +1267,7 @@ static void codecommutative (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { int flip = 0; if (isSCint(e1)) { - expdesc temp = *e1; *e1 = *e2; *e2 = temp; /* swap 'e1' and 'e2' */ + swapexps(e1, e2); flip = 1; } codearith(fs, op, e1, e2, flip, line); @@ -1259,10 +1283,6 @@ static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { int rk2 = luaK_exp2anyreg(fs, e2); freeexps(fs, e1, e2); switch (opr) { - case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ - e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); - break; - } case OPR_GT: case OPR_GE: { /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); @@ -1284,21 +1304,28 @@ static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { ** '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 */ + int r1, r2; + lua_Integer im; + OpCode op; + if (e1->k != VNONRELOC) { + lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT); + swapexps(e1, e2); + } + r1 = luaK_exp2anyreg(fs, e1); /* 1nd expression must be in register */ + if (isSCnumber(e2, &im)) { + op = OP_EQI; + r2 = cast_int(im); /* immediate operand */ + } + else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + op = OP_EQK; + r2 = e2->u.info; /* constant index */ } 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 */ + op = OP_EQ; /* will compare two registers */ + r2 = luaK_exp2anyreg(fs, e2); } freeexps(fs, e1, e2); - e1->u.info = condjump(fs, op, (opr == OPR_EQ), r1, rk2); + e1->u.info = condjump(fs, op, (opr == OPR_EQ), r1, r2); e1->k = VJMP; } @@ -1351,7 +1378,9 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { break; } case OPR_EQ: case OPR_NE: { - luaK_exp2RK(fs, v); + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be an immediate operand */ break; } case OPR_LT: case OPR_LE: diff --git a/lopcodes.c b/lopcodes.c index 87408752..05700950 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.67 2017/11/07 17:20:42 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.68 2017/11/16 12:59:14 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -67,6 +67,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "LT", "LE", "EQK", + "EQI", "TEST", "TESTSET", "CALL", @@ -135,6 +136,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,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_TEST */ ,opmode(1, 1, iABC) /* OP_TESTSET */ ,opmode(0, 1, iABC) /* OP_CALL */ diff --git a/lopcodes.h b/lopcodes.h index a805ba63..6829711c 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.167 2017/11/07 17:20:42 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.168 2017/11/16 12:59:14 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -241,6 +241,7 @@ 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_EQI,/* A B C if ((R(B) == 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 b673db91..6c4bab08 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.312 2017/11/20 12:57:39 roberto Exp roberto $ +** $Id: lvm.c,v 2.313 2017/11/21 14:17:35 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1392,6 +1392,17 @@ void luaV_execute (lua_State *L) { donextjump(ci); vmbreak; } + vmcase(OP_EQI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + if ((ttisinteger(rb) ? (ivalue(rb) == ic) + :ttisfloat(rb) ? luai_numeq(fltvalue(rb), cast_num(ic)) + : 0) != 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