Skip to content

[pull] master from ruby:master#803

Merged
pull[bot] merged 12 commits intoturkdevops:masterfrom
ruby:master
Feb 24, 2026
Merged

[pull] master from ruby:master#803
pull[bot] merged 12 commits intoturkdevops:masterfrom
ruby:master

Conversation

@pull
Copy link

@pull pull bot commented Feb 24, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

jhawthorn and others added 12 commits February 23, 2026 17:06
Closes: Shopify#944

As a first step toward enabling CSE/LVN-based deduplication of frame EP loads, 
splitting `GetLocal` handling for `level > 0` into an explicit `GetEP + LoadField` path.

A follow-up PR will handle the `level == 0` case.
https://github.com/ruby/ruby/actions/runs/22316806245/job/64563939588

Local `make update-man-date` generates nothing but CI complains about
it, so just pushing this diff to make it happy.
inline_array_push, inline_array_pop, and inline_array_aref did not
guard/coerce the receiver to Array type before emitting Array-specific
HIR instructions (ArrayPush, ArrayPop, ArrayLength, ArrayAref).

This caused a MismatchedOperandType validation failure when these
handlers were called from the InvokeSuper CFUNC path, where the
receiver (self) has type BasicObject rather than Array. The crash
was triggered by representable gem's Binding::Map#<< calling
super(binding) to invoke Array#<< on an Array subclass.

Add likely_a + coerce_to checks matching the pattern used by
inline_array_aset. This is a no-op in the normal SendWithoutBlock
path where the caller already adds a GuardType, but correctly inserts
the guard when called from InvokeSuper.
Following up #16225, I'm implementing fold on AND (&) operations.

- Ruby turns this operation into a C `&` in https://github.com/tomascco/ruby/blob/880eb3c76f09c44c85389ac5efbc555afafa3e6f/numeric.c#L5197-L5210
- Rustc compiler emits an `and` assembly instruction on x86: https://godbolt.org/z/Ee74vKTfb

So the operations are equivalent. I tested manually some cases and the results match.
The following code:

```ruby
x = Object.new
sc1 = x.singleton_class
sc2 = sc1.singleton_class
x.freeze
```

Would freeze sc1 but not sc2, even though sc1 would be frozen.

Handle this by walking the class pointer chain for the object.
If the class is a singleton class, and it isn't frozen, and the
attached object for the singleton class is the object, the
singleton class should be frozen, and we move to the next iteration.

Fixes [Bug #20319]
Add a new optimization pass that deduplicates PatchPoint instructions
asserting the same invariant within a basic block when no intervening
instruction could invalidate it.

This is common in practice — e.g., `1 + 2 + 3` produces two identical
`PatchPoint MethodRedefined(Integer, +, cme)` because each `+` call
inserts one. The second is redundant since nothing between them can
redefine Integer#+.

The approach adds a `PatchPoint` leaf to the abstract heap DAG so the
effect system can distinguish instructions that could invalidate
invariants (writes to PatchPoint, e.g. Send/CCall) from those that
cannot (e.g. IncrCounter, Const). The pass maintains a HashSet of
seen invariants per block and skips duplicates, clearing the set when
an instruction writes to the PatchPoint heap.

Removed PatchPoints' orphaned Snapshot dependencies are cleaned up by
the subsequent DCE pass.

I added a new test with snapshots to `zjit/src/hir/tests.rs` in the first commit
so that you can see how the change affects it in the second commit:
88cf26b#diff-38be021d8d0035cca77d3eab5ccc530109e7832f4711a5beb4dfced7001787ae

closes Shopify#779
@pull pull bot locked and limited conversation to collaborators Feb 24, 2026
@pull pull bot added the ⤵️ pull label Feb 24, 2026
@pull pull bot merged commit 70c6251 into turkdevops:master Feb 24, 2026
1 check failed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants