From 79f3403be0cdbec814be29308c0583599ca5824f Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 14 Apr 2020 23:49:28 -0700 Subject: [PATCH] Invalidate fastpath when calling attr_reader by super The same bug as 8355a99883 existed in attr_reader too. --- test/ruby/test_super.rb | 29 ++++++++++++++++++++++++++++- vm_insnhelper.c | 4 ++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index 7cbe851fdf..78c8ee5dc2 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -604,7 +604,7 @@ class TestSuper < Test::Unit::TestCase assert_equal :boo2, subklass.new.boo end - def test_super_attr_writer # Bug #16785 + def test_super_attr_writer # [Bug #16785] writer_class = Class.new do attr_writer :test end @@ -633,4 +633,31 @@ class TestSuper < Test::Unit::TestCase assert_equal 3, superwriter.instance_variable_get(:@test) assert_equal 4, inherited.instance_variable_get(:@test) end + + def test_super_attr_reader + writer_class = Class.new do + attr_reader :test + end + superwriter_class = Class.new(writer_class) do + def initialize + @test = 1 # index: 1 + end + + def test + super + end + end + inherited_class = Class.new(superwriter_class) do + def initialize + @a = nil + @test = 2 # index: 2 + end + end + + superwriter = superwriter_class.new + assert_equal 1, superwriter.test # set ic->index of superwriter_class#test to 1 + + inherited = inherited_class.new + assert_equal 2, inherited.test # it may read index=1 while it should be index=2 + end end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index c4a8dfaf61..70c957cd9a 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3235,9 +3235,9 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c switch (cached_cme->def->type) { // vm_call_refined (search_refined_method) assumes cc->call is vm_call_super_method on invokesuper case VM_METHOD_TYPE_REFINED: - // cc->klass is superclass of a class of receiver. Checking cc->klass is not enough to invalidate IVC for the receiver class. + // cc->klass is superclass of receiver class. Checking cc->klass is not enough to invalidate IVC for the receiver class. case VM_METHOD_TYPE_ATTRSET: - // TODO: case VM_METHOD_TYPE_IVAR: + case VM_METHOD_TYPE_IVAR: vm_cc_call_set(cd->cc, vm_call_super_method); // invalidate fastpath break; default: