96790 Commits

Author SHA1 Message Date
Earlopain
f3a5b0cdb5
Apply backport label to 4.X branches (#15925) 2026-01-21 09:50:28 -08:00
git
e7f6a30d79 Update default gems list at 7f687b0abc155cd941d416677184f9 [ci skip] 2026-01-21 16:02:13 +00:00
Schneems
7f687b0abc [ruby/syntax_suggest] v2.0.3
https://github.com/ruby/syntax_suggest/commit/a81b92fcf2
2026-01-21 16:01:16 +00:00
Schneems
54fa9c81e1 [ruby/syntax_suggest] Refactor multi-prism version logic
The reason this logic for different methods branches in the class instead of internally was to be eagerly aggressive about runtime performance. This code is currently only used once for the document where it's invoked ~N times (where N is number of lines):

```ruby
module SyntaxSuggest
  class CleanDocument
    # ...
    def join_trailing_slash!
      trailing_groups = @document.select(&:trailing_slash?).map do |code_line|
        take_while_including(code_line.index..) { |x| x.trailing_slash? }
      end
      join_groups(trailing_groups)
      self
    end
```

Since this is not currently a hot-spot I think merging the branches and using a case statement is a reasonable tradeoff and avoids the need to do specific version testing.

An alternative idea was presented in #241 of behavior-based testing for branch logic (which I would prefer), however, calling the code triggered requiring a `DelegateClass` when the `syntax_suggest/api` is being required.

https://github.com/ruby/syntax_suggest/commit/ab122c455f
2026-01-21 15:57:38 +00:00
Earlopain
8aedb89681 [ruby/prism] Also handle BasicObject as a return value
We should touch these as little as possible and just pass them along

https://github.com/ruby/prism/commit/52c4fa785e
2026-01-21 13:21:37 +00:00
Benoit Daloze
913ffcd1dd [ruby/prism] Check using Prism nodes if a command call has any arguments in Ripper translator
* We don't know what `on_*` events might return so we cannot assume it's an Array.
* See https://github.com/ruby/prism/issues/3838#issuecomment-3774702396

https://github.com/ruby/prism/commit/bed4271ce2
2026-01-21 13:21:37 +00:00
Jean Boussier
519a4bdbc1 Optimize File.basename
The actual algorithm is largely unchanged, just allowed to use
singlebyte checks for common encodings.

It could certainly be optimized much further, as here again it often
scans from the front of the string when we're interested in the back of
it. But the algorithm as many Windows only corner cases so I'd rather
ship a good improvement now and eventually come back to it later.

Most of improvement here is from the reduced setup cost (avodi double
null checks, avoid duping the argument, etc), and skipping the multi-byte
checks.

```
compare-ruby: ruby 4.1.0dev (2026-01-19T03:51:30Z master 631bf19b37) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-21T08:21:05Z opt-basename 7eb11745b2) +PRISM [arm64-darwin25]
```

|           |compare-ruby|built-ruby|
|:----------|-----------:|---------:|
|long       |      3.412M|   18.158M|
|           |           -|     5.32x|
|long_name  |      1.981M|    8.580M|
|           |           -|     4.33x|
|withext    |      3.200M|   12.986M|
|           |           -|     4.06x|
2026-01-21 11:23:01 +01:00
Hiroshi SHIBATA
0f1eea0949 [ruby/rubygems] Skip failing tests
https://github.com/ruby/rubygems/commit/ee68fd8d20
2026-01-21 07:40:49 +00:00
Jason Lunn
d93235874a [ruby/rubygems] Appease the linter again
https://github.com/ruby/rubygems/commit/92f35e9684
2026-01-21 07:40:48 +00:00
Jason Lunn
2efffe09e1 [ruby/rubygems] Appease the linter
https://github.com/ruby/rubygems/commit/aba307411a
2026-01-21 07:40:48 +00:00
Jason Lunn
c959741695 [ruby/rubygems] Add test
https://github.com/ruby/rubygems/commit/3d8140b289
2026-01-21 07:40:48 +00:00
Jason Lunn
3aa866ca0d [ruby/rubygems] Remove special behavior for rake
Fixes https://github.com/ruby/rubygems/pull/9244

https://github.com/ruby/rubygems/commit/7dc3d43d2e
2026-01-21 07:40:47 +00:00
Randy Stauner
6f1453dc08
ZJIT: Support optional keyword arguments in direct send (#15873)
This fills in constants when unspecified optional keyword args have static default values.
For complex defaults we calculate the kw_bits and utilize the checkkeyword logic we already had.

The following benchmarks used to register param_kw_opt.
Some of them (like graphql*) just trade that for some other complexity, or "too_many_args_for_lir".
Notable improvements include activerecord where the previous param_kw_opt count has a corresponding drop in complex args and dynamic_send_count and a nearly equal rise in optimized_send_count.
The gains are similar but not as complete in hexapdf, liquid-render, lobsters, railsbench, shipit.

| Benchmark | param_kw_opt | Δ one_or_more_complex | Δ too_many_args | Δ dynamic_send | Δ optimized_send |
|-----------|-------------:|----------------------:|----------------:|---------------:|-----------------:|
| activerecord | 6,307,141 | -6,253,823 | +4,084 | -6,306,223 | +6,279,766 |
| blurhash | 21 | -21 | +0 | -23 | +20 |
| chunky-png | 813,604 | -813,604 | +0 | -813,616 | +813,556 |
| erubi-rails | 1,590,395 | -590,274 | +35,578 | -552,914 | +550,826 |
| fluentd | 4,906 | -4,854 | +21 | -5,745 | +5,080 |
| graphql | 1,610,439 | -1,610,432 | +1,605,751 | -4,688 | +4,628 |
| graphql-native | 16,332,386 | -16,332,375 | +16,309,681 | -22,701 | +22,638 |
| hexapdf | 9,165,465 | -9,124,509 | +203,754 | -8,920,727 | +8,839,295 |
| liquid-compile | 14,817 | -14,792 | +0 | -14,705 | +15,045 |
| liquid-render | 3,994,905 | -3,994,901 | +0 | -3,994,868 | +3,020,779 |
| lobsters | 2,467,510 | -2,297,298 | +205,610 | -2,216,583 | +1,694,092 |
| protoboeuf | 11,521 | -11,521 | +0 | -11,523 | +11,520 |
| psych-load | 77,612 | -77,609 | +29,942 | -77,613 | -12,242 |
| rack | 2,743 | -2,742 | +0 | -2,750 | +2,668 |
| railsbench | 3,579,778 | -2,517,615 | +432,575 | -2,084,480 | +1,882,928 |
| ruby-lsp | 287,171 | -379,716 | +37 | -409,368 | -267,248 |
| rubyboy | 5,993,004 | -5,993,003 | +0 | -5,993,006 | +5,992,993 |
| sequel | 182,652 | -182,631 | +0 | -182,563 | +122,687 |
| shipit | 3,289,456 | -2,778,419 | +306,867 | -3,201,395 | +1,068,505 |
| tinygql | 2,732 | -2,732 | +1 | -2,734 | +2,729 |
2026-01-21 01:19:34 -05:00
Peter Zhu
01984fa80e [ruby/mmtk] Pass whether GC is moving to rb_mmtk_update_global_tables
https://github.com/ruby/mmtk/commit/002faa8f92
2026-01-21 01:55:16 +00:00
Alan Wu
36809a8d0c ZJIT: Add fail-fast assert for non-register {cpush,cpop}_pair
There is no splitting for these so let's add a assert to try and catch
misuse. VRegs are not necessarily registers in the end, so this is best
effort. In those situations they'll get a less proximate panic message.
2026-01-20 19:42:25 -05:00
Jeff Zhang
f7e73ba3bf ZJIT: A64: Avoid gaps in the stack when preserving registers for calls
Previously, we used a `str x, [sp, #-0x10]!` for each value, which
left an 8-byte gap. Use STP to store a pair at a time instead.
2026-01-20 19:42:25 -05:00
Peter Zhu
e24b52885f Allow objects on Ruby stack to be GC movable
Objects on the Ruby stack can be GC movable and there is corresponding
code in rb_execution_context_update to update references for moved objects.
2026-01-20 18:01:22 -05:00
Alan Wu
631a5076da ZJIT: Delete Insn::CPushAll and Insn::CPopAll
Since we automatically preserve registers across calls, it's never
necessary to manually and imprecisely do it with `C{Push,Pop}All`.
Delete them to remove the maintenance burden and reduce confusion.
2026-01-20 16:37:51 -05:00
Alan Wu
1bc5111411 ZJIT: Add a smoke test for --zjit-trace-exits
Better than nothing!
2026-01-20 16:37:51 -05:00
Earlopain
9ad8dd00b1 [ruby/prism] Fix on_* return value of ripper translator
You're supposed to return the first argument.
```rb
# Before
[[:stmts_new], [:rescue_mod, nil, nil], [:stmts_add, nil, nil], [:program, nil]]
# After
[[:stmts_new], [:rescue_mod, "1", "2"], [:stmts_add, nil, "1"], [:program, nil]]
```

The correct result would be:
`[[:rescue_mod, "1", "2"], [:stmts_new], [:stmts_add, nil, "1"], [:program, nil]]`

But the order depends on the prism AST so it seems very difficult to match.

https://github.com/ruby/prism/commit/94e0107729
2026-01-20 20:23:18 +00:00
Jeff Zhang
d225bb8b46
ZJIT: Compile IsA into load + compare for String/Array/Hash (#15878)
Resolves https://github.com/Shopify/ruby/issues/880

Implemented this by using the code generation for `GuardType` as a reference.
Not sure if this is the best way to go about it, but it seems to work.
2026-01-20 10:50:43 -05:00
Nobuyoshi Nakada
c27ae8d91a [ruby/psych] Remove excessive check of message
The order of "unexpected" and "missing" keyword argument errors at
`Data#initialize` had not been defined strictly.

[Bug #21844](https://bugs.ruby-lang.org/issues/21844)
ruby/ruby#15910

https://github.com/ruby/psych/commit/ba748d9b04
2026-01-20 14:15:41 +00:00
Earlopain
2842e61c92 Reapply "[ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper"
This reverts commit 58f1127b51cf4fbb1f334f8701a041f40701dca2.
2026-01-20 14:18:30 +01:00
Earlopain
20113a228d Handle on_sp in syntax_suggest when using prism
It used to not emit this token type, but now it does.
So when a newer version of prism is present, we can fall back
to the same code that ripper uses.
2026-01-20 14:18:30 +01:00
Nobuyoshi Nakada
300927b4bb
[Bug #21845] Rebuild gem extensions at RUBY_ABI_VERSION change
As `TARGET_SO_DIR_TIMESTAMP` contains `ruby_version`, after bumping
`RUBY_ABI_VERSION` it should not be existing.  Usually such outdated
files will be removed by `make outdate-bundled-gems` automatically
invoked by `make up`.
2026-01-20 19:21:45 +09:00
Hiroshi SHIBATA
58f1127b51
Revert "[ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper"
This reverts commit 35a7b5159f39de2cac848c072674e5350cc41aa4.

This broke syntax_suggest.

https://github.com/ruby/ruby/actions/runs/21167011751/job/60874111912
2026-01-20 19:10:16 +09:00
Benoit Daloze
35a7b5159f [ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper
* Handle line continuations.
* Handle space at the end of file in LexCompat.

https://github.com/ruby/prism/commit/32bd13eb7d

Co-authored-by: Earlopain <14981592+Earlopain@users.noreply.github.com>
2026-01-20 09:53:08 +00:00
Jean Boussier
53fe9933fd Optimize File.extname for common encodings
Similar optimizations to the ones performed in GH-15907.

- Skip the expensive multi-byte encoding handling for the common
  encodings that are known to be safe.
- Use `CheckPath` to save on copying the argument and only scan it for
  NULL bytes once.
- Create the return string with rb_enc_str_new instead of rb_str_subseq
  as it's going to be a very small string anyway.

This could be optimized a little bit further by searching for both `.` and `dirsep`
in one pass,

```
compare-ruby: ruby 4.1.0dev (2026-01-19T03:51:30Z master 631bf19b37) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-20T07:33:42Z master 6fb50434e3) +PRISM [arm64-darwin25]
```

|           |compare-ruby|built-ruby|
|:----------|-----------:|---------:|
|long       |      3.606M|   22.229M|
|           |           -|     6.17x|
|long_name  |      2.254M|   13.416M|
|           |           -|     5.95x|
|short      |     16.488M|   29.969M|
|           |           -|     1.82x|
2026-01-20 09:58:51 +01:00
Jean Boussier
6fb50434e3 file.c: Stop passing NULL for encoding
`rb_encoding *` is defined as `nonnull` so `if (enc)` is optimized
out by the compiler. We have to pass a boolean alongside it to
avoid crashes.
2026-01-20 08:33:42 +01:00
Jean Boussier
2d10f15118 file.c: dirname_n also use strrdirsep when n > 1
It's both simpler and faster.

|       |compare-ruby|built-ruby|
|:------|-----------:|---------:|
|long   |      3.960M|   24.072M|
|       |           -|     6.08x|
|short  |     15.417M|   29.841M|
|       |           -|     1.94x|
|n_4    |      3.858M|   18.415M|
|       |           -|     4.77x|
2026-01-20 08:33:42 +01:00
Jean Boussier
990cf1286a file.c: Inc macro now handle NULL encoding 2026-01-20 08:33:42 +01:00
Jean Boussier
240a58ecc6 file.c: skiproot doesn't need encoding 2026-01-20 08:33:42 +01:00
Jean Boussier
11d29d32d2 file.c: strrdirsep search from the back of the string for common encodings
`strrdirsep` quite innficiently search for the last separator from the front
of the string.

This is surprising but necessary because in Shift-JS, `0x5c` can
be the second byte of some multi-byte characters, as such it's
not possible to do a pure ASCII search. And it's even more costly
because for each character we need to do expensive checks to
handle this possibility.

However in the overwhelming majority of cases, paths are encoded
in UTF-8 or ASCII, so for these common encodings we can use the
more logical and efficient algorithm.

```
compare-ruby: ruby 4.1.0dev (2026-01-17T14:40:03Z master 00a3b71eaf) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-19T07:43:57Z file-dirname-lower.. a8d3535e5b) +PRISM [arm64-darwin25]
```

|       |compare-ruby|built-ruby|
|:------|-----------:|---------:|
|long   |      3.974M|   23.674M|
|       |           -|     5.96x|
|short  |     15.281M|   29.034M|
|       |           -|     1.90x|
2026-01-20 08:33:42 +01:00
Jean Boussier
27bb1623cd file.c: Optimize rb_file_dirname_n fixed costs
- `str_null_check` was performed twice, once by `FilePathStringValue`
  and a second time by `StringValueCStr`.
- `StringValueCStr` was checking for the terminator presence, but we
  don't care about that.
- `FilePathStringValue` calls `rb_str_new_frozen` to ensure `fname`
  isn't mutated, but that's costly for such a check. Instead we
  can do it in debug mode only.
- `rb_enc_get` is slow because it accepts arbitrary objects, even immediates,
  so it has to do numerous type checks. Add a much faster `rb_str_enc_get`
  when we know we're dealing with a string.
- `rb_enc_copy` is slow for the same reasons, since we already have the
  encoding, we can use `rb_enc_str_new` instead.
2026-01-20 08:33:42 +01:00
Alan Wu
826dbcfb2b ZJIT: A64: Remove nop padding after conditional branches
Previously, there were a lot of nops after conditional branches. They
come from branch to LIR labels:

    ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e 'Object || String'

    # Insn: v14 CheckInterrupts
    # RUBY_VM_CHECK_INTS(ec)
      ldur w2, [x20, #0x20]
      tst w2, w2
      b.ne #0x120900278
      nop
      nop
      nop
      nop
      nop
    # Insn: v15 Test v11
      tst x0, #-5
      mov x2, #0
      mov x3, #1
      csel x2, x2, x3, eq
    # Insn: v16 IfTrue v15, bb3(v6, v11)
      tst x2, x2
      b.eq #0x120900198
      nop
      nop
      nop
      nop
      nop

They gunk up the disassembly and can't be helpful for speed. This commit
removes them. I think they were accidentally inherited from certain YJIT
branches that require padding for patching. ZJIT doesn't have these
requirements.

Use a single branch instruction for conditional branches to labels; Jmp
already uses a single `B` instruction. This will work for assemblers
that generate less than ~260,000 instructions -- plenty.

Let the CodeBlock::label_ref() callback return a failure, so we can
fail compilation instead of panicking in case we do get large offsets.
2026-01-19 22:47:36 -05:00
Peter Zhu
fa910e2bba [ruby/mmtk] Restore MMTK_DEBUG around zeroing in obj_free
https://github.com/ruby/mmtk/commit/ae69d69768
2026-01-20 01:32:51 +00:00
Earlopain
16adb9303f [ruby/prism] Optimize ripper translator
Creating state classes is pretty expensive.
Since they are not modifiable, we can reuse them instead.

Benchmark script:
```rb
require "ripper"
require "prism"
require "benchmark/ips"

codes = Dir["**/*.rb"].map { File.read(it) }

Benchmark.ips do |x|
  x.config(time: 10)
  x.report("prism") { codes.each { Prism::Translation::Ripper.lex(it) } }
  x.report("ripper") { codes.each { Ripper.lex(it) } }

  x.compare!
end
```

Before:

```
ruby 4.0.0 (2025-12-25 revision https://github.com/ruby/prism/commit/553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
               prism     1.000 i/100ms
              ripper     1.000 i/100ms
Calculating -------------------------------------
               prism      0.293 (± 0.0%) i/s     (3.42 s/i) -      3.000 in  10.248348s
              ripper      0.633 (± 0.0%) i/s     (1.58 s/i) -      7.000 in  11.055687s

Comparison:
              ripper:        0.6 i/s
               prism:        0.3 i/s - 2.16x  slower
```

After

```
ruby 4.0.0 (2025-12-25 revision https://github.com/ruby/prism/commit/553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
               prism     1.000 i/100ms
              ripper     1.000 i/100ms
Calculating -------------------------------------
               prism      0.486 (± 0.0%) i/s     (2.06 s/i) -      5.000 in  10.280413s
              ripper      0.635 (± 0.0%) i/s     (1.58 s/i) -      7.000 in  11.027169s

Comparison:
              ripper:        0.6 i/s
               prism:        0.5 i/s - 1.31x  slower
```

https://github.com/ruby/prism/commit/bdde16554c
2026-01-19 23:54:39 +00:00
Peter Zhu
c939330b7a [DOC] Escape Coverage 2026-01-19 17:09:29 -05:00
Alan Wu
6f890976e0 JITs: Fix comment about ARM64 stack growth direction [ci skip] 2026-01-19 15:17:11 -05:00
Benoit Daloze
859920dfd2 [ruby/prism] Add Prism::Source#line_to_byte_offset and replace direct accesses to offsets
https://github.com/ruby/prism/commit/ff81a29ba5
2026-01-19 12:03:33 +00:00
Benoit Daloze
ae5efb55d1 [ruby/prism] Simplify and optimize Prism::Node#tunnel
* By comparing byte offsets which folds 3 branches into 1.
* Also avoids allocation of Location objects.

https://github.com/ruby/prism/commit/71fcb891e0
2026-01-19 12:03:33 +00:00
Benoit Daloze
e85fd7c878 [ruby/prism] Fix docs of opening_loc/closing_loc of BlockNode
https://github.com/ruby/prism/commit/0b22d9060a
2026-01-19 12:03:33 +00:00
dependabot[bot]
aa31754e56 Bump actions/cache in /.github/actions/setup/directories
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](9255dc7a25...8b402f58fb)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-19 18:56:44 +09:00
Earlopain
3c9ca23ba4 [ruby/prism] Remove duplicate lex tests
`RipperTest` already does this (added in https://github.com/ruby/prism/pull/3849)
Since it doesn't use the token classes, it also lists out all the excludes instead of just claiming some are passing.

https://github.com/ruby/prism/commit/e86a28263c
2026-01-19 07:46:48 +00:00
Hiroshi SHIBATA
df479f41f8 [ruby/rubygems] Added another usage of pristine command
ref. https://github.com/rubygems/guides/issues/388

https://github.com/ruby/rubygems/commit/43f3768f09
2026-01-19 07:14:33 +00:00
Sutou Kouhei
fb75e99efe [ruby/rubygems] Add missing .binmode for Gem::AtomicFileWriter
In https://github.com/ruby/rubygems/pull/9202, I commented that `temp_file.binmode` is redundant. But I
was wrong. We need `temp_file.binmode` even when we specify
`File::BINARY`. Sorry.

https://github.com/ruby/rubygems/commit/d9f1f5c6a6
2026-01-19 07:10:42 +00:00
Hiroshi SHIBATA
631bf19b37
Skip Onigmo file sync. This target is only for commit sync. 2026-01-19 12:51:30 +09:00
dependabot[bot]
ed116239c7 Bump actions/cache from 5.0.1 to 5.0.2
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](9255dc7a25...8b402f58fb)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-18 18:34:27 -08:00
Herwin
b4a62a1ca9
[DOC] Update docs for rb_interned_str and related functions (#15897)
Related to [Bug #21842].

* rb_interned_str: document what decides whether the returned string is
  in US-ASCII or BINARY encoding.
* rb_interned_str_cstr: include the same description as rb_interned_str
  for the encoding. This one was still missing the update for US-ASCII
  and erroneously said the returned string was alwasy in BINARY encoding
* rb_str_to_interned_str: document how the encoding of the result is
  defined.

Co-authored-by: Herwin <herwinw@users.noreply.github.com>
2026-01-19 11:16:47 +09:00
Peter Zhu
64c142770a [ruby/mmtk] Fix assertion in rb_gc_impl_ractor_cache_free for RUBY_FREE_AT_EXIT
https://github.com/ruby/mmtk/commit/e2a89d5a22
2026-01-18 21:34:57 +00:00