Skip to content

[pull] master from ruby:master - #1439

Merged
pull[bot] merged 10 commits into
turkdevops:masterfrom
ruby:master
Sep 24, 2026
Merged

pull[bot] merged 10 commits into
turkdevops:masterfrom
ruby:master

Conversation

@pull

@pull pull Bot commented Sep 24, 2026

Copy link
Copy Markdown

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 : )

k0kubun and others added 10 commits September 23, 2026 12:50
The JIT optimizer sees an `invokebuiltin` and would like to assume that calling it does not write back to the frame. A `Primitive` should never write to the frame by taking a pointer to a local, so this PR removes that functionality.

Partial revert of bb89242.

----

* Don't allow writing to locals in cexpr

This makes the few remaining cases of `cexpr`-that-looks-at-locals a
read-only view.

* Remove uses of LOCAL_PTR from ractor.rb

Use two new builtin functions instead.

* Remove LOCAL_PTR from mk_builtin_loader

* Don't bother making the intermediate pointer

* Revert bb89242

* Add Primitive.local_self!
Guard the block arg of `foo(&blk)` when profiling shows it is exactly
a Proc, and pass it directly as the callee frame's block handler
instead of falling back to a dynamic send.
There were some difficulties after ruby/prism#4223 was merged because
the excludes were out of sync.
Previously, `setlocal level=0` did not set the local in the frame state
during HIR build, unlike `setlocal_WC_0`. `getlocal` and `getlocal_WC_0`
had the same issue.

I don't know if it's possible to trigger an ZJIT issue with default
iseq compile options today, but with ZJIT patches I'm working on
that touch locals, it is readily possible.

Fix by centralizing the match arms for `getlocal`, `setlocal`, and all
of their `*_WC_*` variants.
Closes Shopify#1061.

Also add a test to make sure `String#intern` generates the same HIR.

### Benchmarks

I had AI create 4 new microbenchmarks for this change and also run `protoboeuf-encode`.

They look like this:

```ruby
require_relative '../harness/loader'

keys = Array.new(2_048) { |i| "zjit-benchmark-key-#{i}" }
keys.each(&:to_sym)
expected = keys.last.to_sym

def zjit_bench_varied(keys)
  i = 0
  result = nil
  while i < 2_048
    result = keys[i].to_sym
    i += 1
  end
  result
end

run_benchmark(1) do
  result = nil
  1_000.times { result = zjit_bench_varied(keys) }
  raise 'incorrect symbol' unless result.equal?(expected)
end
```

Let me know if you want those microbenchmarks in the repository and I'll open the PR.

Also let me know if you want other macro benchmakrs included.

```
before: ruby 4.1.0dev (2026-09-23T16:47:54Z :detached: d74c656) +ZJIT dev +PRISM [arm64-darwin25]
after: ruby 4.1.0dev (2026-09-23T18:10:52Z :detached: 6662568) +ZJIT dev +PRISM [arm64-darwin25]

------------------  ------------  ------------  -------------  ------------
bench                before (ms)    after (ms)  after 1st itr  before/after
protoboeuf-encode   233.2 ± 2.1%  228.5 ± 0.9%          1.075         1.021
zjit-to-sym-dup      64.8 ± 1.7%   60.2 ± 2.0%          1.071         1.075
zjit-to-sym-new      57.3 ± 4.4%   55.3 ± 3.6%          0.936         1.038
zjit-to-sym-reused  165.5 ± 2.1%  148.9 ± 1.3%          1.245         1.112
zjit-to-sym-varied  196.2 ± 1.8%  179.1 ± 1.3%          1.108         1.096
------------------  ------------  ------------  -------------  ------------
```
(ruby/strscan#219)

`#pos=` accepts an arbitrary byte offset, so the scan position can fall
in the middle of a multi-byte character such as UTF-16BE. Matching from
there made Onigmo read a whole character starting at that position,
reading past the end of the string.

On CRuby this is an out-of-bounds read.

On JRuby a search such as `#scan_until` could loop without terminating.

On TruffleRuby it aborts with an internal error while building the
matched substring. But we don't change the TruffleRuby implementation
because we don't have a fast implementation for this.

Refuse to match unless the current position is the head of a character.

ruby/strscan@a552ea6f49
@pull pull Bot locked and limited conversation to collaborators Sep 24, 2026
@pull pull Bot added the ⤵️ pull label Sep 24, 2026
@pull
pull Bot merged commit 1c91d9b into turkdevops:master Sep 24, 2026
1 of 3 checks passed
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.

7 participants