ruby-changes:71031
From: Nobuyoshi <ko1@a...>
Date: Thu, 27 Jan 2022 15:46:37 +0900 (JST)
Subject: [ruby-changes:71031] e89d80702b (master): Fix memory leak at the same named alias [Bug #18516]
https://git.ruby-lang.org/ruby.git/commit/?id=e89d80702b From e89d80702bd98a8276243a7fcaa2a158b3bfb659 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Thu, 27 Jan 2022 00:28:39 +0900 Subject: Fix memory leak at the same named alias [Bug #18516] When aliasing a method to the same name method, set a separate bit flag on that method definition, instead of the reference count increment. Although this kind of alias has no actual effect at runtime, is used as the hack to suppress the method re-definition warning. --- method.h | 1 + test/ruby/test_alias.rb | 18 ++++++++++++++++++ vm_method.c | 9 ++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/method.h b/method.h index 815fd9da470..2f4504bfec9 100644 --- a/method.h +++ b/method.h @@ -181,6 +181,7 @@ struct rb_method_definition_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L181 unsigned int iseq_overload: 1; int alias_count : 27; int complemented_count : 28; + unsigned int no_redef_warning: 1; union { rb_method_iseq_t iseq; diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb index c6fad25cc24..99f2223b49d 100644 --- a/test/ruby/test_alias.rb +++ b/test/ruby/test_alias.rb @@ -264,4 +264,22 @@ class TestAlias < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_alias.rb#L264 end end; end + + def test_alias_memory_leak + assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true) + begin; + class A + 500.times do + 1000.times do |i| + define_method(:"foo_#{i}") {} + + alias :"foo_#{i}" :"foo_#{i}" + + remove_method :"foo_#{i}" + end + GC.start + end + end + end; + end end diff --git a/vm_method.c b/vm_method.c index 6867b5cf8c5..b926654bdcc 100644 --- a/vm_method.c +++ b/vm_method.c @@ -856,6 +856,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil https://github.com/ruby/ruby/blob/trunk/vm_method.c#L856 if (RTEST(ruby_verbose) && type != VM_METHOD_TYPE_UNDEF && (old_def->alias_count == 0) && + (!old_def->no_redef_warning) && !make_refined && old_def->type != VM_METHOD_TYPE_UNDEF && old_def->type != VM_METHOD_TYPE_ZSUPER && @@ -1086,7 +1087,13 @@ method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1087 rb_method_visibility_t visi, VALUE defined_class) { rb_method_entry_t *newme = rb_method_entry_make(klass, mid, defined_class, visi, - me->def->type, method_definition_addref(me->def), 0, NULL); + me->def->type, me->def, 0, NULL); + if (newme == me) { + me->def->no_redef_warning = TRUE; + } + else { + method_definition_addref(me->def); + } method_added(klass, mid); return newme; } -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/