[前][次][番号順一覧][スレッド一覧]

ruby-changes:67286

From: Nobuyoshi <ko1@a...>
Date: Sun, 29 Aug 2021 18:37:16 +0900 (JST)
Subject: [ruby-changes:67286] a615885f1e (master): Free previously used tables [Bug #18134]

https://git.ruby-lang.org/ruby.git/commit/?id=a615885f1e

From a615885f1e87f4bfbc5398b060fd3a64d5de8c4a Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Sun, 29 Aug 2021 16:47:26 +0900
Subject: Free previously used tables [Bug #18134]

---
 hash.c                 | 22 +++++++---------------
 test/ruby/test_hash.rb |  9 +++++++++
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/hash.c b/hash.c
index 6675b81..314ac18 100644
--- a/hash.c
+++ b/hash.c
@@ -2951,25 +2951,17 @@ rb_hash_replace(VALUE hash, VALUE hash2) https://github.com/ruby/ruby/blob/trunk/hash.c#L2951
     COPY_DEFAULT(hash, hash2);
 
     if (RHASH_AR_TABLE_P(hash)) {
-        if (RHASH_AR_TABLE_P(hash2)) {
-            ar_clear(hash);
-        }
-        else {
-            ar_free_and_clear_table(hash);
-            RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), RHASH_SIZE(hash2)));
-        }
+        ar_free_and_clear_table(hash);
     }
     else {
-        if (RHASH_AR_TABLE_P(hash2)) {
-            st_free_table(RHASH_ST_TABLE(hash));
-            RHASH_ST_CLEAR(hash);
-        }
-        else {
-            st_clear(RHASH_ST_TABLE(hash));
-            RHASH_TBL_RAW(hash)->type = RHASH_ST_TABLE(hash2)->type;
-        }
+        st_free_table(RHASH_ST_TABLE(hash));
+        RHASH_ST_CLEAR(hash);
     }
     hash_copy(hash, hash2);
+    if (RHASH_EMPTY_P(hash2) && RHASH_ST_TABLE_P(hash2)) {
+        /* ident hash */
+        RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), 0));
+    }
 
     rb_gc_writebarrier_remember(hash);
 
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index ac0d1df..f79879c 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -1278,6 +1278,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1278
     assert_raise(FrozenError) { h2.replace(42) }
   end
 
+  def test_replace_memory_leak
+    assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}")
+    h = ("aa".."zz").each_with_index.to_h
+    10_000.times {h.dup}
+    begin;
+      500_000.times {h.dup.replace(h)}
+    end;
+  end
+
   def test_size2
     assert_equal(0, @cls[].size)
   end
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]