diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-08-10 12:31:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-08-10 12:31:44 -0300 |
commit | 1b4480003b1bfa7e1d34e587ebd19a9de63c6467 (patch) | |
tree | 2c1ded051c89e62a49c156c63a1ccfde9f8818c1 /lcode.c | |
parent | 42167804b89b26428dea98b97549892c24623d71 (diff) | |
download | lua-1b4480003b1bfa7e1d34e587ebd19a9de63c6467.tar.gz lua-1b4480003b1bfa7e1d34e587ebd19a9de63c6467.tar.bz2 lua-1b4480003b1bfa7e1d34e587ebd19a9de63c6467.zip |
"stange numbers" (-0 and NaN) also go to the constant table (as
strings with their binary representation). Therefore, constant
folding may produce these results.
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 45 |
1 files changed, 29 insertions, 16 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.39 2009/06/17 17:49:09 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.40 2009/06/18 16:35:05 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,6 +21,7 @@ | |||
21 | #include "lobject.h" | 21 | #include "lobject.h" |
22 | #include "lopcodes.h" | 22 | #include "lopcodes.h" |
23 | #include "lparser.h" | 23 | #include "lparser.h" |
24 | #include "lstring.h" | ||
24 | #include "ltable.h" | 25 | #include "ltable.h" |
25 | 26 | ||
26 | 27 | ||
@@ -224,22 +225,24 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { | |||
224 | lua_State *L = fs->L; | 225 | lua_State *L = fs->L; |
225 | TValue *idx = luaH_set(L, fs->h, key); | 226 | TValue *idx = luaH_set(L, fs->h, key); |
226 | Proto *f = fs->f; | 227 | Proto *f = fs->f; |
227 | int k; | 228 | int k, oldsize; |
228 | if (ttisnumber(idx)) { | 229 | if (ttisnumber(idx)) { |
229 | lua_Number n = nvalue(idx); | 230 | lua_Number n = nvalue(idx); |
230 | lua_number2int(k, n); | 231 | lua_number2int(k, n); |
231 | lua_assert(luaO_rawequalObj(&f->k[k], v)); | 232 | if (luaO_rawequalObj(&f->k[k], v)) |
232 | } | 233 | return k; |
233 | else { /* constant not found; create a new entry */ | 234 | /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); |
234 | int oldsize = f->sizek; | 235 | go through and create a new entry for this value */ |
235 | k = fs->nk; | ||
236 | setnvalue(idx, cast_num(k)); | ||
237 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Bx, "constants"); | ||
238 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
239 | setobj(L, &f->k[k], v); | ||
240 | fs->nk++; | ||
241 | luaC_barrier(L, f, v); | ||
242 | } | 236 | } |
237 | /* constant not found; create a new entry */ | ||
238 | oldsize = f->sizek; | ||
239 | k = fs->nk; | ||
240 | setnvalue(idx, cast_num(k)); | ||
241 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Bx, "constants"); | ||
242 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | ||
243 | setobj(L, &f->k[k], v); | ||
244 | fs->nk++; | ||
245 | luaC_barrier(L, f, v); | ||
243 | return k; | 246 | return k; |
244 | } | 247 | } |
245 | 248 | ||
@@ -252,9 +255,20 @@ int luaK_stringK (FuncState *fs, TString *s) { | |||
252 | 255 | ||
253 | 256 | ||
254 | int luaK_numberK (FuncState *fs, lua_Number r) { | 257 | int luaK_numberK (FuncState *fs, lua_Number r) { |
258 | int n; | ||
259 | lua_State *L = fs->L; | ||
255 | TValue o; | 260 | TValue o; |
256 | setnvalue(&o, r); | 261 | setnvalue(&o, r); |
257 | return addk(fs, &o, &o); | 262 | if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ |
263 | /* use raw representation as key to avoid numeric problems */ | ||
264 | setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r))); | ||
265 | incr_top(L); | ||
266 | n = addk(fs, L->top - 1, &o); | ||
267 | L->top--; | ||
268 | } | ||
269 | else | ||
270 | n = addk(fs, &o, &o); /* regular case */ | ||
271 | return n; | ||
258 | } | 272 | } |
259 | 273 | ||
260 | 274 | ||
@@ -643,7 +657,6 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |||
643 | if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) | 657 | if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) |
644 | return 0; /* do not attempt to divide by 0 */ | 658 | return 0; /* do not attempt to divide by 0 */ |
645 | r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); | 659 | r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); |
646 | if (luai_numisnan(NULL, r)) return 0; /* do not attempt to produce NaN */ | ||
647 | e1->u.nval = r; | 660 | e1->u.nval = r; |
648 | return 1; | 661 | return 1; |
649 | } | 662 | } |
@@ -690,7 +703,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { | |||
690 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; | 703 | e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
691 | switch (op) { | 704 | switch (op) { |
692 | case OPR_MINUS: { | 705 | case OPR_MINUS: { |
693 | if (isnumeral(e) && e->u.nval != 0) /* minus non-zero constant? */ | 706 | if (isnumeral(e)) /* minus constant? */ |
694 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ | 707 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ |
695 | else { | 708 | else { |
696 | luaK_exp2anyreg(fs, e); | 709 | luaK_exp2anyreg(fs, e); |