96730 Commits

Author SHA1 Message Date
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
Peter Zhu
b7e9e66b59 [ruby/mmtk] Check RUBY_FL_FINALIZE on new location of object if moved
https://github.com/ruby/mmtk/commit/a31deee342
2026-01-18 21:34:57 +00:00
Peter Zhu
4111c5465f [ruby/mmtk] Replace RUBY_ASSERT with MMTK_ASSERT
https://github.com/ruby/mmtk/commit/e92baf15ef
2026-01-18 21:34:57 +00:00
tomoya ishida
b536c6a849
[DOC] Remove _emphasis_ in code blocks which is not handled as emphasis anymore (#15901) 2026-01-19 04:59:09 +09:00
tomoya ishida
37c7ee536d
[DOC] Replace rdoc style codeblocks with markdown style backtick codeblocks in markdown documents (#15900) 2026-01-19 02:25:02 +09:00
Jean Boussier
43d879d3ac rb_file_join_fastpath: removed useless StringValueCStr 2026-01-18 17:15:36 +01:00
Peter Zhu
19450d85d6 [DOC] Improve docs for ObjectSpace.define_finalizer 2026-01-18 10:47:13 -05:00
Jean Boussier
7e0e9984d0 rb_file_join_fastpath: optimize searching for separators
`chompdirsep` searches from the start of the string each time, which
perhaps is necessary for certain encodings (not even sure?) but for
the common encodings it's very wasteful. Instead we can start from the
back of the string and only compare one or two characters in most cases.

Also replace `StringValueCStr` for the simpler `rb_str_null_check`
as we only care about whether the string contains `NULL` bytes, we
don't care whether it is NULL terminated or not.

We also only check the final string for NULLs.

```
compare-ruby: ruby 4.1.0dev (2026-01-17T14:40:03Z master 00a3b71eaf) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-18T12:55:15Z spedup-file-join 5948e92e03) +PRISM [arm64-darwin25]
warming up....

|              |compare-ruby|built-ruby|
|:-------------|-----------:|---------:|
|two_strings   |      2.477M|   19.317M|
|              |           -|     7.80x|
|many_strings  |    547.577k|   10.298M|
|              |           -|    18.81x|
|array         |    515.280k|  523.291k|
|              |           -|     1.02x|
|mixed         |    621.840k|  635.422k|
|              |           -|     1.02x|
```
2026-01-18 16:31:31 +01:00
Jean Boussier
6cd4549060 Optimize File.join common use case
`File.join` is a hotspot for common libraries such as Zeitwerk
and Bootsnap. It has a fairly flexible signature, but 99% of
the time it's called with just two (or a small number of) UTF-8 strings.

If we optimistically optimize for that use case we can cut down a large
number of type and encoding checks, significantly speeding up the method.

The one remaining expensive check we could try to optimize is `str_null_check`.
Given it's common to use the same base string for joining, we could memoize it.
Also we could precompute it for literal strings.

```
compare-ruby: ruby 4.1.0dev (2026-01-17T14:40:03Z master 00a3b71eaf) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-18T12:10:38Z spedup-file-join 069bab58d4) +PRISM [arm64-darwin25]
warming up....

|              |compare-ruby|built-ruby|
|:-------------|-----------:|---------:|
|two_strings   |      2.475M|    9.444M|
|              |           -|     3.82x|
|many_strings  |    551.975k|    2.346M|
|              |           -|     4.25x|
|array         |    514.946k|  522.034k|
|              |           -|     1.01x|
|mixed         |    621.236k|  633.189k|
|              |           -|     1.02x|
```
2026-01-18 16:31:31 +01:00
Earlopain
d1dc4bdb2f [ruby/prism] Fix ripper translator for __END__
https://github.com/ruby/prism/commit/2792ac78ca
2026-01-18 14:07:06 +00:00
Peter Zhu
00a3b71eaf [DOC] Improve docs for ObjectSpace.memsize_of_all 2026-01-17 09:40:03 -05:00