ruby-changes:36739
From: normal <ko1@a...>
Date: Sat, 13 Dec 2014 10:28:30 +0900 (JST)
Subject: [ruby-changes:36739] normal:r48820 (trunk): gc.c (define_final0): avoid duplicate blocks
normal 2014-12-13 10:28:18 +0900 (Sat, 13 Dec 2014) New Revision: 48820 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48820 Log: gc.c (define_final0): avoid duplicate blocks This prevents excessive memory growth when a WeakRef is repeatedly created * gc.c (define_final0): avoid duplicate blocks [Bug #10537] * test/test_weakref.rb (test_repeated_object_leak): new test Modified files: trunk/ChangeLog trunk/gc.c trunk/test/test_weakref.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 48819) +++ ChangeLog (revision 48820) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Dec 13 09:58:41 2014 Eric Wong <e@8...> + + * gc.c (define_final0): avoid duplicate blocks + [Bug #10537] + * test/test_weakref.rb (test_repeated_object_leak): new test + Sat Dec 13 04:59:20 2014 Nobuyoshi Nakada <nobu@r...> * bin/erb (ERB::Main#run): get rid of shadowing outer local Index: gc.c =================================================================== --- gc.c (revision 48819) +++ gc.c (revision 48820) @@ -2370,6 +2370,20 @@ define_final0(VALUE obj, VALUE block) https://github.com/ruby/ruby/blob/trunk/gc.c#L2370 if (st_lookup(finalizer_table, obj, &data)) { table = (VALUE)data; + + /* avoid duplicate block, table is usually small */ + { + const VALUE *ptr = RARRAY_CONST_PTR(table); + long len = RARRAY_LEN(table); + long i; + + for (i = 0; i < len; i++, ptr++) { + if (rb_funcall(*ptr, idEq, 1, block)) { + return *ptr; + } + } + } + rb_ary_push(table, block); } else { Index: test/test_weakref.rb =================================================================== --- test/test_weakref.rb (revision 48819) +++ test/test_weakref.rb (revision 48820) @@ -60,4 +60,12 @@ class TestWeakRef < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/test_weakref.rb#L60 end }, bug7304 end + + def test_repeated_object_leak + bug10537 = '[ruby-core:66428]' + assert_no_memory_leak(%w(-rweakref), '', <<-'end;', bug10537) + a = Object.new + 150_000.times { WeakRef.new(a) } + end; + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/