summaryrefslogtreecommitdiff
path: root/test/ruby
diff options
context:
space:
mode:
authorEileen M. Uchitelle <eileencodes@users.noreply.github.com>2023-07-25 07:05:27 -0400
committerGitHub <noreply@github.com>2023-07-25 11:05:27 +0000
commitcba152ff1f69fad98f4c67747dcf763407cd1883 (patch)
treeb7a784de2e842a2bfc589b6d4d0909960734aa45 /test/ruby
parent7e926c4d8c2e785d174161b38a8a688b19ea4b99 (diff)
Backport cvar clone bug fix for 19379 to 3.1 (#7889)
* Copy cvar table on clone When a class with a class variable is cloned we need to also copy the cvar cache table from the original table to the clone. I found this bug while working on fixing [Bug #19379]. While this does not fix that bug directly it is still a required change to fix another bug revealed by the fix in https://github.com/ruby/ruby/pull/7265 This needs to be backported to 3.2.x and 3.1.x. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> * Fix cvar caching when class is cloned The class variable cache that was added in https://github.com/ruby/ruby/pull/4544 changed the behavior of class variables on cloned classes. As reported when a class is cloned AND a class variable was set, and the class variable was read from the original class, reading a class variable from the cloned class would return the value from the original class. This was happening because the IC (inline cache) is stored on the ISEQ which is shared between the original and cloned class, therefore they share the cache too. To fix this we are now storing the `cref` in the cache so that we can check if it's equal to the current `cref`. If it's different we don't want to read from the cache. If it's the same we do. Cloned classes don't share the same cref with their original class. This will need to be backported to 3.1 in addition to 3.2 since the bug exists in both versions. We also added a marking function which was missing. Fixes [Bug #19379] Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> * Add missing write barrier We were missing the write barrier for class_value to cref. This should fix the segv we were seeing in http://ci.rvm.jp/logfiles/brlog.trunk-gc-asserts.20230601-165052 Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> --------- Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/test_variable.rb19
1 files changed, 19 insertions, 0 deletions
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index f8a7c68fd3..d425b43b0d 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -33,6 +33,12 @@ class TestVariable < Test::Unit::TestCase
end
end
+ Athena = Gods.clone
+
+ def test_cloned_classes_copy_cvar_cache
+ assert_equal "Cronus", Athena.new.ruler0
+ end
+
def test_setting_class_variable_on_module_through_inheritance
mod = Module.new
mod.class_variable_set(:@@foo, 1)
@@ -43,6 +49,19 @@ class TestVariable < Test::Unit::TestCase
assert_equal(1, c.class_variable_get(:@@foo))
end
+ Zeus = Gods.clone
+
+ def test_cloned_allows_setting_cvar
+ Zeus.class_variable_set(:@@rule, "Athena")
+
+ god = Gods.new.ruler0
+ zeus = Zeus.new.ruler0
+
+ assert_equal "Cronus", god
+ assert_equal "Athena", zeus
+ assert_not_equal god.object_id, zeus.object_id
+ end
+
def test_singleton_class_included_class_variable
c = Class.new
c.extend(Olympians)