summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-17 13:17:01 +0000
committerglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-17 13:17:01 +0000
commit7c1a2f61921392a7f8df3e52ca7ae5b78252f522 (patch)
tree6d879e4151b228d37b4a86f4a3a8d47efc181f87 /hash.c
parenta3b6aeba68a3ab2aa0124c384dcb518875179a65 (diff)
* hash.c (rb_hash_replace): performance improvement by using
st_copy(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/hash.c b/hash.c
index e170e67660..275d87f1d5 100644
--- a/hash.c
+++ b/hash.c
@@ -1342,21 +1342,35 @@ rb_hash_initialize_copy(VALUE hash, VALUE hash2)
static VALUE
rb_hash_replace(VALUE hash, VALUE hash2)
{
+ st_table *table2;
+
rb_hash_modify_check(hash);
- hash2 = to_hash(hash2);
if (hash == hash2) return hash;
- rb_hash_clear(hash);
- if (RHASH(hash2)->ntbl) {
- hash_tbl(hash);
- RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
- }
- rb_hash_foreach(hash2, replace_i, hash);
+ hash2 = to_hash(hash2);
+
RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
- if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
+ if (FL_TEST(hash2, HASH_PROC_DEFAULT))
FL_SET(hash, HASH_PROC_DEFAULT);
+ else
+ FL_UNSET(hash, HASH_PROC_DEFAULT);
+
+ table2 = RHASH(hash2)->ntbl;
+
+ if (RHASH_EMPTY_P(hash2)) {
+ rb_hash_clear(hash);
+ if (table2) hash_tbl(hash)->type = table2->type;
+ return hash;
+ }
+
+ if (RHASH_ITER_LEV(hash) > 0) {
+ rb_hash_clear(hash);
+ hash_tbl(hash)->type = table2->type;
+ rb_hash_foreach(hash2, replace_i, hash);
}
else {
- FL_UNSET(hash, HASH_PROC_DEFAULT);
+ st_table *old_table = RHASH(hash)->ntbl;
+ if (old_table) st_free_table(old_table);
+ RHASH(hash)->ntbl = st_copy(table2);
}
return hash;