Project

General

Profile

Actions

Bug #22306

open

Ruby::Box: with_jit hooks do not reach existing boxes

Bug #22306: Ruby::Box: with_jit hooks do not reach existing boxes

Added by hsbt (Hiroshi SHIBATA) 10 days ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 4.1.0dev (2026-09-10T03:20:50Z master fe58143f12) +YJIT +MN +PRISM [arm64-darwin27]
[ruby-core:126659]

Description

Under RUBY_BOX=1, enabling YJIT does not switch Array#each, #map, #select and Integer#downto to their Ruby implementations in the root and main boxes. Only boxes created later get them.

$ RUBY_BOX=1 ruby --yjit -e 'p Array.instance_method(:each).source_location, Ruby::Box.new.eval("Array.instance_method(:each).source_location")'
nil
["<internal:array>", 219]

Without RUBY_BOX the first line is ["<internal:array>", 219]. 4.0.6 gives the same output. TestYJIT#test_yjit_option_uses_array_each_in_ruby and #test_yjit_enable_replaces_array_each fail under RUBY_BOX=1 for this reason.

with_jit in jit_hook.rb registers its block while the builtins load in the master box, so the undef and def in it change only the master box. The hooks run after the root and main boxes exist, even with --yjit (ruby.c:1877). By then loading RubyGems has given both boxes their own copy of Array, as any cached method call on it does.

Moving the hook call before the boxes are created would cover only --yjit, not RubyVM::YJIT.enable.

I see two designs.

The first runs the hooks in every existing box as well as the master box when a JIT is enabled. Each box would then check rb_builtin_basic_definition_p against its own definitions, so a box that patched Array#each keeps its patch. The blocks take their box from their environment, so this needs a way to run them with another box as the current one.

The second stops redefining methods after boot. The Ruby implementations are defined at boot next to the C ones, before any box exists, and the JIT picks the Ruby one when it compiles a call. Nothing changes after boot, which fits a master box that runs no code. It does change how the JIT dispatches these methods and what source_location reports.

with_yjit came with 478e0fc710b, when the Ruby Array#each from #20182 was limited to YJIT, and became with_jit for ZJIT in 2cd10de3309. Both predate Ruby::Box.


Related issues 3 (1 open2 closed)

Related to Ruby - Misc #22275: Ruby::Box support plan for RubyGems and BundlerOpenActions
Related to Ruby - Feature #21881: Split the root box into the (newer) root box and the master of copied user boxesClosedtagomoris (Satoshi Tagomori)Actions
Related to Ruby - Feature #20182: Rewrite Array#each in RubyClosedActions
Actions

Also available in: PDF Atom