diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2019-06-03 15:15:48 -0700 |
---|---|---|
committer | Aaron Patterson <tenderlove@ruby-lang.org> | 2019-06-03 15:15:48 -0700 |
commit | c9b74f9fd95113df903fc34cc1d6ec3fb3160c85 (patch) | |
tree | 3418ccd6497c5de25db984f2b8b906fd17eb148e | |
parent | 790a1b17902f7ccb5939b9e0314571079fc30bc8 (diff) |
Pin keys in "compare by identity" hashes
Hashes that compare by identity care about the location of the object in
memory. Since they care about the memory location, we can't let them
move.
-rw-r--r-- | gc.c | 16 |
1 files changed, 15 insertions, 1 deletions
@@ -4547,10 +4547,24 @@ mark_keyvalue(st_data_t key, st_data_t value, st_data_t data) return ST_CONTINUE; } +static int +pin_key_mark_value(st_data_t key, st_data_t value, st_data_t data) +{ + rb_objspace_t *objspace = (rb_objspace_t *)data; + + gc_mark_and_pin(objspace, (VALUE)key); + gc_mark(objspace, (VALUE)value); + return ST_CONTINUE; +} + static void mark_hash(rb_objspace_t *objspace, VALUE hash) { - rb_hash_stlike_foreach(hash, mark_keyvalue, (st_data_t)objspace); + if (rb_hash_compare_by_id_p(hash)) { + rb_hash_stlike_foreach(hash, pin_key_mark_value, (st_data_t)objspace); + } else { + rb_hash_stlike_foreach(hash, mark_keyvalue, (st_data_t)objspace); + } if (RHASH_AR_TABLE_P(hash)) { if (objspace->mark_func_data == NULL && RHASH_TRANSIENT_P(hash)) { |