summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorAlexander Momchilov <alexandermomchilov@gmail.com>2023-12-18 03:19:02 -0500
committerPeter Zhu <peter@peterzhu.ca>2023-12-18 14:51:16 -0500
commit11fa76b1b521072c200c78ea023960221ff426d6 (patch)
treea37c14a842ff533186c5e8959bd1fea1e6e29965 /hash.c
parentb5c6c0122f5b010cb5f43e7a236c4ba2b1d56a2a (diff)
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`.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/hash.c b/hash.c
index f6525ba4a5..78e9d9a2d6 100644
--- a/hash.c
+++ b/hash.c
@@ -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);
}