Skip to content

Commit

Permalink
Fix inline cache incoherency for ME resolved through VM_METHOD_TYPE_R…
Browse files Browse the repository at this point in the history
…EFINED

Previously, we didn't invalidate the method entry wrapped by
VM_METHOD_TYPE_REFINED method entries which could cause calls to
land in the wrong method like in the included test.

Fixup: cfd7729
See-also: e201b81
  • Loading branch information
XrXr committed Nov 25, 2023
1 parent fb7add4 commit cfdef36
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
22 changes: 22 additions & 0 deletions test/ruby/test_refinement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,28 @@ def to_s = :R
end;
end

def test_inline_cache_invalidation
klass = Class.new do
def cached_foo_callsite = foo

def foo = :v1

host = self
@refinement = Module.new do
refine(host) do
def foo = :unused
end
end
end

obj = klass.new
obj.cached_foo_callsite # prime cache
klass.class_eval do
def foo = :v2 # invalidate
end
assert_equal(:v2, obj.cached_foo_callsite)
end

private

def eval_using(mod, s)
Expand Down
7 changes: 7 additions & 0 deletions vm_method.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
vm_cme_invalidate((rb_callable_method_entry_t *)cme);
RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme);

// In case of refinement ME, also invalidate the wrapped ME that
// could be cached at some callsite and is unreachable from any
// RCLASS_CC_TBL.
if (cme->def->type == VM_METHOD_TYPE_REFINED && cme->def->body.refined.orig_me) {
vm_cme_invalidate((rb_callable_method_entry_t *)cme->def->body.refined.orig_me);
}

if (cme->def->iseq_overload) {
rb_callable_method_entry_t *monly_cme = (rb_callable_method_entry_t *)lookup_overloaded_cme(cme);
if (monly_cme) {
Expand Down

0 comments on commit cfdef36

Please sign in to comment.