further tighten eq-hash code generation

Avoids including the bit thet indicates whether the object
is GCable in the eq hash code (in a configuration where
bits are available in the GC header for hashing).
This commit is contained in:
Matthew Flatt 2013-10-12 08:33:57 -06:00
parent 8b7b96215b
commit 2a79377c60

View File

@ -51,6 +51,22 @@ static void register_traversers(void);
#define to_signed_hash(v) ((intptr_t)v) #define to_signed_hash(v) ((intptr_t)v)
#define to_unsigned_hash(v) ((uintptr_t)v) #define to_unsigned_hash(v) ((uintptr_t)v)
#ifdef OBJHEAD_HAS_HASH_BITS
/* In 3m mode, we only have 14 bits of hash code in the
Scheme_Object header. But the GC-level object header has some
leftover bits (currently 9, 11, 41, or 43, depending on the
platform), so use those, too. That only works for GCable
objects, so we use 1 of our 14 bits to indicate whether the
other bits are present. */
# define GCABLE_OBJ_HASH_BIT 0x0004
# define OBJ_HASH_USELESS_BITS 3
#else
# define GCABLE_OBJ_HASH_BIT 0
# define OBJ_HASH_USELESS_BITS 2
#endif
#define OBJ_HASH_USEFUL_BITS (16 - OBJ_HASH_USELESS_BITS)
#define OBJ_HASH_USEFUL_MASK ((1 << OBJ_HASH_USEFUL_BITS)-1)
#ifdef MZ_PRECISE_GC #ifdef MZ_PRECISE_GC
/* keygen race conditions below are "ok", because keygen is randomness /* keygen race conditions below are "ok", because keygen is randomness
used to create a hashkey. Technically, a race condition allows used to create a hashkey. Technically, a race condition allows
@ -59,7 +75,7 @@ static void register_traversers(void);
that only one thread at a time sets a hash code in a specific that only one thread at a time sets a hash code in a specific
object, though, and watch out for a race with JIT-generated code object, though, and watch out for a race with JIT-generated code
running in a future and setting flags on pairs. */ running in a future and setting flags on pairs. */
SHARED_OK static uintptr_t keygen; SHARED_OK static uintptr_t keygen = GCABLE_OBJ_HASH_BIT;
XFORM_NONGCING static MZ_INLINE XFORM_NONGCING static MZ_INLINE
uintptr_t PTR_TO_LONG(Scheme_Object *o) uintptr_t PTR_TO_LONG(Scheme_Object *o)
@ -76,17 +92,11 @@ uintptr_t PTR_TO_LONG(Scheme_Object *o)
uintptr_t local_keygen = keygen; uintptr_t local_keygen = keygen;
v |= (short)local_keygen; v |= (short)local_keygen;
#ifdef OBJHEAD_HAS_HASH_BITS #ifdef OBJHEAD_HAS_HASH_BITS
/* In 3m mode, we only have 14 bits of hash code in the
Scheme_Object header. But the GC-level object header has some
leftover bits (currently 9, 11, 41, or 43, depending on the
platform), so use those, too. That only works for GCable
objects, so we use 1 of our 14 bits to indicate whether the
other bit are present. */
if (GC_is_allocated(o)) { if (GC_is_allocated(o)) {
OBJHEAD_HASH_BITS(o) = (local_keygen >> 16); OBJHEAD_HASH_BITS(o) = (local_keygen >> 16);
v |= 0x4000; v |= GCABLE_OBJ_HASH_BIT;
} else } else
v &= ~0x4000; v &= ~GCABLE_OBJ_HASH_BIT;
#endif #endif
if (!v) v = 0x1AD0; if (!v) v = 0x1AD0;
#ifdef MZ_USE_FUTURES #ifdef MZ_USE_FUTURES
@ -99,11 +109,11 @@ uintptr_t PTR_TO_LONG(Scheme_Object *o)
} else } else
#endif #endif
o->keyex = v; o->keyex = v;
keygen += 4; keygen += (1 << OBJ_HASH_USELESS_BITS);
} }
#ifdef OBJHEAD_HAS_HASH_BITS #ifdef OBJHEAD_HAS_HASH_BITS
if (v & 0x4000) if (v & GCABLE_OBJ_HASH_BIT)
bits = OBJHEAD_HASH_BITS(o); bits = OBJHEAD_HASH_BITS(o);
else else
#endif #endif
@ -112,7 +122,7 @@ uintptr_t PTR_TO_LONG(Scheme_Object *o)
/* We need to drop the low two bits of `v', which /* We need to drop the low two bits of `v', which
are used for non-hashing purposes in some types. */ are used for non-hashing purposes in some types. */
return (bits << 14) | ((v >> 2) & 0x3FFF); return (bits << OBJ_HASH_USEFUL_BITS) | ((v >> OBJ_HASH_USELESS_BITS) & OBJ_HASH_USEFUL_MASK);
} }
#else #else
# define PTR_TO_LONG(p) ((uintptr_t)(p)>>2) # define PTR_TO_LONG(p) ((uintptr_t)(p)>>2)