Bug #22421
closed`RubyVM::YJIT.max_compile_time_ns=` aborts the process when YJIT is not enabled
Description
Calling RubyVM::YJIT.max_compile_time_ns= (added by [Feature #22236]) before YJIT is enabled aborts the process with a Rust panic.
$ ruby -v
ruby 4.1.0dev (2026-10-09T00:54:42Z master 21f68cfec7) +PRISM [x86_64-linux]
$ ruby -e 'RubyVM::YJIT.max_compile_time_ns = 10'
thread '<unnamed>' (10) panicked at /usr/src/ruby/yjit/src/codegen.rs:11313:43:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' (10) panicked at .../library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
Aborted (core dumped)
The same happens with ruby --yjit-disable -e 'RubyVM::YJIT.max_compile_time_ns = 10'.
It works as expected once YJIT is enabled, either with --yjit or after RubyVM::YJIT.enable:
$ ruby --yjit -e 'RubyVM::YJIT.max_compile_time_ns = 10; p RubyVM::YJIT.max_compile_time_ns'
10
$ ruby -e 'RubyVM::YJIT.enable; RubyVM::YJIT.max_compile_time_ns = 10; p RubyVM::YJIT.max_compile_time_ns'
10
The reader side does not crash (RubyVM::YJIT.max_compile_time_ns and RubyVM::YJIT.total_compile_time_ns return 0 when YJIT is not enabled).
The panic is the unwrap() in CodegenGlobals::get_instance() (yjit/src/codegen.rs), which is None until YJIT is initialized. Other YJIT methods that touch the globals (for example reset_stats! or enable) check CodegenGlobals::has_instance() or the enabled state first.
Expected behavior: either store the value so that it takes effect when YJIT is enabled later (useful for the warmup-budget use case in [Feature #22236], where the budget may be set early in a boot script), or raise a Ruby exception, but not abort the process.
Reproduced in the ghcr.io/ruby/ruby:master Docker image (x86_64-linux).
Updated by znz (Kazuhiro NISHIYAMA) 20 days ago
- Backport changed from 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.3: DONTNEED, 3.4: DONTNEED, 4.0: DONTNEED
Updated by znz (Kazuhiro NISHIYAMA) 20 days ago
I checked the released branches.
RubyVM::YJIT.max_compile_time_ns= (and max_compile_time_ns / total_compile_time_ns) was added to master by c29739cb3 (2026-09-24, [Feature #22236]) and does not exist in ruby_3_3, ruby_3_4 or ruby_4_0 (yjit.rb on those branches has no max_compile_time_ns):
$ ruby -v
ruby 3.3.11 (2026-03-26 revision 1f2d15125a) [x86_64-linux]
$ ruby -e 'RubyVM::YJIT.max_compile_time_ns = 10'
-e:1:in `<main>': undefined method `max_compile_time_ns=' for module RubyVM::YJIT (NoMethodError)
The same NoMethodError is raised on 3.4.11 and 4.0.7 (ghcr.io/ruby/ruby:3.4 / :4.0).
I also called every other RubyVM::YJIT singleton method with YJIT not enabled on 3.3.11, 3.4.11, 4.0.7 and master (code_gc, enable, enabled?, exit_locations, log, log_enabled?, reset_stats!, runtime_stats, simulate_oom!, stats_enabled?, stats_string, trace_exit_locations_enabled? without arguments; disasm and insns_compiled with an ISeq; dump_exit_locations with a file name). None of them aborts (they return nil/false or raise an ArgumentError), so the crash is limited to the new setter on master. The backport field can be set to DONTNEED for 3.3, 3.4 and 4.0.
🤖 Generated with Claude Code
Updated by byroot (Jean Boussier) 20 days ago
- Assignee changed from jit to byroot (Jean Boussier)
Updated by byroot (Jean Boussier) 19 days ago
- Status changed from Open to Closed
Applied in changeset git|8264d60f975c49b0e0dd481a04ed7ee7b3e63dcf.
Fix RubyVM::YJIT.max_compile_time_ns= when YJIT is disabled
[Bug #22421]
Updated by satadru (Satadru Pramanik) 5 days ago
I'm seeing this error message building with --enable-yjit on our x86_64 4.0.9 builds on Chromebrew:
transdb.h updated linking miniruby
thread '' (41405) panicked at src/input_files.rs:1954:35: called Option::unwrap() on a None value stack backtrace:
0: 0x5fb9dbc3e571 - 1: 0x5fb9dbc53a3a - 2: 0x5fb9dbc43ddc -
3: 0x5fb9dbc1c246 - 4: 0x5fb9dbc368e1 - 5: 0x5fb9dbc36c42 -
6: 0x5fb9dbc1c324 - 7: 0x5fb9dbc15099 -
8: 0x5fb9dbc1ce6d - 9: 0x5fb9dbc5416c -
10: 0x5fb9dbc54132 - 11: 0x5fb9dbc53ee9 -
12: 0x5fb9db8ba26f - 13: 0x5fb9db8b6ab7 -
14: 0x5fb9db9047ff - 15: 0x5fb9db92840c -
16: 0x5fb9db9fe566 - 17: 0x5fb9db928633 - 18: 0x5fb9db9fe566 - 19: 0x5fb9db928633 -
20: 0x5fb9db9284d4 -
21: 0x5fb9db9284d4 -
22: 0x5fb9db9fe566 - 23: 0x5fb9db9a5ace - 24: 0x5fb9dbbea37f -
25: 0x5fb9dbbe99ed -
26: 0x5fb9dbbeb44a -
27: 0x5fb9dbbe6fed -
28: 0x5fb9dbc3dcd9 - 29: 0x7aa62c1e6f84 -
30: 0x7aa62c123b3f - __clone 31: 0x0 -
collect2: fatal error: ld terminated with signal 6 [Aborted], core dumped
Updated by byroot (Jean Boussier) 5 days ago
I don't know what cause your compilation failure, but this ticket is about a feature added in 4.1.0dev, so this isn't the right place to report it.