diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-06-25 15:57:18 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-06-25 15:57:18 -0300 |
| commit | 483c2ccd0feb881947d2e2ce5177d0061d87adad (patch) | |
| tree | 0a79b9e1ebb71bd440356903e2f909862842838c | |
| parent | 982aa7058f62781960169a38e20781f76be29ac6 (diff) | |
| download | lua-483c2ccd0feb881947d2e2ce5177d0061d87adad.tar.gz lua-483c2ccd0feb881947d2e2ce5177d0061d87adad.tar.bz2 lua-483c2ccd0feb881947d2e2ce5177d0061d87adad.zip | |
avoid using raw representation of numbers for hashing, as number may
not use all its space (e.g., long double can have sizeof=12 but
use only 10 bytes)
| -rw-r--r-- | lcode.c | 40 |
1 files changed, 25 insertions, 15 deletions
| @@ -1,10 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.69 2013/05/06 17:22:16 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.70 2013/06/20 17:37:31 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 | */ |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | #include <math.h> | ||
| 8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| 9 | 10 | ||
| 10 | #define lcode_c | 11 | #define lcode_c |
| @@ -26,6 +27,14 @@ | |||
| 26 | #include "lvm.h" | 27 | #include "lvm.h" |
| 27 | 28 | ||
| 28 | 29 | ||
| 30 | /* test for x == -0 */ | ||
| 31 | #if defined(signbit) | ||
| 32 | #define isminuszero(x) ((x) == 0.0 && signbit(x)) | ||
| 33 | #else | ||
| 34 | #define isminuszero(x) ((x) == 0.0 && 1.0/(x) < 0.0) | ||
| 35 | #endif | ||
| 36 | |||
| 37 | |||
| 29 | #define hasjumps(e) ((e)->t != (e)->f) | 38 | #define hasjumps(e) ((e)->t != (e)->f) |
| 30 | 39 | ||
| 31 | 40 | ||
| @@ -332,30 +341,28 @@ int luaK_stringK (FuncState *fs, TString *s) { | |||
| 332 | } | 341 | } |
| 333 | 342 | ||
| 334 | 343 | ||
| 344 | /* | ||
| 345 | ** use userdata as key to avoid collision with float with same value; | ||
| 346 | ** conversion to 'void*' used only for hash, no "precision" problems | ||
| 347 | */ | ||
| 335 | int luaK_intK (FuncState *fs, lua_Integer n) { | 348 | int luaK_intK (FuncState *fs, lua_Integer n) { |
| 336 | TValue k, o; | 349 | TValue k, o; |
| 337 | /* use userdata as key to avoid collision with float with same value; | ||
| 338 | conversion to 'void*' used only for hash, no "precision" problems */ | ||
| 339 | setpvalue(&k, cast(void*, cast(size_t, n))); | 350 | setpvalue(&k, cast(void*, cast(size_t, n))); |
| 340 | setivalue(&o, n); | 351 | setivalue(&o, n); |
| 341 | return addk(fs, &k, &o); | 352 | return addk(fs, &k, &o); |
| 342 | } | 353 | } |
| 343 | 354 | ||
| 344 | 355 | ||
| 356 | /* | ||
| 357 | ** Both NaN and -0.0 should not go to the constant table, as they have | ||
| 358 | ** problems with the hashing. (NaN is not ** a valid key, | ||
| 359 | ** -0.0 collides with +0.0.) | ||
| 360 | */ | ||
| 345 | static int luaK_numberK (FuncState *fs, lua_Number r) { | 361 | static int luaK_numberK (FuncState *fs, lua_Number r) { |
| 346 | int n; | ||
| 347 | lua_State *L = fs->ls->L; | ||
| 348 | TValue o; | 362 | TValue o; |
| 363 | lua_assert(!luai_numisnan(NULL, r) && !isminuszero(r)); | ||
| 349 | setnvalue(&o, r); | 364 | setnvalue(&o, r); |
| 350 | if (r != 0 && !luai_numisnan(NULL, r)) /* avoid -0 and NaN */ | 365 | return addk(fs, &o, &o); |
| 351 | n = addk(fs, &o, &o); /* regular case */ | ||
| 352 | else { /* handle -0 and NaN */ | ||
| 353 | /* use raw representation as key to avoid numeric problems */ | ||
| 354 | setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); | ||
| 355 | n = addk(fs, L->top - 1, &o); | ||
| 356 | L->top--; | ||
| 357 | } | ||
| 358 | return n; | ||
| 359 | } | 366 | } |
| 360 | 367 | ||
| 361 | 368 | ||
| @@ -755,8 +762,11 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |||
| 755 | e1->u.ival = ivalue(&res); | 762 | e1->u.ival = ivalue(&res); |
| 756 | } | 763 | } |
| 757 | else { | 764 | else { |
| 765 | lua_Number n = fltvalue(&res); | ||
| 766 | if (luai_numisnan(NULL, n) || isminuszero(n)) | ||
| 767 | return 0; /* folds neither NaN nor -0 */ | ||
| 758 | e1->k = VKFLT; | 768 | e1->k = VKFLT; |
| 759 | e1->u.nval = fltvalue(&res); | 769 | e1->u.nval = n; |
| 760 | } | 770 | } |
| 761 | return 1; | 771 | return 1; |
| 762 | } | 772 | } |
