From e20f1e443f6d0a4d377ef237fffc1f4c6e27c9e1 Mon Sep 17 00:00:00 2001 From: Jean byroot Boussier Date: Wed, 2 Aug 2023 17:33:12 +0200 Subject: [PATCH] YJIT: Fallback setivar if the receiver isn't T_OBJECT (#8160) Followup: https://github.com/ruby/ruby/pull/8152 If the receiver is a T_MODULE or T_CLASS and has a lot of ivars, `get_next_shape_internal` will return `NULL`. Co-authored-by: Jean Boussier --- test/ruby/test_yjit.rb | 23 +++++++++++++++++++++++ yjit/src/codegen.rs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 61f86b7178..190073b028 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1238,6 +1238,29 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_setivar_on_class + # Bug in https://github.com/ruby/ruby/pull/8152 + assert_compiles(<<~RUBY, result: :ok) + class Base + def self.or_equal + @or_equal ||= Object.new + end + end + + Base.or_equal # ensure compiled + + class Child < Base + end + + 200.times do |iv| # Need to be more than MAX_IVAR + Child.instance_variable_set("@_iv_\#{iv}", Object.new) + end + + Child.or_equal + :ok + RUBY + end + def test_nested_send #[Bug #19464] assert_compiles(<<~RUBY, result: [:ok, :ok]) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 6b4c67d31e..312bf3db16 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -2204,7 +2204,7 @@ fn gen_setinstancevariable( }; // Get the next shape information if it needs transition - let new_shape = if !shape_too_complex && ivar_index.is_none() { + let new_shape = if !shape_too_complex && receiver_t_object && ivar_index.is_none() { let shape = comptime_receiver.shape_of(); let current_capacity = unsafe { (*shape).capacity };