aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcode.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/lcode.c b/lcode.c
index 8f08302e..641f0d09 100644
--- a/lcode.c
+++ b/lcode.c
@@ -557,8 +557,6 @@ static int addk (FuncState *fs, Proto *f, TValue *v) {
557** and try to reuse constants. Because some values should not be used 557** and try to reuse constants. Because some values should not be used
558** as keys (nil cannot be a key, integer keys can collapse with float 558** as keys (nil cannot be a key, integer keys can collapse with float
559** keys), the caller must provide a useful 'key' for indexing the cache. 559** keys), the caller must provide a useful 'key' for indexing the cache.
560** Note that all functions share the same table, so entering or exiting
561** a function can make some indices wrong.
562*/ 560*/
563static int k2proto (FuncState *fs, TValue *key, TValue *v) { 561static int k2proto (FuncState *fs, TValue *key, TValue *v) {
564 TValue val; 562 TValue val;
@@ -567,15 +565,14 @@ static int k2proto (FuncState *fs, TValue *key, TValue *v) {
567 int k; 565 int k;
568 if (!tagisempty(tag)) { /* is there an index there? */ 566 if (!tagisempty(tag)) { /* is there an index there? */
569 k = cast_int(ivalue(&val)); 567 k = cast_int(ivalue(&val));
570 lua_assert(k < fs->nk); 568 /* collisions can happen only for float keys */
571 /* correct value? (warning: must distinguish floats from integers!) */ 569 lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v));
572 if (ttypetag(&f->k[k]) == ttypetag(v) && luaV_rawequalobj(&f->k[k], v)) 570 return k; /* reuse index */
573 return k; /* reuse index */
574 } 571 }
575 /* constant not found; create a new entry */ 572 /* constant not found; create a new entry */
576 k = addk(fs, f, v); 573 k = addk(fs, f, v);
577 /* cache for reuse; numerical value does not need GC barrier; 574 /* cache it for reuse; numerical value does not need GC barrier;
578 table has no metatable, so it does not need to invalidate cache */ 575 table is not a metatable, so it does not need to invalidate cache */
579 setivalue(&val, k); 576 setivalue(&val, k);
580 luaH_set(fs->ls->L, fs->kcache, key, &val); 577 luaH_set(fs->ls->L, fs->kcache, key, &val);
581 return k; 578 return k;
@@ -607,27 +604,32 @@ static int luaK_intK (FuncState *fs, lua_Integer n) {
607** with actual integers. To that, we add to the number its smaller 604** with actual integers. To that, we add to the number its smaller
608** power-of-two fraction that is still significant in its scale. 605** power-of-two fraction that is still significant in its scale.
609** For doubles, that would be 1/2^52. 606** For doubles, that would be 1/2^52.
610** (This method is not bulletproof: there may be another float 607** This method is not bulletproof: different numbers may generate the
611** with that value, and for floats larger than 2^53 the result is 608** same key (e.g., very large numbers will overflow to 'inf') and for
612** still an integer. At worst, this only wastes an entry with 609** floats larger than 2^53 the result is still an integer. At worst,
613** a duplicate.) 610** this only wastes an entry with a duplicate.
614*/ 611*/
615static int luaK_numberK (FuncState *fs, lua_Number r) { 612static int luaK_numberK (FuncState *fs, lua_Number r) {
616 TValue o; 613 TValue o, kv;
617 lua_Integer ik; 614 setfltvalue(&o, r); /* value as a TValue */
618 setfltvalue(&o, r); 615 if (r == 0) { /* handle zero as a special case */
619 if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ 616 setpvalue(&kv, fs); /* use FuncState as index */
620 return k2proto(fs, &o, &o); /* use number itself as key */ 617 return k2proto(fs, &kv, &o); /* cannot collide */
621 else { /* must build an alternative key */ 618 }
619 else {
622 const int nbm = l_floatatt(MANT_DIG); 620 const int nbm = l_floatatt(MANT_DIG);
623 const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1); 621 const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1);
624 const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ 622 const lua_Number k = r * (1 + q); /* key */
625 TValue kv; 623 lua_Integer ik;
626 setfltvalue(&kv, k); 624 setfltvalue(&kv, k); /* key as a TValue */
627 /* result is not an integral value, unless value is too large */ 625 if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integral value? */
628 lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || 626 int n = k2proto(fs, &kv, &o); /* use key */
629 l_mathop(fabs)(r) >= l_mathop(1e6)); 627 if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */
630 return k2proto(fs, &kv, &o); 628 return n;
629 }
630 /* else, either key is still an integer or there was a collision;
631 anyway, do not try to reuse constant; instead, create a new one */
632 return addk(fs, fs->f, &o);
631 } 633 }
632} 634}
633 635
@@ -658,7 +660,7 @@ static int boolT (FuncState *fs) {
658static int nilK (FuncState *fs) { 660static int nilK (FuncState *fs) {
659 TValue k, v; 661 TValue k, v;
660 setnilvalue(&v); 662 setnilvalue(&v);
661 /* cannot use nil as key; instead use table itself to represent nil */ 663 /* cannot use nil as key; instead use table itself */
662 sethvalue(fs->ls->L, &k, fs->kcache); 664 sethvalue(fs->ls->L, &k, fs->kcache);
663 return k2proto(fs, &k, &v); 665 return k2proto(fs, &k, &v);
664} 666}