From e381c582de1b80a5f3df2c0d36fc25b415b48de0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 25 Apr 2013 16:12:41 -0300 Subject: [PATCH] integer handling for order comparisons, power, and modulo operations --- lvm.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- lvm.h | 5 +++- 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/lvm.c b/lvm.c index 96628872..212583f6 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.159 2013/04/25 15:59:42 roberto Exp roberto $ +** $Id: lvm.c,v 2.160 2013/04/25 16:07:52 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -150,7 +150,9 @@ static int l_strcmp (const TString *ls, const TString *rs) { int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttisnumber(l) && ttisnumber(r)) + if (ttisinteger(l) && ttisinteger(r)) + return (ivalue(l) < ivalue(r)); + else if (ttisnumber(l) && ttisnumber(r)) return luai_numlt(L, nvalue(l), nvalue(r)); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; @@ -162,7 +164,9 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttisnumber(l) && ttisnumber(r)) + if (ttisinteger(l) && ttisinteger(r)) + return (ivalue(l) <= ivalue(r)); + else if (ttisnumber(l) && ttisnumber(r)) return luai_numle(L, nvalue(l), nvalue(r)); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; @@ -283,6 +287,54 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { } +lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { + if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ + if (y == 0) + luaG_runerror(L, "attempt to divide by zero"); + else /* -1 */ + return -x; /* avoid overflow with 0x80000... */ + } + else { + lua_Integer d = x / y; /* perform division */ + if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ + return d; + else + return d - 1; /* correct 'div' for negative case */ + } +} + + +lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { + if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ + if (y == 0) + luaG_runerror(L, "attempt to divide by zero (in '%%')"); + else /* -1 */ + return 0; /* avoid overflow with 0x80000... */ + } + else { + lua_Integer r = x % y; + if (r == 0 || (x ^ y) >= 0) + return r; + else + return r + y; /* correct 'mod' for negative case */ + } +} + + +lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { + lua_Integer r = 1; + lua_assert(y >= 0); + if (y == 0) return r; + for (; y > 1; y >>= 1) { + if (y & 1) + r = cast_integer(cast_unsigned(r) * cast_unsigned(x)); + x = cast_integer(cast_unsigned(x) * cast_unsigned(x)); + } + r = cast_integer(cast_unsigned(r) * cast_unsigned(x)); + return r; +} + + void luaV_arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op) { TValue tempb, tempc; @@ -589,10 +641,32 @@ void luaV_execute (lua_State *L) { else { Protect(luaV_arith(L, ra, rb, rc, TM_DIV)); } ) vmcase(OP_MOD, - arith_op(luai_nummod, TM_MOD); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_mod(L, ib, ic)); + } + else if (ttisnumber(rb) && ttisnumber(rc)) { + lua_Number nb = nvalue(rb); lua_Number nc = nvalue(rc); + setnvalue(ra, luai_nummod(L, nb, nc)); + } + else { Protect(luaV_arith(L, ra, rb, rc, TM_MOD)); } ) vmcase(OP_POW, - arith_op(luai_numpow, TM_POW); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ic; + if (ttisinteger(rb) && ttisinteger(rc) && + (ic = ivalue(rc)) >= 0) { + lua_Integer ib = ivalue(rb); + setivalue(ra, luaV_pow(ib, ic)); + } + else if (ttisnumber(rb) && ttisnumber(rc)) { + lua_Number nb = nvalue(rb); lua_Number nc = nvalue(rc); + setnvalue(ra, luai_numpow(L, nb, nc)); + } + else { Protect(luaV_arith(L, ra, rb, rc, TM_POW)); } ) vmcase(OP_UNM, TValue *rb = RB(i); diff --git a/lvm.h b/lvm.h index 365e4a48..07235f19 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $ +** $Id: lvm.h,v 2.19 2013/04/15 15:44:46 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -33,6 +33,9 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op); LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);