diff options
Diffstat (limited to 'lcode.c')
-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 | } |