<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/vm_args.c, branch v3_4_9</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Fix allocationless anonymous splat keyword argument check</title>
<updated>2025-12-12T16:56:50+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2025-12-03T01:34:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=88f1d98676d435a79e2086ed8054b459f1b4bd2a'/>
<id>88f1d98676d435a79e2086ed8054b459f1b4bd2a</id>
<content type='text'>
Previously, if an argument splat and keywords are provided by
the caller, it did not check whether the method/proc accepted
keywords before avoiding the allocation. This is incorrect,
because if the method/proc does not accept keywords, the
keywords passed by the caller are added as a positional
argument, so there must be an allocation to avoid mutating
the positional splat argument.

Add a check that if the caller passes keywords, the
method/proc must accept keywords in order to optimize.
If the caller passes a keyword splat, either the
method/proc must accept keywords, or the keyword splat must
be empty in order to optimize.

If keywords are explicitly disallowed via `**nil`, the
optimization should be skipped, because the array is mutated
before the ArgumentError exception is raised.

In addition to a test for the correct behavior, add an
allocation test for a method that accepts an anonymous splat
without keywords.

Fixes [Bug #21757]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, if an argument splat and keywords are provided by
the caller, it did not check whether the method/proc accepted
keywords before avoiding the allocation. This is incorrect,
because if the method/proc does not accept keywords, the
keywords passed by the caller are added as a positional
argument, so there must be an allocation to avoid mutating
the positional splat argument.

Add a check that if the caller passes keywords, the
method/proc must accept keywords in order to optimize.
If the caller passes a keyword splat, either the
method/proc must accept keywords, or the keyword splat must
be empty in order to optimize.

If keywords are explicitly disallowed via `**nil`, the
optimization should be skipped, because the array is mutated
before the ArgumentError exception is raised.

In addition to a test for the correct behavior, add an
allocation test for a method that accepts an anonymous splat
without keywords.

Fixes [Bug #21757]
</pre>
</div>
</content>
</entry>
<entry>
<title>FCALL shouldn't be forwarded from caller</title>
<updated>2025-03-27T22:23:56+00:00</updated>
<author>
<name>Aaron Patterson</name>
<email>tenderlove@ruby-lang.org</email>
</author>
<published>2025-03-21T16:19:42+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=00c6e537ce46e4482c77fa8676a4a1e44cc6f623'/>
<id>00c6e537ce46e4482c77fa8676a4a1e44cc6f623</id>
<content type='text'>
When we forward an FCALL (a method call with an implicit self), we
shouldn't forward the FCALL flag because it ignores method visibility
checks.  This patch removes the FCALL flag from callers.

[Bug #21196]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When we forward an FCALL (a method call with an implicit self), we
shouldn't forward the FCALL flag because it ignores method visibility
checks.  This patch removes the FCALL flag from callers.

[Bug #21196]
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove meaningless comma expression</title>
<updated>2024-12-04T04:59:54+00:00</updated>
<author>
<name>Yusuke Endoh</name>
<email>mame@ruby-lang.org</email>
</author>
<published>2024-12-04T04:23:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c0454abdee127fcf5c6952ae1cebed57401d9044'/>
<id>c0454abdee127fcf5c6952ae1cebed57401d9044</id>
<content type='text'>
Coverity Scan alerts `for(i, j=0;...)` as a misuse of comma expression.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Coverity Scan alerts `for(i, j=0;...)` as a misuse of comma expression.
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove "simple" flag from forwarded ICs</title>
<updated>2024-10-16T02:06:07+00:00</updated>
<author>
<name>Aaron Patterson</name>
<email>tenderlove@ruby-lang.org</email>
</author>
<published>2024-10-15T23:57:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=a0ecdbfbfe57a57ab33bdb5e1de4d5dfa8407dbb'/>
<id>a0ecdbfbfe57a57ab33bdb5e1de4d5dfa8407dbb</id>
<content type='text'>
I don't think we should ever consider forwarded IC's to be "simple".
Previously, the "simple" flag would be copied to the derived IC and this
happened to cause struct set / get iseqs to write an invalid CC
fastpath:

  https://github.com/tenderlove/ruby/blob/f45eb3dcb9c7d849064cb802953f37e1cf9f3996/vm_insnhelper.c#L4726-L4729

[Bug #20799]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I don't think we should ever consider forwarded IC's to be "simple".
Previously, the "simple" flag would be copied to the derived IC and this
happened to cause struct set / get iseqs to write an invalid CC
fastpath:

  https://github.com/tenderlove/ruby/blob/f45eb3dcb9c7d849064cb802953f37e1cf9f3996/vm_insnhelper.c#L4726-L4729

[Bug #20799]
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid hash allocation for certain proc calls</title>
<updated>2024-08-20T02:00:37+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-08-20T02:00:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=ea7ceff82cec98d0c419e9807dcb33dcc08b56fa'/>
<id>ea7ceff82cec98d0c419e9807dcb33dcc08b56fa</id>
<content type='text'>
Previously, proc calls such as:

```ruby
proc{|| }.(**empty_hash)
proc{|b: 1| }.(**r2k_array_with_empty_hash)
```

both allocated hashes unnecessarily, due to two separate code paths.

The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
and is simple to fix by not duping an empty keyword hash that will be
dropped.

The second case is more involved, in setup_parameters_complex, but is
fixed the exact same way as when the ruby2_keywords hash is not empty,
by flattening the rest array to the VM stack, ignoring the last
element (the empty keyword splat).  Add a flatten_rest_array static
function to handle this case.

Update test_allocation.rb to automatically convert the method call
allocation tests to proc allocation tests, at least for the calls
that can be converted.  With the code changes, all proc call
allocation tests pass, showing that proc calls and method calls
now allocate the same number of objects.

I've audited the allocation tests, and I believe that all of the low
hanging fruit has been collected.  All remaining allocations are
either caller side:

* Positional splat + post argument
* Multiple positional splats
* Literal keywords + keyword splat
* Multiple keyword splats

Or callee side:

* Positional splat parameter
* Keyword splat parameter
* Keyword to positional argument conversion for methods that don't accept keywords
* ruby2_keywords method called with keywords

Reapplies abc04e898b627ab37fa9dd5e330f239768778d8b, which was reverted at
d56470a27c5a8a2e7aee7a76cea445c2d29c0c59, with the addition of a bug fix and
test.

Fixes [Bug #20679]</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, proc calls such as:

```ruby
proc{|| }.(**empty_hash)
proc{|b: 1| }.(**r2k_array_with_empty_hash)
```

both allocated hashes unnecessarily, due to two separate code paths.

The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
and is simple to fix by not duping an empty keyword hash that will be
dropped.

The second case is more involved, in setup_parameters_complex, but is
fixed the exact same way as when the ruby2_keywords hash is not empty,
by flattening the rest array to the VM stack, ignoring the last
element (the empty keyword splat).  Add a flatten_rest_array static
function to handle this case.

Update test_allocation.rb to automatically convert the method call
allocation tests to proc allocation tests, at least for the calls
that can be converted.  With the code changes, all proc call
allocation tests pass, showing that proc calls and method calls
now allocate the same number of objects.

I've audited the allocation tests, and I believe that all of the low
hanging fruit has been collected.  All remaining allocations are
either caller side:

* Positional splat + post argument
* Multiple positional splats
* Literal keywords + keyword splat
* Multiple keyword splats

Or callee side:

* Positional splat parameter
* Keyword splat parameter
* Keyword to positional argument conversion for methods that don't accept keywords
* ruby2_keywords method called with keywords

Reapplies abc04e898b627ab37fa9dd5e330f239768778d8b, which was reverted at
d56470a27c5a8a2e7aee7a76cea445c2d29c0c59, with the addition of a bug fix and
test.

Fixes [Bug #20679]</pre>
</div>
</content>
</entry>
<entry>
<title>Revert "Avoid hash allocation for certain proc calls"</title>
<updated>2024-08-17T00:59:05+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-08-16T23:47:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d56470a27c5a8a2e7aee7a76cea445c2d29c0c59'/>
<id>d56470a27c5a8a2e7aee7a76cea445c2d29c0c59</id>
<content type='text'>
This reverts commit abc04e898b627ab37fa9dd5e330f239768778d8b.

This caused problems in a Rails test.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This reverts commit abc04e898b627ab37fa9dd5e330f239768778d8b.

This caused problems in a Rails test.
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid hash allocation for certain proc calls</title>
<updated>2024-08-15T20:00:09+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-07-26T22:18:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=abc04e898b627ab37fa9dd5e330f239768778d8b'/>
<id>abc04e898b627ab37fa9dd5e330f239768778d8b</id>
<content type='text'>
Previous, proc calls such as:

```ruby
proc{|| }.(**empty_hash)
proc{|b: 1| }.(**r2k_array_with_empty_hash)
```

both allocated hashes unnecessarily, due to two separate code paths.

The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
and is simple to fix by not duping an empty keyword hash that will be
dropped.

The second case is more involved, in setup_parameters_complex, but is
fixed the exact same way as when the ruby2_keywords hash is not empty,
by flattening the rest array to the VM stack, ignoring the last
element (the empty keyword splat).  Add a flatten_rest_array static
function to handle this case.

Update test_allocation.rb to automatically convert the method call
allocation tests to proc allocation tests, at least for the calls
that can be converted.  With the code changes, all proc call
allocation tests pass, showing that proc calls and method calls
now allocate the same number of objects.

I've audited the allocation tests, and I believe that all of the low
hanging fruit has been collected.  All remaining allocations are
either caller side:

* Positional splat + post argument
* Multiple positional splats
* Literal keywords + keyword splat
* Multiple keyword splats

Or callee side:

* Positional splat parameter
* Keyword splat parameter
* Keyword to positional argument conversion for methods that don't accept keywords
* ruby2_keywords method called with keywords
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previous, proc calls such as:

```ruby
proc{|| }.(**empty_hash)
proc{|b: 1| }.(**r2k_array_with_empty_hash)
```

both allocated hashes unnecessarily, due to two separate code paths.

The first call goes through CALLER_SETUP_ARG/vm_caller_setup_keyword_hash,
and is simple to fix by not duping an empty keyword hash that will be
dropped.

The second case is more involved, in setup_parameters_complex, but is
fixed the exact same way as when the ruby2_keywords hash is not empty,
by flattening the rest array to the VM stack, ignoring the last
element (the empty keyword splat).  Add a flatten_rest_array static
function to handle this case.

Update test_allocation.rb to automatically convert the method call
allocation tests to proc allocation tests, at least for the calls
that can be converted.  With the code changes, all proc call
allocation tests pass, showing that proc calls and method calls
now allocate the same number of objects.

I've audited the allocation tests, and I believe that all of the low
hanging fruit has been collected.  All remaining allocations are
either caller side:

* Positional splat + post argument
* Multiple positional splats
* Literal keywords + keyword splat
* Multiple keyword splats

Or callee side:

* Positional splat parameter
* Keyword splat parameter
* Keyword to positional argument conversion for methods that don't accept keywords
* ruby2_keywords method called with keywords
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid array allocation for f(*r2k_ary) when def f(x)</title>
<updated>2024-07-19T05:17:21+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-07-12T22:33:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=6428ce80f0ef85324a4d0a72ffa4c6fa2db37cdd'/>
<id>6428ce80f0ef85324a4d0a72ffa4c6fa2db37cdd</id>
<content type='text'>
When calling a method that does not accept a positional splat
parameter with a splatted array with a ruby2_keywords flagged hash,
there is no need to duplicate the splatted array.  Previously,
Ruby would duplicate the splatted array and potentially modify
it before flattening it to the VM stack

Use a similar approach as the f(*ary, **hash) optimization,
flattening the splatted array to the VM stack without modifying
it, and make any modifications needed to the VM stack.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When calling a method that does not accept a positional splat
parameter with a splatted array with a ruby2_keywords flagged hash,
there is no need to duplicate the splatted array.  Previously,
Ruby would duplicate the splatted array and potentially modify
it before flattening it to the VM stack

Use a similar approach as the f(*ary, **hash) optimization,
flattening the splatted array to the VM stack without modifying
it, and make any modifications needed to the VM stack.
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid hash allocation for f(*r2k_ary) when def f(kw: 1)</title>
<updated>2024-07-19T05:17:21+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-07-12T21:19:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=1cc5a64dd87a6a474ec8387083d41a3c6c1c3ca5'/>
<id>1cc5a64dd87a6a474ec8387083d41a3c6c1c3ca5</id>
<content type='text'>
When calling a method that accepts keywords but not a keyword
splat with a splatted array with a ruby2_keywords flagged hash,
there is no need to duplicate the ruby2_keywords flagged hash,
since it will be accessed to get the keyword values, but it will
not be modified.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When calling a method that accepts keywords but not a keyword
splat with a splatted array with a ruby2_keywords flagged hash,
there is no need to duplicate the ruby2_keywords flagged hash,
since it will be accessed to get the keyword values, but it will
not be modified.
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid array allocation for f(*empty_ary, **hash) when def f(x)</title>
<updated>2024-07-19T05:17:21+00:00</updated>
<author>
<name>Jeremy Evans</name>
<email>code@jeremyevans.net</email>
</author>
<published>2024-07-12T20:28:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=94e7d2664388039fc8c2f6a063017cae22193fa3'/>
<id>94e7d2664388039fc8c2f6a063017cae22193fa3</id>
<content type='text'>
This avoids an array allocation when calling a method that does
not accept a positional splat or keywords with both a positional
splat and keywords.  Previously, Ruby would dup the positional
splat to append the keyword splat to it. Then it would flatten
the dupped positional splat array to the VM stack.

This flattens the given positional splat to the VM stack, then
adds the keyword splat hash after the last positional splat
element on the VM stack, avoiding the need to modify
the positional splat array.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This avoids an array allocation when calling a method that does
not accept a positional splat or keywords with both a positional
splat and keywords.  Previously, Ruby would dup the positional
splat to append the keyword splat to it. Then it would flatten
the dupped positional splat array to the VM stack.

This flattens the given positional splat to the VM stack, then
adds the keyword splat hash after the last positional splat
element on the VM stack, avoiding the need to modify
the positional splat array.
</pre>
</div>
</content>
</entry>
</feed>
