compare_by_identity: remove alloc for empty Hash
For non-empty Hashes, this function needs to rehash all the stored values (using the new `compare` and `hash` functions from `identhash`). It does so by writing into a newly allocated `tmp` Hash, and then transferring ownership of its st table into `self`. For empty Hashes, we can skip allocating this `tmp`, because there's nothing to re-hash. We can just modify our new st table's `type` in-place.
This commit is contained in:
parent
893fe30ef2
commit
b5c6c0122f
21
hash.c
21
hash.c
@ -4380,15 +4380,22 @@ rb_hash_compare_by_id(VALUE hash)
|
|||||||
ar_force_convert_table(hash, __FILE__, __LINE__);
|
ar_force_convert_table(hash, __FILE__, __LINE__);
|
||||||
HASH_ASSERT(RHASH_ST_TABLE_P(hash));
|
HASH_ASSERT(RHASH_ST_TABLE_P(hash));
|
||||||
|
|
||||||
tmp = hash_alloc(0);
|
if (RHASH_TABLE_EMPTY_P(hash)) {
|
||||||
hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
|
// Fast path: There's nothing to rehash, so we don't need a `tmp` table.
|
||||||
identtable = RHASH_ST_TABLE(tmp);
|
RHASH_ST_TABLE(hash)->type = &identhash;
|
||||||
|
} 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);
|
||||||
|
hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
|
||||||
|
identtable = RHASH_ST_TABLE(tmp);
|
||||||
|
|
||||||
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
|
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
|
||||||
|
|
||||||
rb_hash_free(hash);
|
rb_hash_free(hash);
|
||||||
RHASH_ST_TABLE_SET(hash, identtable);
|
RHASH_ST_TABLE_SET(hash, identtable);
|
||||||
RHASH_ST_CLEAR(tmp);
|
RHASH_ST_CLEAR(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user