mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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]
This commit is contained in:
parent
ec78b8b62a
commit
2943ff9d44
2 changed files with 59 additions and 8 deletions
|
@ -61,4 +61,50 @@ class TestMethod < Test::Unit::TestCase
|
|||
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
|
||||
|
|
21
vm_method.c
21
vm_method.c
|
@ -166,15 +166,20 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
|
|||
// 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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue