summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2021-04-15 10:11:19 +0900
committernagachika <nagachika@ruby-lang.org>2021-04-15 10:25:30 +0900
commit84d9a9afc0b49d095541acb9832f8b12fb506e19 (patch)
tree1f6b27559c103dfffbe0977f0fe014e20ac07537 /hash.c
parentd5a34e1b142eccc54971494be2243a0c6ac01d94 (diff)
merge revision(s) 31e0382723bfb35cffe3ca485dd0577668cafa07,5e5fb72f99701dc27c66ab148471893f14e6d6f0,fb6ebe55d91187d9635e0183d47dbf38e95b1141,522d4cd32f7727886f4fcbc28ed29c08d361ee20: [Backport #17735]
Keep non evaluated keys in `Hash#transform_keys!` [Bug #17735] --- hash.c | 6 +++++- spec/ruby/core/hash/transform_keys_spec.rb | 12 +++++++++++- test/ruby/test_hash.rb | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) Clear an intermediate hash [Bug #17735] --- hash.c | 1 + 1 file changed, 1 insertion(+) Hide an intermediate array --- hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) Force recycle intermediate collection in Hash#transform_keys! [Bug #17735] * Force recycle intermediate hash * Force recycle intermediate array too https://github.com/ruby/ruby/pull/4329#issuecomment-808840718 --- hash.c | 2 ++ 1 file changed, 2 insertions(+)
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/hash.c b/hash.c
index 0ed2692f24..e29e98598a 100644
--- a/hash.c
+++ b/hash.c
@@ -3249,7 +3249,7 @@ rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
return result;
}
-static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash);
+static int flatten_i(VALUE key, VALUE val, VALUE ary);
/*
* call-seq:
@@ -3278,8 +3278,9 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
long i;
- VALUE pairs = rb_hash_flatten(0, NULL, hash);
- rb_hash_clear(hash);
+ VALUE new_keys = hash_alloc(0);
+ VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2);
+ rb_hash_foreach(hash, flatten_i, pairs);
for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
VALUE key = RARRAY_AREF(pairs, i), new_key, val;
@@ -3296,8 +3297,16 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
new_key = key;
}
val = RARRAY_AREF(pairs, i+1);
+ if (!hash_stlike_lookup(new_keys, key, NULL)) {
+ rb_hash_stlike_delete(hash, &key, NULL);
+ }
rb_hash_aset(hash, new_key, val);
+ rb_hash_aset(new_keys, new_key, Qnil);
}
+ rb_ary_clear(pairs);
+ rb_gc_force_recycle(pairs);
+ rb_hash_clear(new_keys);
+ rb_gc_force_recycle(new_keys);
}
return hash;
}