<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/bootstraptest/test_yjit.rb, 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>merge revision(s) 9168cad4d63a5d281d443bde4edea6be213b0b25: [Backport #21266]</title>
<updated>2025-12-16T23:53:40+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-12-16T23:53:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d8f087b581735ec250b8671c3574fa4d5b16ae54'/>
<id>d8f087b581735ec250b8671c3574fa4d5b16ae54</id>
<content type='text'>
	[PATCH] YJIT: Bail out if proc would be stored above stack top

	Fixes [Bug #21266].
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	[PATCH] YJIT: Bail out if proc would be stored above stack top

	Fixes [Bug #21266].
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Fix panic from overly loose filtering in identity method inlining</title>
<updated>2025-12-12T23:43:41+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2025-12-12T23:00:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=f19e9c6699150d56853ba1a33f6149d7588c8478'/>
<id>f19e9c6699150d56853ba1a33f6149d7588c8478</id>
<content type='text'>
Credits to @rwstauner for noticing this issue in GH-15533.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Credits to @rwstauner for noticing this issue in GH-15533.
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Add missing local variable type update for fallback setlocal blocks</title>
<updated>2025-12-12T23:43:41+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2025-12-12T18:42:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=628a94104768b294ae8068c7bb39ab9e495fdd94'/>
<id>628a94104768b294ae8068c7bb39ab9e495fdd94</id>
<content type='text'>
Previously, the chain_depth&gt;0 version of setlocal blocks did not
update the type of the local variable in the context. This can leave
the context with stale type information and trigger or lead to miscompilation.

To trigger the issue, YJIT needs to see the same ISEQ before and after
environment escape and have tracked type info before the escape. To
trigger in ISEQs that do not send with a block, it probably requires
Kernel#binding or the use of include/ruby/debug.h APIs.

[Backport #21772]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, the chain_depth&gt;0 version of setlocal blocks did not
update the type of the local variable in the context. This can leave
the context with stale type information and trigger or lead to miscompilation.

To trigger the issue, YJIT needs to see the same ISEQ before and after
environment escape and have tracked type info before the escape. To
trigger in ISEQs that do not send with a block, it probably requires
Kernel#binding or the use of include/ruby/debug.h APIs.

[Backport #21772]
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Abort expandarray optimization if method_missing is defined</title>
<updated>2025-12-01T17:45:35+00:00</updated>
<author>
<name>Randy Stauner</name>
<email>randy@r4s6.net</email>
</author>
<published>2025-11-26T02:29:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=28b2e2ede97b569c2f6121e7808975fbd5c6f298'/>
<id>28b2e2ede97b569c2f6121e7808975fbd5c6f298</id>
<content type='text'>
Fixes: [Bug #21707]
[AW: rewrote comments]
Co-authored-by: Alan Wu &lt;alanwu@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fixes: [Bug #21707]
[AW: rewrote comments]
Co-authored-by: Alan Wu &lt;alanwu@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Fix stack handling in rb_str_dup</title>
<updated>2025-11-14T18:07:34+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-11-13T20:01:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=0b559eab0447905a784092824e5ea0999018cd01'/>
<id>0b559eab0447905a784092824e5ea0999018cd01</id>
<content type='text'>
Previously because we did a stack_push before ccall, in some cases we
could end up pushing an uninitialized value to the VM stack when
spilling regs as part of the ccall.

Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously because we did a stack_push before ccall, in some cases we
could end up pushing an uninitialized value to the VM stack when
spilling regs as part of the ccall.

Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Fix `defined?(yield)` and `block_given?` at top level</title>
<updated>2025-10-22T20:53:20+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2025-08-13T16:39:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=3afa38d0ee34a453d7c53d4512a8f14d25d23f57'/>
<id>3afa38d0ee34a453d7c53d4512a8f14d25d23f57</id>
<content type='text'>
Previously, YJIT returned truthy for the block given query at the top
level. That's incorrect because the top level script never receives a
block, and `yield` is a syntax error there.

Inside methods, the number of hops to get from `iseq` to
`iseq-&gt;body-&gt;local_iseq` is the same as the number of
`VM_ENV_PREV_EP(ep)` hops to get to an environment with
`VM_ENV_FLAG_LOCAL`. YJIT and the interpreter both rely on this as can
be seen in get_lvar_level(). However, this identity does not hold for
the top level frame because of `vm_set_eval_stack()`, which sets up
`TOPLEVEL_BINDING`.

Since only methods can take a block that `yield` goes to, have ISEQs
that are the child of a non-method ISEQ return falsy for the block given
query. This fixes the issue for the top level script and is an
optimization for non-method contexts such as inside `ISEQ_TYPE_CLASS`.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, YJIT returned truthy for the block given query at the top
level. That's incorrect because the top level script never receives a
block, and `yield` is a syntax error there.

Inside methods, the number of hops to get from `iseq` to
`iseq-&gt;body-&gt;local_iseq` is the same as the number of
`VM_ENV_PREV_EP(ep)` hops to get to an environment with
`VM_ENV_FLAG_LOCAL`. YJIT and the interpreter both rely on this as can
be seen in get_lvar_level(). However, this identity does not hold for
the top level frame because of `vm_set_eval_stack()`, which sets up
`TOPLEVEL_BINDING`.

Since only methods can take a block that `yield` goes to, have ISEQs
that are the child of a non-method ISEQ return falsy for the block given
query. This fixes the issue for the top level script and is an
optimization for non-method contexts such as inside `ISEQ_TYPE_CLASS`.
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Fix potential infinite loop when OOM (GH-13186)</title>
<updated>2025-04-28T16:23:33+00:00</updated>
<author>
<name>Rian McGuire</name>
<email>rian@rian.id.au</email>
</author>
<published>2025-04-28T12:50:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=50b1759be00713535c41f5650feb3967c533450a'/>
<id>50b1759be00713535c41f5650feb3967c533450a</id>
<content type='text'>
Avoid generating an infinite loop in the case where:
1. Block `first` is adjacent to block `second`, and the branch from `first` to
   `second` is a fallthrough, and
2. Block `second` immediately exits to the interpreter, and
3. Block `second` is invalidated and YJIT is OOM

While pondering how to fix this, I think I've stumbled on another related edge case:
1. Block `incoming_one` and `incoming_two` both branch to block `second`. Block
   `incoming_one` has a fallthrough
2. Block `second` immediately exits to the interpreter (so it starts with its exit)
3. When Block `second` is invalidated, the incoming fallthrough branch from
   `incoming_one` might be rewritten first, which overwrites the start of block
   `second` with a jump to a new branch stub.
4. YJIT runs of out memory
5. The incoming branch from `incoming_two` is then rewritten, but because we're
   OOM we can't generate a new stub, so we use `second`'s exit as the branch
   target. However `second`'s exit was already overwritten with a jump to the
   branch stub for `incoming_one`, so `incoming_two` will end up jumping to
   `incoming_one`'s branch stub.

Backport [Bug #21257]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Avoid generating an infinite loop in the case where:
1. Block `first` is adjacent to block `second`, and the branch from `first` to
   `second` is a fallthrough, and
2. Block `second` immediately exits to the interpreter, and
3. Block `second` is invalidated and YJIT is OOM

While pondering how to fix this, I think I've stumbled on another related edge case:
1. Block `incoming_one` and `incoming_two` both branch to block `second`. Block
   `incoming_one` has a fallthrough
2. Block `second` immediately exits to the interpreter (so it starts with its exit)
3. When Block `second` is invalidated, the incoming fallthrough branch from
   `incoming_one` might be rewritten first, which overwrites the start of block
   `second` with a jump to a new branch stub.
4. YJIT runs of out memory
5. The incoming branch from `incoming_two` is then rewritten, but because we're
   OOM we can't generate a new stub, so we use `second`'s exit as the branch
   target. However `second`'s exit was already overwritten with a jump to the
   branch stub for `incoming_one`, so `incoming_two` will end up jumping to
   `incoming_one`'s branch stub.

Backport [Bug #21257]
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Filter `&amp;` calls from specialized C method codegen</title>
<updated>2025-02-14T01:46:14+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2025-01-09T00:07:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=294aef53b8c988f605001e4555d9532cefe8806d'/>
<id>294aef53b8c988f605001e4555d9532cefe8806d</id>
<content type='text'>
Evident with the crash reported in [Bug #20997], the C replacement
codegen functions aren't authored to handle block arguments (nor
should they because the extra code from the complexity defeats
optimization). Filter sites with VM_CALL_ARGS_BLOCKARG.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Evident with the crash reported in [Bug #20997], the C replacement
codegen functions aren't authored to handle block arguments (nor
should they because the extra code from the complexity defeats
optimization). Filter sites with VM_CALL_ARGS_BLOCKARG.
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Initialize locals in ISeqs defined with `...`</title>
<updated>2025-02-14T01:44:58+00:00</updated>
<author>
<name>Alan Wu</name>
<email>XrXr@users.noreply.github.com</email>
</author>
<published>2025-01-28T21:13:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=706f1d0573f0b807bee4c0cc8937b8f5b9b24ebd'/>
<id>706f1d0573f0b807bee4c0cc8937b8f5b9b24ebd</id>
<content type='text'>
Backport of GH-12660:

    Previously, callers of forwardable ISeqs moved the stack pointer up
    without writing to the stack. If there happens to be a stale value in
    the area skipped over, it could crash due to "try to mark T_NONE". Also,
    the uninitialized local variables were observable through `binding`.

    Initialize the locals to nil.

    [Bug #21021]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Backport of GH-12660:

    Previously, callers of forwardable ISeqs moved the stack pointer up
    without writing to the stack. If there happens to be a stale value in
    the area skipped over, it could crash due to "try to mark T_NONE". Also,
    the uninitialized local variables were observable through `binding`.

    Initialize the locals to nil.

    [Bug #21021]
</pre>
</div>
</content>
</entry>
<entry>
<title>YJIT: Add crashing test for yielding keyword args</title>
<updated>2025-02-14T01:37:38+00:00</updated>
<author>
<name>Nick Dower</name>
<email>nicholasdower@gmail.com</email>
</author>
<published>2025-01-02T16:24:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=cefa630bce3aea8317f09fe73c6439f67c42bb69'/>
<id>cefa630bce3aea8317f09fe73c6439f67c42bb69</id>
<content type='text'>
Code like the following is crashing for us on 3.4.1:

```ruby
def a(&amp;) = yield(x: 0)

1000.times { a { |x:| x } }
```

Crash:

```
ruby: YJIT has panicked. More info to follow...
thread '&lt;unnamed&gt;' panicked at ./yjit/src/codegen.rs:8018:13:
assertion `left == right` failed
  left: 0
 right: 1
```

Co-authored-by: Dani Acherkan &lt;dtl.117@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Code like the following is crashing for us on 3.4.1:

```ruby
def a(&amp;) = yield(x: 0)

1000.times { a { |x:| x } }
```

Crash:

```
ruby: YJIT has panicked. More info to follow...
thread '&lt;unnamed&gt;' panicked at ./yjit/src/codegen.rs:8018:13:
assertion `left == right` failed
  left: 0
 right: 1
```

Co-authored-by: Dani Acherkan &lt;dtl.117@gmail.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
