aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean byroot Boussier <jean.boussier+github@shopify.com>2023-08-02 17:33:12 +0200
committerGitHub <noreply@github.com>2023-08-02 11:33:12 -0400
commite20f1e443f6d0a4d377ef237fffc1f4c6e27c9e1 (patch)
tree02888128443cfd17bae4d203c7f66ae5a44889c7
parent3c41a04b6cedbace1406d46a20a673f59b1502de (diff)
downloadruby-e20f1e443f6d0a4d377ef237fffc1f4c6e27c9e1.tar.gz
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 <byroot@ruby-lang.org>
-rw-r--r--test/ruby/test_yjit.rb23
-rw-r--r--yjit/src/codegen.rs2
2 files changed, 24 insertions, 1 deletions
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 };