From eaaf0b89553a9f61ea30dfff90f667092c7115ac Mon Sep 17 00:00:00 2001
From: Dylan Thacker-Smith <Dylan.Smith@shopify.com>
Date: Fri, 23 Aug 2019 00:48:06 -0400
Subject: [PATCH 4/4] Stop making a redundant hash copy in Hash#dup

It was making a copy of the hash without rehashing, then created an
extra copy of the hash to do the rehashing.  Since rehashing creates
a new copy already, this change just uses that rehashing to make
the copy.
---
 hash.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/hash.c b/hash.c
index aeddf44d34..08c2c97505 100644
--- a/hash.c
+++ b/hash.c
@@ -2800,18 +2800,14 @@ rb_hash_initialize_copy(VALUE hash, VALUE hash2)
         ar_free_and_clear_table(hash);
     }
 
-    if (RHASH_AR_TABLE_P(hash2)) {
-        ar_copy(hash, hash2);
-        if (RHASH_AR_TABLE_SIZE(hash))
-	    rb_hash_rehash(hash);
-    }
-    else {
-        RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(hash2)));
-        if (RHASH_ST_TABLE(hash)->num_entries)
-            rb_hash_rehash(hash);
+    unsigned long size = RHASH_SIZE(hash2);
+    if (size > RHASH_AR_TABLE_MAX_SIZE) {
+        RHASH_ST_TABLE_SET(hash, st_init_table_with_size(&objhash, size));
     }
 
+    rb_hash_foreach(hash2, rb_hash_rehash_i, (VALUE)hash);
     COPY_DEFAULT(hash, hash2);
+    rb_gc_writebarrier_remember(hash);
 
     return hash;
 }
-- 
2.21.0

