compare_by_identity: remove alloc for non-empty Hash

If a Hash is non-empty, there's no point calling `ar_force_convert_table`. We'll be immediately discarding that new st table, and replacing it with the new `identtable` st table that we're stealing out of `tmp`.
This commit is contained in:
Alexander Momchilov 2023-12-18 03:19:02 -05:00 committed by Peter Zhu
parent b5c6c0122f
commit 11fa76b1b5

13
hash.c
View File

@ -4377,13 +4377,16 @@ rb_hash_compare_by_id(VALUE hash)
if (hash_iterating_p(hash)) {
rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
}
ar_force_convert_table(hash, __FILE__, __LINE__);
HASH_ASSERT(RHASH_ST_TABLE_P(hash));
if (RHASH_TABLE_EMPTY_P(hash)) {
// Fast path: There's nothing to rehash, so we don't need a `tmp` table.
// We're most likely an AR table, so this will need an allocation.
ar_force_convert_table(hash, __FILE__, __LINE__);
HASH_ASSERT(RHASH_ST_TABLE_P(hash));
RHASH_ST_TABLE(hash)->type = &identhash;
} else {
}
else {
// Slow path: Need to rehash the members of `self` into a new
// `tmp` table using the new `identhash` compare/hash functions.
tmp = hash_alloc(0);
@ -4391,8 +4394,10 @@ rb_hash_compare_by_id(VALUE hash)
identtable = RHASH_ST_TABLE(tmp);
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
rb_hash_free(hash);
// We know for sure `identtable` is an st table,
// so we can skip `ar_force_convert_table` here.
RHASH_ST_TABLE_SET(hash, identtable);
RHASH_ST_CLEAR(tmp);
}