diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-03-30 14:49:18 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-03-30 14:49:18 -0300 |
commit | 36de01d9885562444ae2e2a3e0b7e01b3fb8743b (patch) | |
tree | 7aed386cc8d13e3b2a960404d2cf605d8090d571 /lcode.c | |
parent | 7fbe2158089898f09d741e991737f282e514ffaa (diff) | |
download | lua-36de01d9885562444ae2e2a3e0b7e01b3fb8743b.tar.gz lua-36de01d9885562444ae2e2a3e0b7e01b3fb8743b.tar.bz2 lua-36de01d9885562444ae2e2a3e0b7e01b3fb8743b.zip |
Changes in cache for function constants
In 'lcode.c', when adding constants to the list of constants of a
function, integers represent themselves in the cache and floats
with integral values get a small delta to avoid collision with
integers. (This change avoids creating artificial addresses; the old
implementation converted integers to pointers to index the cache.)
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 34 |
1 files changed, 26 insertions, 8 deletions
@@ -10,6 +10,7 @@ | |||
10 | #include "lprefix.h" | 10 | #include "lprefix.h" |
11 | 11 | ||
12 | 12 | ||
13 | #include <float.h> | ||
13 | #include <limits.h> | 14 | #include <limits.h> |
14 | #include <math.h> | 15 | #include <math.h> |
15 | #include <stdlib.h> | 16 | #include <stdlib.h> |
@@ -580,24 +581,41 @@ static int stringK (FuncState *fs, TString *s) { | |||
580 | 581 | ||
581 | /* | 582 | /* |
582 | ** Add an integer to list of constants and return its index. | 583 | ** Add an integer to list of constants and return its index. |
583 | ** Integers use userdata as keys to avoid collision with floats with | ||
584 | ** same value; conversion to 'void*' is used only for hashing, so there | ||
585 | ** are no "precision" problems. | ||
586 | */ | 584 | */ |
587 | static int luaK_intK (FuncState *fs, lua_Integer n) { | 585 | static int luaK_intK (FuncState *fs, lua_Integer n) { |
588 | TValue k, o; | 586 | TValue o; |
589 | setpvalue(&k, cast_voidp(cast_sizet(n))); | ||
590 | setivalue(&o, n); | 587 | setivalue(&o, n); |
591 | return addk(fs, &k, &o); | 588 | return addk(fs, &o, &o); /* use integer itself as key */ |
592 | } | 589 | } |
593 | 590 | ||
594 | /* | 591 | /* |
595 | ** Add a float to list of constants and return its index. | 592 | ** Add a float to list of constants and return its index. Floats |
593 | ** with integral values need a different key, to avoid collision | ||
594 | ** with actual integers. To that, we add to the number its smaller | ||
595 | ** power-of-two fraction that is still significant in its scale. | ||
596 | ** For doubles, that would be 1/2^52. | ||
597 | ** (This method is not bulletproof: there may be another float | ||
598 | ** with that value, and for floats larger than 2^53 the result is | ||
599 | ** still an integer. At worst, this only wastes an entry with | ||
600 | ** a duplicate.) | ||
596 | */ | 601 | */ |
597 | static int luaK_numberK (FuncState *fs, lua_Number r) { | 602 | static int luaK_numberK (FuncState *fs, lua_Number r) { |
598 | TValue o; | 603 | TValue o; |
604 | lua_Integer ik; | ||
599 | setfltvalue(&o, r); | 605 | setfltvalue(&o, r); |
600 | return addk(fs, &o, &o); /* use number itself as key */ | 606 | if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ |
607 | return addk(fs, &o, &o); /* use number itself as key */ | ||
608 | else { /* must build an alternative key */ | ||
609 | const int nbm = l_floatatt(MANT_DIG); | ||
610 | const lua_Number q = l_mathop(ldexp)(1.0, -nbm + 1); | ||
611 | const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ | ||
612 | TValue kv; | ||
613 | setfltvalue(&kv, k); | ||
614 | /* result is not an integral value, unless value is too large */ | ||
615 | lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || | ||
616 | l_mathop(fabs)(r) >= l_mathop(1e6)); | ||
617 | return addk(fs, &kv, &o); | ||
618 | } | ||
601 | } | 619 | } |
602 | 620 | ||
603 | 621 | ||