<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/vm_insnhelper.c, branch v3_3_11</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>merge revision(s) 08b3a45bc97c835b4677bf76dbce68fd51d81897: [Backport #21180]</title>
<updated>2025-03-16T09:52:56+00:00</updated>
<author>
<name>nagachika</name>
<email>nagachika@ruby-lang.org</email>
</author>
<published>2025-03-16T09:52:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=2b2ab1a67c236eb0c47e63e8adcf877b0d20a38c'/>
<id>2b2ab1a67c236eb0c47e63e8adcf877b0d20a38c</id>
<content type='text'>
	Push a real iseq in rb_vm_push_frame_fname()

	Previously, vm_make_env_each() (used during proc
	creation and for the debug inspector C API) picked up the
	non-GC-allocated iseq that rb_vm_push_frame_fname() creates,
	which led to a SEGV when the GC tried to mark the non GC object.

	Put a real iseq imemo instead. Speed should be about the same since
	the old code also did a imemo allocation and a malloc allocation.

	Real iseq allows ironing out the special-casing of dummy frames in
	rb_execution_context_mark() and rb_execution_context_update(). A check
	is added to RubyVM::ISeq#eval, though, to stop attempts to run dummy
	iseqs.

	[Bug #21180]

	Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	Push a real iseq in rb_vm_push_frame_fname()

	Previously, vm_make_env_each() (used during proc
	creation and for the debug inspector C API) picked up the
	non-GC-allocated iseq that rb_vm_push_frame_fname() creates,
	which led to a SEGV when the GC tried to mark the non GC object.

	Put a real iseq imemo instead. Speed should be about the same since
	the old code also did a imemo allocation and a malloc allocation.

	Real iseq allows ironing out the special-casing of dummy frames in
	rb_execution_context_mark() and rb_execution_context_update(). A check
	is added to RubyVM::ISeq#eval, though, to stop attempts to run dummy
	iseqs.

	[Bug #21180]

	Co-authored-by: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>merge revision(s) f65a6c090c229de1665af49f2e51fc1d6397ab72: [Backport #20921]</title>
<updated>2025-01-15T01:52:11+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-01-15T01:52:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=1b1c6e67588ef417847d36f4f4017bd18157a1d2'/>
<id>1b1c6e67588ef417847d36f4f4017bd18157a1d2</id>
<content type='text'>
	Fix use-after-free in constant cache

	[Bug #20921]

	When we create a cache entry for a constant, the following sequence of
	events could happen:

	- vm_track_constant_cache is called to insert a constant cache.
	- In vm_track_constant_cache, we first look up the ST table for the ID
	  of the constant. Assume the ST table exists because another iseq also
	  holds a cache entry for this ID.
	- We then insert into this ST table with the iseq_inline_constant_cache.
	- However, while inserting into this ST table, it allocates memory, which
	  could trigger a GC. Assume that it does trigger a GC.
	- The GC frees the one and only other iseq that holds a cache entry for
	  this ID.
	- In remove_from_constant_cache, it will appear that the ST table is now
	  empty because there are no more iseq with cache entries for this ID, so
	  we free the ST table.
	- We complete GC and continue our st_insert. However, this ST table has
	  been freed so we now have a use-after-free.

	This issue is very hard to reproduce, because it requires that the GC runs
	at a very specific time. However, we can make it show up by applying this
	patch which runs GC right before the st_insert to mimic the st_insert
	triggering a GC:

	    diff --git a/vm_insnhelper.c b/vm_insnhelper.c
	    index 3cb23f06f0..a93998136a 100644
	    --- a/vm_insnhelper.c
	    +++ b/vm_insnhelper.c
	    @@ -6338,6 +6338,10 @@ vm_track_constant_cache(ID id, void *ic)
	            rb_id_table_insert(const_cache, id, (VALUE)ics);
	        }

	    +    if (id == rb_intern("MyConstant")) rb_gc();
	    +
	        st_insert(ics, (st_data_t) ic, (st_data_t) Qtrue);
	    }

	And if we run this script:

	    Object.const_set("MyConstant", "Hello!")

	    my_proc = eval("-&gt; { MyConstant }")
	    my_proc.call

	    my_proc = eval("-&gt; { MyConstant }")
	    my_proc.call

	We can see that ASAN outputs a use-after-free error:

	    ==36540==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000049528 at pc 0x000102f3ceac bp 0x00016d607a70 sp 0x00016d607a68
	    READ of size 8 at 0x606000049528 thread T0
	        #0 0x102f3cea8 in do_hash st.c:321
	        #1 0x102f3ddd0 in rb_st_insert st.c:1132
	        #2 0x103140700 in vm_track_constant_cache vm_insnhelper.c:6345
	        #3 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #4 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #5 0x1030bc1e0 in vm_exec_core insns.def:263
	        #6 0x1030b55fc in rb_vm_exec vm.c:2585
	        #7 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #8 0x102a82588 in rb_ec_exec_node eval.c:281
	        #9 0x102a81fe0 in ruby_run_node eval.c:319
	        #10 0x1027f3db4 in rb_main main.c:43
	        #11 0x1027f3bd4 in main main.c:68
	        #12 0x183900270  (&lt;unknown module&gt;)

	    0x606000049528 is located 8 bytes inside of 56-byte region [0x606000049520,0x606000049558)
	    freed by thread T0 here:
	        #0 0x104174d40 in free+0x98 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54d40)
	        #1 0x102ada89c in rb_gc_impl_free default.c:8183
	        #2 0x102ada7dc in ruby_sized_xfree gc.c:4507
	        #3 0x102ac4d34 in ruby_xfree gc.c:4518
	        #4 0x102f3cb34 in rb_st_free_table st.c:663
	        #5 0x102bd52d8 in remove_from_constant_cache iseq.c:119
	        #6 0x102bbe2cc in iseq_clear_ic_references iseq.c:153
	        #7 0x102bbd2a0 in rb_iseq_free iseq.c:166
	        #8 0x102b32ed0 in rb_imemo_free imemo.c:564
	        #9 0x102ac4b44 in rb_gc_obj_free gc.c:1407
	        #10 0x102af4290 in gc_sweep_plane default.c:3546
	        #11 0x102af3bdc in gc_sweep_page default.c:3634
	        #12 0x102aeb140 in gc_sweep_step default.c:3906
	        #13 0x102aeadf0 in gc_sweep_rest default.c:3978
	        #14 0x102ae4714 in gc_sweep default.c:4155
	        #15 0x102af8474 in gc_start default.c:6484
	        #16 0x102afbe30 in garbage_collect default.c:6363
	        #17 0x102ad37f0 in rb_gc_impl_start default.c:6816
	        #18 0x102ad3634 in rb_gc gc.c:3624
	        #19 0x1031406ec in vm_track_constant_cache vm_insnhelper.c:6342
	        #20 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #21 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #22 0x1030bc1e0 in vm_exec_core insns.def:263
	        #23 0x1030b55fc in rb_vm_exec vm.c:2585
	        #24 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #25 0x102a82588 in rb_ec_exec_node eval.c:281
	        #26 0x102a81fe0 in ruby_run_node eval.c:319
	        #27 0x1027f3db4 in rb_main main.c:43
	        #28 0x1027f3bd4 in main main.c:68
	        #29 0x183900270  (&lt;unknown module&gt;)

	    previously allocated by thread T0 here:
	        #0 0x104174c04 in malloc+0x94 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54c04)
	        #1 0x102ada0ec in rb_gc_impl_malloc default.c:8198
	        #2 0x102acee44 in ruby_xmalloc gc.c:4438
	        #3 0x102f3c85c in rb_st_init_table_with_size st.c:571
	        #4 0x102f3c900 in rb_st_init_table st.c:600
	        #5 0x102f3c920 in rb_st_init_numtable st.c:608
	        #6 0x103140698 in vm_track_constant_cache vm_insnhelper.c:6337
	        #7 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #8 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #9 0x1030bc1e0 in vm_exec_core insns.def:263
	        #10 0x1030b55fc in rb_vm_exec vm.c:2585
	        #11 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #12 0x102a82588 in rb_ec_exec_node eval.c:281
	        #13 0x102a81fe0 in ruby_run_node eval.c:319
	        #14 0x1027f3db4 in rb_main main.c:43
	        #15 0x1027f3bd4 in main main.c:68
	        #16 0x183900270  (&lt;unknown module&gt;)

	This commit fixes this bug by adding a inserting_constant_cache_id field
	to the VM, which stores the ID that is currently being inserted and, in
	remove_from_constant_cache, we don't free the ST table for ID equal to
	this one.

	Co-Authored-By: Alan Wu &lt;alanwu@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	Fix use-after-free in constant cache

	[Bug #20921]

	When we create a cache entry for a constant, the following sequence of
	events could happen:

	- vm_track_constant_cache is called to insert a constant cache.
	- In vm_track_constant_cache, we first look up the ST table for the ID
	  of the constant. Assume the ST table exists because another iseq also
	  holds a cache entry for this ID.
	- We then insert into this ST table with the iseq_inline_constant_cache.
	- However, while inserting into this ST table, it allocates memory, which
	  could trigger a GC. Assume that it does trigger a GC.
	- The GC frees the one and only other iseq that holds a cache entry for
	  this ID.
	- In remove_from_constant_cache, it will appear that the ST table is now
	  empty because there are no more iseq with cache entries for this ID, so
	  we free the ST table.
	- We complete GC and continue our st_insert. However, this ST table has
	  been freed so we now have a use-after-free.

	This issue is very hard to reproduce, because it requires that the GC runs
	at a very specific time. However, we can make it show up by applying this
	patch which runs GC right before the st_insert to mimic the st_insert
	triggering a GC:

	    diff --git a/vm_insnhelper.c b/vm_insnhelper.c
	    index 3cb23f06f0..a93998136a 100644
	    --- a/vm_insnhelper.c
	    +++ b/vm_insnhelper.c
	    @@ -6338,6 +6338,10 @@ vm_track_constant_cache(ID id, void *ic)
	            rb_id_table_insert(const_cache, id, (VALUE)ics);
	        }

	    +    if (id == rb_intern("MyConstant")) rb_gc();
	    +
	        st_insert(ics, (st_data_t) ic, (st_data_t) Qtrue);
	    }

	And if we run this script:

	    Object.const_set("MyConstant", "Hello!")

	    my_proc = eval("-&gt; { MyConstant }")
	    my_proc.call

	    my_proc = eval("-&gt; { MyConstant }")
	    my_proc.call

	We can see that ASAN outputs a use-after-free error:

	    ==36540==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000049528 at pc 0x000102f3ceac bp 0x00016d607a70 sp 0x00016d607a68
	    READ of size 8 at 0x606000049528 thread T0
	        #0 0x102f3cea8 in do_hash st.c:321
	        #1 0x102f3ddd0 in rb_st_insert st.c:1132
	        #2 0x103140700 in vm_track_constant_cache vm_insnhelper.c:6345
	        #3 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #4 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #5 0x1030bc1e0 in vm_exec_core insns.def:263
	        #6 0x1030b55fc in rb_vm_exec vm.c:2585
	        #7 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #8 0x102a82588 in rb_ec_exec_node eval.c:281
	        #9 0x102a81fe0 in ruby_run_node eval.c:319
	        #10 0x1027f3db4 in rb_main main.c:43
	        #11 0x1027f3bd4 in main main.c:68
	        #12 0x183900270  (&lt;unknown module&gt;)

	    0x606000049528 is located 8 bytes inside of 56-byte region [0x606000049520,0x606000049558)
	    freed by thread T0 here:
	        #0 0x104174d40 in free+0x98 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54d40)
	        #1 0x102ada89c in rb_gc_impl_free default.c:8183
	        #2 0x102ada7dc in ruby_sized_xfree gc.c:4507
	        #3 0x102ac4d34 in ruby_xfree gc.c:4518
	        #4 0x102f3cb34 in rb_st_free_table st.c:663
	        #5 0x102bd52d8 in remove_from_constant_cache iseq.c:119
	        #6 0x102bbe2cc in iseq_clear_ic_references iseq.c:153
	        #7 0x102bbd2a0 in rb_iseq_free iseq.c:166
	        #8 0x102b32ed0 in rb_imemo_free imemo.c:564
	        #9 0x102ac4b44 in rb_gc_obj_free gc.c:1407
	        #10 0x102af4290 in gc_sweep_plane default.c:3546
	        #11 0x102af3bdc in gc_sweep_page default.c:3634
	        #12 0x102aeb140 in gc_sweep_step default.c:3906
	        #13 0x102aeadf0 in gc_sweep_rest default.c:3978
	        #14 0x102ae4714 in gc_sweep default.c:4155
	        #15 0x102af8474 in gc_start default.c:6484
	        #16 0x102afbe30 in garbage_collect default.c:6363
	        #17 0x102ad37f0 in rb_gc_impl_start default.c:6816
	        #18 0x102ad3634 in rb_gc gc.c:3624
	        #19 0x1031406ec in vm_track_constant_cache vm_insnhelper.c:6342
	        #20 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #21 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #22 0x1030bc1e0 in vm_exec_core insns.def:263
	        #23 0x1030b55fc in rb_vm_exec vm.c:2585
	        #24 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #25 0x102a82588 in rb_ec_exec_node eval.c:281
	        #26 0x102a81fe0 in ruby_run_node eval.c:319
	        #27 0x1027f3db4 in rb_main main.c:43
	        #28 0x1027f3bd4 in main main.c:68
	        #29 0x183900270  (&lt;unknown module&gt;)

	    previously allocated by thread T0 here:
	        #0 0x104174c04 in malloc+0x94 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x54c04)
	        #1 0x102ada0ec in rb_gc_impl_malloc default.c:8198
	        #2 0x102acee44 in ruby_xmalloc gc.c:4438
	        #3 0x102f3c85c in rb_st_init_table_with_size st.c:571
	        #4 0x102f3c900 in rb_st_init_table st.c:600
	        #5 0x102f3c920 in rb_st_init_numtable st.c:608
	        #6 0x103140698 in vm_track_constant_cache vm_insnhelper.c:6337
	        #7 0x1030b91d8 in vm_ic_track_const_chain vm_insnhelper.c:6356
	        #8 0x1030b8cf8 in rb_vm_opt_getconstant_path vm_insnhelper.c:6424
	        #9 0x1030bc1e0 in vm_exec_core insns.def:263
	        #10 0x1030b55fc in rb_vm_exec vm.c:2585
	        #11 0x1030fe0ac in rb_iseq_eval_main vm.c:2851
	        #12 0x102a82588 in rb_ec_exec_node eval.c:281
	        #13 0x102a81fe0 in ruby_run_node eval.c:319
	        #14 0x1027f3db4 in rb_main main.c:43
	        #15 0x1027f3bd4 in main main.c:68
	        #16 0x183900270  (&lt;unknown module&gt;)

	This commit fixes this bug by adding a inserting_constant_cache_id field
	to the VM, which stores the ID that is currently being inserted and, in
	remove_from_constant_cache, we don't free the ST table for ID equal to
	this one.

	Co-Authored-By: Alan Wu &lt;alanwu@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>[Backport #20633] Fix the condition for `atomic_signal_fence` (#11166)</title>
<updated>2024-07-15T16:08:16+00:00</updated>
<author>
<name>Ivo Anjo</name>
<email>ivo.anjo@datadoghq.com</email>
</author>
<published>2024-07-15T16:08:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=425e468d25a70740cef3ed676e9b82f7902e077a'/>
<id>425e468d25a70740cef3ed676e9b82f7902e077a</id>
<content type='text'>
[Bug #20633] Fix the condition for `atomic_signal_fence`

`AC_CHECK_DECLS` defines `HAVE_DECL_SYMBOL` to 1 if declared, 0
otherwise, not undefined.

Co-authored-by: kimuraw (Wataru Kimura) &lt;kimuraw@i.nifty.jp&gt;</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[Bug #20633] Fix the condition for `atomic_signal_fence`

`AC_CHECK_DECLS` defines `HAVE_DECL_SYMBOL` to 1 if declared, 0
otherwise, not undefined.

Co-authored-by: kimuraw (Wataru Kimura) &lt;kimuraw@i.nifty.jp&gt;</pre>
</div>
</content>
</entry>
<entry>
<title>[Backport #11036] Add explicit compiler fence when pushing frames to ensure safe profiling (#11090)</title>
<updated>2024-07-03T16:56:00+00:00</updated>
<author>
<name>Ivo Anjo</name>
<email>ivo.anjo@datadoghq.com</email>
</author>
<published>2024-07-03T16:56:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=b2be36ef3349ebdab5423ea3337c03bcc3319b60'/>
<id>b2be36ef3349ebdab5423ea3337c03bcc3319b60</id>
<content type='text'>
**What does this PR do?**

This PR tweaks the `vm_push_frame` function to add an explicit compiler
fence (`atomic_signal_fence`) to ensure profilers that use signals
to interrupt applications (stackprof, vernier, pf2, Datadog profiler)
can safely sample from the signal handler.

This is a backport of #11036 to Ruby 3.3 .

**Motivation:**

The `vm_push_frame` was specifically tweaked in
https://github.com/ruby/ruby/pull/3296 to initialize the a frame
before updating the `cfp` pointer.

But since there's nothing stopping the compiler from reordering
the initialization of a frame (`*cfp =`) with the update of the cfp
pointer (`ec-&gt;cfp = cfp`) we've been hesitant to rely on this on
the Datadog profiler.

In practice, after some experimentation + talking to folks, this
reordering does not seem to happen.

But since modern compilers have a way for us to exactly tell them
not to do the reordering (`atomic_signal_fence`), this seems even
better.

I've actually extracted `vm_push_frame` into the "Compiler Explorer"
website, which you can use to see the assembly output of this function
across many compilers and architectures: https://godbolt.org/z/3oxd1446K

On that link you can observe two things across many compilers:
1. The compilers are not reordering the writes
2. The barrier does not change the generated assembly output
   (== has no cost in practice)

**Additional Notes:**

The checks added in `configure.ac` define two new macros:
* `HAVE_STDATOMIC_H`
* `HAVE_DECL_ATOMIC_SIGNAL_FENCE`

Since Ruby generates an arch-specific `config.h` header with
these macros upon installation, this can be used by profilers
and other libraries to test if Ruby was compiled with the fence enabled.

**How to test the change?**

As I mentioned above, you can check https://godbolt.org/z/3oxd1446K
to confirm the compiled output of `vm_push_frame` does not change
in most compilers (at least all that I've checked on that site).</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
**What does this PR do?**

This PR tweaks the `vm_push_frame` function to add an explicit compiler
fence (`atomic_signal_fence`) to ensure profilers that use signals
to interrupt applications (stackprof, vernier, pf2, Datadog profiler)
can safely sample from the signal handler.

This is a backport of #11036 to Ruby 3.3 .

**Motivation:**

The `vm_push_frame` was specifically tweaked in
https://github.com/ruby/ruby/pull/3296 to initialize the a frame
before updating the `cfp` pointer.

But since there's nothing stopping the compiler from reordering
the initialization of a frame (`*cfp =`) with the update of the cfp
pointer (`ec-&gt;cfp = cfp`) we've been hesitant to rely on this on
the Datadog profiler.

In practice, after some experimentation + talking to folks, this
reordering does not seem to happen.

But since modern compilers have a way for us to exactly tell them
not to do the reordering (`atomic_signal_fence`), this seems even
better.

I've actually extracted `vm_push_frame` into the "Compiler Explorer"
website, which you can use to see the assembly output of this function
across many compilers and architectures: https://godbolt.org/z/3oxd1446K

On that link you can observe two things across many compilers:
1. The compilers are not reordering the writes
2. The barrier does not change the generated assembly output
   (== has no cost in practice)

**Additional Notes:**

The checks added in `configure.ac` define two new macros:
* `HAVE_STDATOMIC_H`
* `HAVE_DECL_ATOMIC_SIGNAL_FENCE`

Since Ruby generates an arch-specific `config.h` header with
these macros upon installation, this can be used by profilers
and other libraries to test if Ruby was compiled with the fence enabled.

**How to test the change?**

As I mentioned above, you can check https://godbolt.org/z/3oxd1446K
to confirm the compiled output of `vm_push_frame` does not change
in most compilers (at least all that I've checked on that site).</pre>
</div>
</content>
</entry>
<entry>
<title>Support tracing of struct member accessor methods</title>
<updated>2023-12-07T18:29:33+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2023-10-27T00:03:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=3081c83169c55ef7eead6222e49248e09232c22c'/>
<id>3081c83169c55ef7eead6222e49248e09232c22c</id>
<content type='text'>
This follows the same approach used for attr_reader/attr_writer in
2d98593bf54a37397c6e4886ccc7e3654c2eaf85, skipping the checking for
tracing after the first call using the call cache, and clearing the
call cache when tracing is turned on/off.

Fixes [Bug #18886]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This follows the same approach used for attr_reader/attr_writer in
2d98593bf54a37397c6e4886ccc7e3654c2eaf85, skipping the checking for
tracing after the first call using the call cache, and clearing the
call cache when tracing is turned on/off.

Fixes [Bug #18886]
</pre>
</div>
</content>
</entry>
<entry>
<title>Support eval "return" at toplevel</title>
<updated>2023-12-07T17:30:36+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2023-10-25T19:49:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=3a88de3ca73052809f5c0bfb4ef8cd435b29ae5f'/>
<id>3a88de3ca73052809f5c0bfb4ef8cd435b29ae5f</id>
<content type='text'>
Since Ruby 2.4, `return` is supported at toplevel.  This makes `eval "return"`
also supported at toplevel.

This mostly uses the same tests as direct `return` at toplevel, with a couple
differences:

`END {return if false}` is a SyntaxError, but `END {eval "return" if false}`
is not an error since the eval is never executed. `END {return}` is a
SyntaxError, but `END {eval "return"}` is a LocalJumpError.

The following is a SyntaxError:

```ruby
class X
nil&amp;defined?0--begin e=no_method_error(); return; 0;end
end
```

However, the following is not, because the eval is never executed:

```ruby
class X
nil&amp;defined?0--begin e=no_method_error(); eval "return"; 0;end
end
```

Fixes [Bug #19779]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Since Ruby 2.4, `return` is supported at toplevel.  This makes `eval "return"`
also supported at toplevel.

This mostly uses the same tests as direct `return` at toplevel, with a couple
differences:

`END {return if false}` is a SyntaxError, but `END {eval "return" if false}`
is not an error since the eval is never executed. `END {return}` is a
SyntaxError, but `END {eval "return"}` is a LocalJumpError.

The following is a SyntaxError:

```ruby
class X
nil&amp;defined?0--begin e=no_method_error(); return; 0;end
end
```

However, the following is not, because the eval is never executed:

```ruby
class X
nil&amp;defined?0--begin e=no_method_error(); eval "return"; 0;end
end
```

Fixes [Bug #19779]
</pre>
</div>
</content>
</entry>
<entry>
<title>Make expandarray compaction safe</title>
<updated>2023-12-01T22:13:56+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2023-11-30T15:51:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=0aed37b973c66e9ff071a1f46944cb0c6151d2dc'/>
<id>0aed37b973c66e9ff071a1f46944cb0c6151d2dc</id>
<content type='text'>
The expandarray instruction can allocate an array, which can trigger
a GC compaction. However, since it does not increment the sp until the
end of the instruction, the objects it places on the stack are not
marked or reference updated by the GC, which can cause the objects to
move which leaves broken or incorrect objects on the stack.

This commit changes the instruction to be handles_sp so the sp is
incremented inside of the instruction right after the object is written
on the stack.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The expandarray instruction can allocate an array, which can trigger
a GC compaction. However, since it does not increment the sp until the
end of the instruction, the objects it places on the stack are not
marked or reference updated by the GC, which can cause the objects to
move which leaves broken or incorrect objects on the stack.

This commit changes the instruction to be handles_sp so the sp is
incremented inside of the instruction right after the object is written
on the stack.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix cache incoherency for ME resolved through VM_METHOD_TYPE_REFINED</title>
<updated>2023-11-28T18:03:04+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2023-11-28T00:19:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=cd4207869ff831c41db3ec873b175369ffca080a'/>
<id>cd4207869ff831c41db3ec873b175369ffca080a</id>
<content type='text'>
Previously, we didn't invalidate the method entry wrapped by
VM_METHOD_TYPE_REFINED method entries which could cause calls to
land in the wrong method like it did in the included test.

Do the invalidation, and adjust rb_method_entry_clone() to accommodate
this new invalidation vector.

Fix: cfd7729ce7a31c8b6ec5dd0e99c67b2932de4732
See-also: e201b81f79828c30500947fe8c8ea3c515e3d112
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, we didn't invalidate the method entry wrapped by
VM_METHOD_TYPE_REFINED method entries which could cause calls to
land in the wrong method like it did in the included test.

Do the invalidation, and adjust rb_method_entry_clone() to accommodate
this new invalidation vector.

Fix: cfd7729ce7a31c8b6ec5dd0e99c67b2932de4732
See-also: e201b81f79828c30500947fe8c8ea3c515e3d112
</pre>
</div>
</content>
</entry>
<entry>
<title>vm_setivar_slowpath: only optimize T_OBJECT</title>
<updated>2023-11-23T10:19:12+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>byroot@ruby-lang.org</email>
</author>
<published>2023-11-23T08:44:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=f1c32c0ee08e924e202f529ee8438d2de4f2702a'/>
<id>f1c32c0ee08e924e202f529ee8438d2de4f2702a</id>
<content type='text'>
We've seen occasional CI failures on i686 in this codepath:

```
[BUG] vm_setivar_slowpath: didn't find ivar @verify_depth in shape
```

Generic ivars are very complex to get right, but also quite rare.
I don't see a good reason to take the risk to give them an optimized
path here, when the much more common T_CLASS/T_MODULE don't have one.

Having an optimization here means duplicating the fairly brittle
logic, which is a recipe for bugs, and I don't think it's worth
it in such case.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We've seen occasional CI failures on i686 in this codepath:

```
[BUG] vm_setivar_slowpath: didn't find ivar @verify_depth in shape
```

Generic ivars are very complex to get right, but also quite rare.
I don't see a good reason to take the risk to give them an optimized
path here, when the much more common T_CLASS/T_MODULE don't have one.

Having an optimization here means duplicating the fairly brittle
logic, which is a recipe for bugs, and I don't think it's worth
it in such case.
</pre>
</div>
</content>
</entry>
<entry>
<title>vm_setivar_slowpath: improve bug error message</title>
<updated>2023-11-15T10:19:03+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>byroot@ruby-lang.org</email>
</author>
<published>2023-11-15T09:40:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=960a031a06e4401589cfa29673e27b0bf2895f6d'/>
<id>960a031a06e4401589cfa29673e27b0bf2895f6d</id>
<content type='text'>
We're occasionally hitting this bug on CI, it would be useful
to see if the id is consistent.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We're occasionally hitting this bug on CI, it would be useful
to see if the id is consistent.
</pre>
</div>
</content>
</entry>
</feed>
