From 425d08c8e2e884d0fad32f564124639e6fe93cd0 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 7 Sep 2017 17:53:29 +0100 Subject: [PATCH] optimizer: improve hashing of variables during inlining When creating a copy of a variable in the process of inlining, make sure the copy has its own `eq?` hash code. --- racket/src/racket/src/hash.c | 15 ++++++++++++++- racket/src/racket/src/optimize.c | 1 + racket/src/racket/src/schpriv.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/racket/src/racket/src/hash.c b/racket/src/racket/src/hash.c index 242ec5cd6e..1ac82cc7e9 100644 --- a/racket/src/racket/src/hash.c +++ b/racket/src/racket/src/hash.c @@ -67,6 +67,10 @@ static void register_traversers(void); #define OBJ_HASH_USEFUL_BITS (16 - OBJ_HASH_USELESS_BITS) #define OBJ_HASH_USEFUL_MASK ((1 << OBJ_HASH_USEFUL_BITS)-1) +/* A hash code has been installed if any of these bits is + non-zero: */ +#define HASH_CODE_PRESENT_BITS 0xFFFC + #ifdef MZ_PRECISE_GC /* keygen race conditions below are "ok", because keygen is randomness used to create a hashkey. Technically, a race condition allows @@ -88,7 +92,7 @@ uintptr_t PTR_TO_LONG(Scheme_Object *o) v = o->keyex; - if (!(v & 0xFFFC)) { + if (!(v & HASH_CODE_PRESENT_BITS)) { uintptr_t local_keygen = keygen; v |= (short)local_keygen; #ifdef OBJHEAD_HAS_HASH_BITS @@ -128,6 +132,15 @@ uintptr_t PTR_TO_LONG(Scheme_Object *o) # define PTR_TO_LONG(p) ((uintptr_t)(p)>>2) #endif +void scheme_set_distinct_eq_hash(Scheme_Object *o) +/* Used after cloning a value to ensure that the + hash code is not cloned */ +{ +#ifdef MZ_PRECISE_GC + o->keyex = o->keyex & ~HASH_CODE_PRESENT_BITS; +#endif +} + void scheme_install_symbol_hash_code(Scheme_Object *sym, uintptr_t h) { #ifdef MZ_PRECISE_GC diff --git a/racket/src/racket/src/optimize.c b/racket/src/racket/src/optimize.c index 10e423bae1..8982848ba7 100644 --- a/racket/src/racket/src/optimize.c +++ b/racket/src/racket/src/optimize.c @@ -8386,6 +8386,7 @@ static Scheme_IR_Local *clone_variable(Scheme_IR_Local *var) MZ_ASSERT(SAME_TYPE(var->so.type, scheme_ir_local_type)); var2 = MALLOC_ONE_TAGGED(Scheme_IR_Local); memcpy(var2, var, sizeof(Scheme_IR_Local)); + scheme_set_distinct_eq_hash((Scheme_Object *)var2); return var2; } diff --git a/racket/src/racket/src/schpriv.h b/racket/src/racket/src/schpriv.h index 1f7467d2bb..6975dd521b 100644 --- a/racket/src/racket/src/schpriv.h +++ b/racket/src/racket/src/schpriv.h @@ -4510,6 +4510,8 @@ Scheme_Object *scheme_append_strings(Scheme_Object *s1, Scheme_Object *s2); void scheme_reset_hash_table(Scheme_Hash_Table *ht, int *history); +XFORM_NONGCING void scheme_set_distinct_eq_hash(Scheme_Object *var2); + XFORM_NONGCING Scheme_Object *scheme_regexp_source(Scheme_Object *re); int scheme_regexp_is_byte(Scheme_Object *re); int scheme_regexp_is_pregexp(Scheme_Object *re);