summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2023-06-29 09:14:55 -0400
committerPeter Zhu <peter@peterzhu.ca>2023-06-29 11:16:50 -0400
commitdf2b3a29987e9353596af76ed77f35d7366d654e (patch)
tree3b01c4925aa0a142150c42388fa46e9e09d526d2 /hash.c
parent3cfcd3d1663169ad68e22e5efef35f8057173993 (diff)
Refactor rb_hash_replace to use hash_copy
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/8000
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/hash.c b/hash.c
index f49f881990..a74db258e4 100644
--- a/hash.c
+++ b/hash.c
@@ -1460,14 +1460,31 @@ rb_hash_new_capa(long capa)
static VALUE
hash_copy(VALUE ret, VALUE hash)
{
- if (!RHASH_EMPTY_P(hash)) {
- if (RHASH_AR_TABLE_P(hash)) {
+ if (RHASH_AR_TABLE_P(hash)) {
+ if (RHASH_AR_TABLE_P(ret)) {
ar_copy(ret, hash);
}
else {
- RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash)));
+ st_table *tab = RHASH_ST_TABLE(ret);
+ rb_st_init_existing_table_with_size(tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
+
+ int bound = RHASH_AR_TABLE_BOUND(hash);
+ for (int i = 0; i < bound; i++) {
+ if (ar_cleared_entry(hash, i)) continue;
+
+ ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
+ st_add_direct(tab, pair->key, pair->val);
+ RB_OBJ_WRITTEN(ret, Qundef, pair->key);
+ RB_OBJ_WRITTEN(ret, Qundef, pair->val);
+ }
}
}
+ else {
+ HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table));
+
+ RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash)));
+ rb_gc_writebarrier_remember(ret);
+ }
return ret;
}
@@ -2877,31 +2894,7 @@ rb_hash_replace(VALUE hash, VALUE hash2)
RHASH_ST_CLEAR(hash);
}
- if (RHASH_AR_TABLE_P(hash2)) {
- if (RHASH_AR_TABLE_P(hash)) {
- ar_copy(hash, hash2);
- }
- else {
- st_table *tab = RHASH_ST_TABLE(hash);
- rb_st_init_existing_table_with_size(tab, &objhash, RHASH_AR_TABLE_SIZE(hash2));
-
- int bound = RHASH_AR_TABLE_BOUND(hash2);
- for (int i = 0; i < bound; i++) {
- if (ar_cleared_entry(hash2, i)) continue;
-
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash2, i);
- st_add_direct(tab, pair->key, pair->val);
- RB_OBJ_WRITTEN(hash, Qundef, pair->key);
- RB_OBJ_WRITTEN(hash, Qundef, pair->val);
- }
- }
- }
- else {
- HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table));
-
- RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(hash2)));
- rb_gc_writebarrier_remember(hash);
- }
+ hash_copy(hash, hash2);
return hash;
}