Skip to content

[pull] master from ruby:master - #1400

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

[pull] master from ruby:master#1400
pull[bot] merged 16 commits into
turkdevops:masterfrom
ruby:master

Conversation

@pull

@pull pull Bot commented Sep 12, 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 : )

hmcguire-shopify and others added 16 commits September 11, 2026 19:55
`RUBY_FIXNUM_MIN / -1` is the only Fixnum division that returns a
Bignum. When either operand's known value rules out that pair, infer
Fixnum instead of Integer. This allows downstream Fixnum operations to
avoid guarding the result again.

Division by zero side exits before producing a value, so typing its
unreachable normal path as Fixnum is also safe.

Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
`tr_trans_pairs_search` expect the pointer to be incremented by
one only. Therefore, when matching a multibyte character, `search.s`
must be incremented by 1, and not `clen`.

Co-Authored-By: Federico Carrocera <fedecarrocera@gmail.com>
The disarm path MOD'd the registration to no events instead of deleting
it, to save a syscall on the next wait.  But epoll reports EPOLLHUP and
EPOLLERR whatever the mask asks for, and a mask of 0 carries no
EPOLLONESHOT, so those are reported level-triggered.  A waiter that gave
up without an event -- Thread#kill, an interrupt, a timeout -- therefore
left a registration that fires forever once the fd hangs up, and
epoll_wait returned it on every round.

The timer thread then never took its timeout branch, which is the only
place that mints a shared NT or signals the global ready queue.  Under
RUBY_MN_THREADS=2 the main thread goes dedicated while it waits in
rb_ractor_terminate_all, so snt_cnt reaches 0, a ractor sits on the grq
with nothing to run it, and the process never exits.  Repro: kill a
thread blocked on a pipe read, close the write end, then use a Ractor --
4/6 to 8/20 runs hang, with the timer thread at 100% CPU.

Under RUBY_MN_THREADS=1 the same spin burns a core silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
When the receiver is a `String` and both arguments are likely `Fixnum`, the annotation now emits a new `StringByteslice` HIR instruction that calls `rb_str_byte_substr` directly, instead of going through `CCallVariadic`.

Any other shape, one argument, a Range, or non-Fixnum arguments, keeps using CCallVariadic.
)

The ELFv2 ABI makes f14-f31 and v20-v31 callee-saved (OpenPOWER 64-bit
ELF V2 ABI, 2.2.1 Register Roles), but coroutine_transfer saved only
r14-r31, LR and CR.  A coroutine resuming from a transfer therefore
sees whatever the other side left in those registers, and GCC does keep
GPR data there: it vectorizes "store the same pointer twice" as
mtvsrdd vs63 / stxvx, and spills GPRs to VSX under register pressure.

This never bit while nothing on either side of a transfer held a live
value there.  ce6f200 reshaped nt_start, and GCC 13 now keeps a
pointer in v31 for the whole shared-nt loop, the transfer target of
every M:N park.  From then on rubyci ppc64le was red on every run:
non-main Ractor threads resumed with a stale VALUE where the VM expected
a block handler (rb_block_given_p() true without a block, "the block
passed to ... may be ignored" warnings, SEGV in invoke_block_from_c_bh
at 0x71/0x75 with the same address on every run).  x86_64 has no
callee-saved FP registers and the aarch64 Context.S already saves
d8-d15, which is why only ppc64le failed.

  https://rubyci.s3.amazonaws.com/ppc64le/ruby-master/recent.html
  https://rubyci.s3.amazonaws.com/ppc64le/ruby-master/log/20260911T003005Z.fail.html.gz

Save f14-f31 with stfd/lfd and v20-v31 with stvx/lvx (VMX only, no VSX
requirement); the frame grows from 160 to 496 bytes and
COROUTINE_REGISTERS from 24 to 66 words.  The LR slot stays at index
18, so coroutine_initialize is otherwise unchanged.  Fibers use the same
transfer and are covered too.  glibc's setjmp/longjmp on ppc64 already
save and restore this set, so the EC tags and
RB_VM_SAVE_MACHINE_CONTEXT were not affected.

Verified on POWER9 (Ubuntu 24.04, gcc 13.3.0, 64K pages, the rubyci
configure) at fef20ce: without this patch
TestSetTraceFunc#test_tp_ractor_local_untargeted dies at 0x75 and
TestEnv#test_delete_in_ractor at 0x71 as on rubyci, and
TestTmpdir#test_ractor / TestEnv#test_fetch_in_ractor fail on the same
warnings; with it all of them pass and bootstraptest/test_ractor.rb
passes.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
We can see some nice performance gains across the board with StickyImmix
support:

--------------  -------------  ------------  ----------------  ------------  -------------------  -----------------  ---------------------
bench              Immix (ms)     RSS (MiB)  StickyImmix (ms)     RSS (MiB)  StickyImmix 1st itr  Immix/StickyImmix  RSS Immix/StickyImmix
activerecord     205.1 ± 1.4%  127.8 ± 0.0%      126.1 ± 3.8%  150.3 ± 0.6%                1.790              1.626                  0.850
chunky-png       409.2 ± 1.6%   90.2 ± 0.1%      378.7 ± 1.0%  119.0 ± 0.4%                1.046              1.081                  0.758
erubi-rails     1028.3 ± 1.0%  168.5 ± 0.0%      549.3 ± 0.8%  194.1 ± 0.0%                1.879              1.872                  0.868
hexapdf         1014.9 ± 2.3%  534.7 ± 2.3%      885.5 ± 0.7%  743.4 ± 2.4%                1.075              1.146                  0.719
liquid-c          35.1 ± 2.9%   93.5 ± 0.1%       25.1 ± 5.2%  107.6 ± 0.3%                1.502              1.399                  0.869
liquid-compile    88.3 ± 3.4%   91.4 ± 0.1%       31.2 ± 3.9%  110.1 ± 0.3%                2.707              2.826                  0.830
liquid-il        228.9 ± 1.7%   77.8 ± 0.1%      168.2 ± 0.7%   93.2 ± 0.0%                1.347              1.361                  0.835
liquid-render     71.2 ± 2.0%   93.8 ± 0.1%       59.2 ± 2.4%  109.8 ± 0.2%                1.197              1.203                  0.854
lobsters         425.8 ± 0.7%  387.6 ± 0.8%      368.6 ± 3.0%  514.6 ± 0.4%                1.238              1.155                  0.753
mail             115.0 ± 1.7%  104.8 ± 0.0%       62.7 ± 2.2%  110.9 ± 0.1%                1.927              1.835                  0.945
psych-load      1618.2 ± 1.1%   86.2 ± 0.0%      993.7 ± 0.6%  101.2 ± 0.0%                1.648              1.628                  0.852
railsbench      1058.4 ± 0.4%  190.8 ± 0.0%      775.2 ± 0.5%  216.5 ± 0.0%                1.384              1.365                  0.881
rubocop           84.3 ± 3.9%  169.5 ± 1.5%       74.6 ± 5.1%  202.4 ± 1.1%                1.381              1.130                  0.837
ruby-lsp         106.8 ± 4.0%  126.8 ± 0.3%       75.2 ± 5.7%  151.1 ± 0.9%                1.377              1.420                  0.839
sequel            54.2 ± 3.0%   81.1 ± 0.1%       27.7 ± 4.2%   92.5 ± 0.3%                2.065              1.953                  0.876
shipit           667.4 ± 2.7%  240.0 ± 0.0%      630.6 ± 0.8%  301.3 ± 0.3%                1.097              1.058                  0.796
--------------  -------------  ------------  ----------------  ------------  -------------------  -----------------  ---------------------

ruby/mmtk@24f507513f
@pull pull Bot locked and limited conversation to collaborators Sep 12, 2026
@pull pull Bot added the ⤵️ pull label Sep 12, 2026
@pull
pull Bot merged commit 81757dd into turkdevops:master Sep 12, 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.

10 participants