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

ruby-changes:71675

From: NAKAMURA <ko1@a...>
Date: Thu, 7 Apr 2022 22:52:58 +0900 (JST)
Subject: [ruby-changes:71675] 5da2a3e316 (ruby_2_7): merge revision(s) 7ff1bf317887c0d7b21e91ad548d07b9f05c540c,e89d80702bd98a8276243a7fcaa2a158b3bfb659: [Backport #18516]

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

From 5da2a3e31699570ae1a951c8bbc489040051d19e Mon Sep 17 00:00:00 2001
From: NAKAMURA Usaku <usa@r...>
Date: Sat, 19 Mar 2022 22:34:37 +0900
Subject: merge revision(s)
 7ff1bf317887c0d7b21e91ad548d07b9f05c540c,e89d80702bd98a8276243a7fcaa2a158b3bfb659:
 [Backport #18516]

    An alias can suppress method redefinition warning

    ---
     test/ruby/test_alias.rb | 11 +++++++++++
     1 file changed, 11 insertions(+)

    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(-)
---
 method.h                |  1 +
 test/ruby/test_alias.rb | 29 +++++++++++++++++++++++++++++
 version.h               |  2 +-
 vm_method.c             |  9 ++++++++-
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/method.h b/method.h
index b26caaa92d..18deea7b03 100644
--- a/method.h
+++ b/method.h
@@ -164,6 +164,7 @@ struct rb_method_definition_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L164
     BITFIELD(rb_method_type_t, type, VM_METHOD_TYPE_MINIMUM_BITS);
     int alias_count : 28;
     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 33fb82e1d7..1acf12f7f3 100644
--- a/test/ruby/test_alias.rb
+++ b/test/ruby/test_alias.rb
@@ -227,4 +227,33 @@ class TestAlias < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_alias.rb#L227
     assert_equal(:foo, k.instance_method(:bar).original_name)
     assert_equal(:foo, name)
   end
+
+  def test_alias_suppressing_redefinition
+    assert_in_out_err(%w[-w], "#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      class A
+        def foo; end
+        alias foo foo
+        def foo; end
+      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/version.h b/version.h
index db464e84d0..8afa4b53af 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L2
 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 #define RUBY_VERSION_TEENY 6
 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 214
+#define RUBY_PATCHLEVEL 215
 
 #define RUBY_RELEASE_YEAR 2022
 #define RUBY_RELEASE_MONTH 3
diff --git a/vm_method.c b/vm_method.c
index 3c087841dc..270334ea1b 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -584,6 +584,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#L584
 	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 &&
@@ -698,7 +699,13 @@ method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L699
 		 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/

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