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

ruby-changes:60357

From: Koichi <ko1@a...>
Date: Wed, 11 Mar 2020 02:55:38 +0900 (JST)
Subject: [ruby-changes:60357] 2943ff9d44 (master): fix bug on method cache invalidation.

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

From 2943ff9d4441485a18773aa745bab7f47767dde2 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Wed, 11 Mar 2020 02:45:49 +0900
Subject: fix bug on method cache invalidation.

To invalidate cached method entry, existing method entry (ment)
is marked as invalidated and replace with copied ment. However,
complemented method entry (method entries in Module) should not
be set to Module's m_tbl.
[Bug #16669]

diff --git a/test/ruby/test_inlinecache.rb b/test/ruby/test_inlinecache.rb
index 90d0189..6c2d86a 100644
--- a/test/ruby/test_inlinecache.rb
+++ b/test/ruby/test_inlinecache.rb
@@ -61,4 +61,50 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_inlinecache.rb#L61
       assert_equal :E, test[]
     EOS
   end
+
+  def test_module_methods_redefiniton
+    m0 = Module.new do
+      def foo
+        super
+      end
+    end
+
+    c1 = Class.new do
+      def foo
+        :C1
+      end
+    end
+
+    c2 = Class.new do
+      def foo
+        :C2
+      end
+    end
+
+    d1 = Class.new(c1) do
+      include m0
+    end
+
+    d2 = Class.new(c2) do
+      include m0
+    end
+
+    assert_equal :C1, d1.new.foo
+
+    m = Module.new do
+      def foo
+        super
+      end
+    end
+
+    d1.class_eval do
+      include m
+    end
+
+    d2.class_eval do
+      include m
+    end
+
+    assert_equal :C2, d2.new.foo
+  end
 end
diff --git a/vm_method.c b/vm_method.c
index d1afb88..cce2846 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -166,15 +166,20 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L166
             // invalidate cme if found to invalidate the inline method cache.
 
             if (METHOD_ENTRY_CACHED(cme)) {
-                // invalidate cc by invalidating cc->cme
-                VALUE owner = cme->owner;
-                rb_callable_method_entry_t *new_cme =
-                  (rb_callable_method_entry_t *)rb_method_entry_clone((const rb_method_entry_t *)cme);
-                struct rb_id_table *mtbl = RCLASS_M_TBL(RCLASS_ORIGIN(owner));
-                rb_id_table_insert(mtbl, mid, (VALUE)new_cme);
-                RB_OBJ_WRITTEN(owner, cme, new_cme);
+                if (METHOD_ENTRY_COMPLEMENTED(cme)) {
+                    // do nothing
+                }
+                else {
+                    // invalidate cc by invalidating cc->cme
+                    VALUE owner = cme->owner;
+                    VM_ASSERT(BUILTIN_TYPE(owner) == T_CLASS);
+                    rb_callable_method_entry_t *new_cme =
+                      (rb_callable_method_entry_t *)rb_method_entry_clone((const rb_method_entry_t *)cme);
+                    struct rb_id_table *mtbl = RCLASS_M_TBL(RCLASS_ORIGIN(owner));
+                    rb_id_table_insert(mtbl, mid, (VALUE)new_cme);
+                    RB_OBJ_WRITTEN(owner, cme, new_cme);
+                }
                 vm_me_invalidate_cache((rb_callable_method_entry_t *)cme);
-
                 RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme);
             }
 
-- 
cgit v0.10.2


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

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