From 1b4480003b1bfa7e1d34e587ebd19a9de63c6467 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 10 Aug 2009 12:31:44 -0300 Subject: [PATCH] "stange numbers" (-0 and NaN) also go to the constant table (as strings with their binary representation). Therefore, constant folding may produce these results. --- lcode.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/lcode.c b/lcode.c index 3371b71c..1fe5874f 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.39 2009/06/17 17:49:09 roberto Exp roberto $ +** $Id: lcode.c,v 2.40 2009/06/18 16:35:05 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -21,6 +21,7 @@ #include "lobject.h" #include "lopcodes.h" #include "lparser.h" +#include "lstring.h" #include "ltable.h" @@ -224,22 +225,24 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { lua_State *L = fs->L; TValue *idx = luaH_set(L, fs->h, key); Proto *f = fs->f; - int k; + int k, oldsize; if (ttisnumber(idx)) { lua_Number n = nvalue(idx); lua_number2int(k, n); - lua_assert(luaO_rawequalObj(&f->k[k], v)); - } - else { /* constant not found; create a new entry */ - int oldsize = f->sizek; - k = fs->nk; - setnvalue(idx, cast_num(k)); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Bx, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); + if (luaO_rawequalObj(&f->k[k], v)) + return k; + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); + go through and create a new entry for this value */ } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + setnvalue(idx, cast_num(k)); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Bx, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); return k; } @@ -252,9 +255,20 @@ int luaK_stringK (FuncState *fs, TString *s) { int luaK_numberK (FuncState *fs, lua_Number r) { + int n; + lua_State *L = fs->L; TValue o; setnvalue(&o, r); - return addk(fs, &o, &o); + if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ + /* use raw representation as key to avoid numeric problems */ + setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r))); + incr_top(L); + n = addk(fs, L->top - 1, &o); + L->top--; + } + else + n = addk(fs, &o, &o); /* regular case */ + return n; } @@ -643,7 +657,6 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) return 0; /* do not attempt to divide by 0 */ r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); - if (luai_numisnan(NULL, r)) return 0; /* do not attempt to produce NaN */ e1->u.nval = r; return 1; } @@ -690,7 +703,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; switch (op) { case OPR_MINUS: { - if (isnumeral(e) && e->u.nval != 0) /* minus non-zero constant? */ + if (isnumeral(e)) /* minus constant? */ e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ else { luaK_exp2anyreg(fs, e);