<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/test/ruby/test_variable.rb, branch v3_2_11</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Fix cvar caching when class is cloned</title>
<updated>2023-07-01T05:17:30+00:00</updated>
<author>
<name>eileencodes</name>
<email>eileencodes@gmail.com</email>
</author>
<published>2023-02-07T20:46:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=8a3d57971c99680d4baec84553247b9c6ee41080'/>
<id>8a3d57971c99680d4baec84553247b9c6ee41080</id>
<content type='text'>
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 &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Copy cvar table on clone</title>
<updated>2023-07-01T05:17:30+00:00</updated>
<author>
<name>eileencodes</name>
<email>eileencodes@gmail.com</email>
</author>
<published>2023-02-08T20:27:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=06dae46036316e6e9926c4613ac8058b78eb7f2e'/>
<id>06dae46036316e6e9926c4613ac8058b78eb7f2e</id>
<content type='text'>
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 &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>merge revision(s) ed6fbb79e19bf401db0e85447fee955fd10a25c7: [Backport #19339]</title>
<updated>2023-01-20T08:01:47+00:00</updated>
<author>
<name>NARUSE, Yui</name>
<email>naruse@airemix.jp</email>
</author>
<published>2023-01-20T08:01:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c0df0a85dec77a09308caddb1e1efd4d38fbf7b8'/>
<id>c0df0a85dec77a09308caddb1e1efd4d38fbf7b8</id>
<content type='text'>
	Fix crash when defining ivars on special constants

	[Bug #19339]
	---
	 test/ruby/test_variable.rb | 6 ++++++
	 vm_insnhelper.c            | 5 +++++
	 2 files changed, 11 insertions(+)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	Fix crash when defining ivars on special constants

	[Bug #19339]
	---
	 test/ruby/test_variable.rb | 6 ++++++
	 vm_insnhelper.c            | 5 +++++
	 2 files changed, 11 insertions(+)
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove cvar overtaken classes at end of test methods</title>
<updated>2021-03-10T20:09:45+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2021-03-10T20:09:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d9fea496afed5a35d2f79ea3cac35176966dd471'/>
<id>d9fea496afed5a35d2f79ea3cac35176966dd471</id>
<content type='text'>
Fixes issues when the same tests are executed more than once,
which some CI machines do.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fixes issues when the same tests are executed more than once,
which some CI machines do.
</pre>
</div>
</content>
</entry>
<entry>
<title>Add cvar overtaken tests</title>
<updated>2021-03-10T17:40:00+00:00</updated>
<author>
<name>eileencodes</name>
<email>eileencodes@gmail.com</email>
</author>
<published>2021-02-25T17:42:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=cbc7c1c06145b02b3d887a6fb2c3b6d9e4bb22dd'/>
<id>cbc7c1c06145b02b3d887a6fb2c3b6d9e4bb22dd</id>
<content type='text'>
While working on another project we noticed that there were no tests for
the cvar overtaken exception when using classes. This change adds a test
for cvar overtaken with classes and moves the cvar overtaken test for
modules into the new file.

Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
While working on another project we noticed that there were no tests for
the cvar overtaken exception when using classes. This change adds a test
for cvar overtaken with classes and moves the cvar overtaken test for
modules into the new file.

Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Raise RuntimeError for class variable overtaken in nonverbose mode</title>
<updated>2020-06-18T15:21:29+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2020-06-11T01:53:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=95dc9c07f3a895f45cfb5dab235cd78f157a9e51'/>
<id>95dc9c07f3a895f45cfb5dab235cd78f157a9e51</id>
<content type='text'>
900e83b50115afda3f79712310e4cb95e4508972 changed from a warning
to an error in this case, but the warning was only issued in
verbose mode, and therefore the error was only raised in verbose
mode.  That was not intentional, verbose mode should only change
whether warnings are emitted, not other behavior.  This issues
the RuntimeError in all cases.

This change broke a couple tests, as the tests actually issued
the warning and therefore now raise an error.  This wasn't caught
earlier as test_variable suppressed the warning in this case,
effectively setting $VERBOSE = false around the code that warned.
basictest isn't run in verbose mode and therefore didn't expose
the issue previously. Fix these tests.

Fixes [Bug #14541]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
900e83b50115afda3f79712310e4cb95e4508972 changed from a warning
to an error in this case, but the warning was only issued in
verbose mode, and therefore the error was only raised in verbose
mode.  That was not intentional, verbose mode should only change
whether warnings are emitted, not other behavior.  This issues
the RuntimeError in all cases.

This change broke a couple tests, as the tests actually issued
the warning and therefore now raise an error.  This wasn't caught
earlier as test_variable suppressed the warning in this case,
effectively setting $VERBOSE = false around the code that warned.
basictest isn't run in verbose mode and therefore didn't expose
the issue previously. Fix these tests.

Fixes [Bug #14541]
</pre>
</div>
</content>
</entry>
<entry>
<title>Prohibit setting class variable on frozen module through inheritance</title>
<updated>2020-06-11T18:46:08+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2020-06-10T22:44:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e100fcbdd1e81c23e3b4c87964aff210232903a8'/>
<id>e100fcbdd1e81c23e3b4c87964aff210232903a8</id>
<content type='text'>
Setting class varibles goes through the ancestor list which can
contain iclasses. Iclasses share a lot of information with the
module they are made from, but not the frozen status.

Check the frozen status of the module instead of the iclass.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Setting class varibles goes through the ancestor list which can
contain iclasses. Iclasses share a lot of information with the
module they are made from, but not the frozen status.

Check the frozen status of the module instead of the iclass.
</pre>
</div>
</content>
</entry>
<entry>
<title>Supress class variable overtaken warning when original modules are the same</title>
<updated>2019-11-29T18:32:03+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2019-11-29T01:28:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=0c273b2279e65c57161e0859f2d4e9f6e649b751'/>
<id>0c273b2279e65c57161e0859f2d4e9f6e649b751</id>
<content type='text'>
This issue was exposed by recent commits to better support including
refined modules.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This issue was exposed by recent commits to better support including
refined modules.
</pre>
</div>
</content>
</entry>
<entry>
<title>* remove trailing spaces. [ci skip]</title>
<updated>2019-11-28T18:11:28+00:00</updated>
<author>
<name>git</name>
<email>svn-admin@ruby-lang.org</email>
</author>
<published>2019-11-28T18:11:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d104ebf2c4fef4751e067ea7a2c7e664a843e088'/>
<id>d104ebf2c4fef4751e067ea7a2c7e664a843e088</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>fastpath for ivar read of FL_EXIVAR objects.</title>
<updated>2019-11-28T18:11:04+00:00</updated>
<author>
<name>Koichi Sasada</name>
<email>ko1@atdot.net</email>
</author>
<published>2019-11-28T18:02:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=dd723771c118da71aa58bb74537cacaec425542a'/>
<id>dd723771c118da71aa58bb74537cacaec425542a</id>
<content type='text'>
vm_getivar() provides fastpath for T_OBJECT by caching an index
of ivar. This patch also provides fastpath for FL_EXIVAR objects.
FL_EXIVAR objects have an each ivar array and index can be cached
as T_OBJECT. To access this ivar array, generic_iv_tbl is exposed
by rb_ivar_generic_ivtbl() (declared in variable.h which is newly
introduced).

Benchmark script:

Benchmark.driver(repeat_count: 3){|x|
  x.executable name: 'clean', command: %w'../clean/miniruby'
  x.executable name: 'trunk', command: %w'./miniruby'

  objs = [Object.new, 'str', {a: 1, b: 2}, [1, 2]]

  objs.each.with_index{|obj, i|
    rep = obj.inspect
    rep = 'Object.new' if /\#/ =~ rep
    x.prelude str = %Q{
      v#{i} = #{rep}
      def v#{i}.foo
        @iv # ivar access method (attr_reader)
      end
      v#{i}.instance_variable_set(:@iv, :iv)
    }
    puts str
    x.report %Q{
      v#{i}.foo
    }
  }
}

Result:

      v0.foo # T_OBJECT

               clean:  85387141.8 i/s
               trunk:  85249373.6 i/s - 1.00x  slower

      v1.foo # T_STRING

               trunk:  57894407.5 i/s
               clean:  39957178.6 i/s - 1.45x  slower

      v2.foo # T_HASH

               trunk:  56629413.2 i/s
               clean:  39227088.9 i/s - 1.44x  slower

      v3.foo # T_ARRAY

               trunk:  55797530.2 i/s
               clean:  38263572.9 i/s - 1.46x  slower
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
vm_getivar() provides fastpath for T_OBJECT by caching an index
of ivar. This patch also provides fastpath for FL_EXIVAR objects.
FL_EXIVAR objects have an each ivar array and index can be cached
as T_OBJECT. To access this ivar array, generic_iv_tbl is exposed
by rb_ivar_generic_ivtbl() (declared in variable.h which is newly
introduced).

Benchmark script:

Benchmark.driver(repeat_count: 3){|x|
  x.executable name: 'clean', command: %w'../clean/miniruby'
  x.executable name: 'trunk', command: %w'./miniruby'

  objs = [Object.new, 'str', {a: 1, b: 2}, [1, 2]]

  objs.each.with_index{|obj, i|
    rep = obj.inspect
    rep = 'Object.new' if /\#/ =~ rep
    x.prelude str = %Q{
      v#{i} = #{rep}
      def v#{i}.foo
        @iv # ivar access method (attr_reader)
      end
      v#{i}.instance_variable_set(:@iv, :iv)
    }
    puts str
    x.report %Q{
      v#{i}.foo
    }
  }
}

Result:

      v0.foo # T_OBJECT

               clean:  85387141.8 i/s
               trunk:  85249373.6 i/s - 1.00x  slower

      v1.foo # T_STRING

               trunk:  57894407.5 i/s
               clean:  39957178.6 i/s - 1.45x  slower

      v2.foo # T_HASH

               trunk:  56629413.2 i/s
               clean:  39227088.9 i/s - 1.44x  slower

      v3.foo # T_ARRAY

               trunk:  55797530.2 i/s
               clean:  38263572.9 i/s - 1.46x  slower
</pre>
</div>
</content>
</entry>
</feed>
