Bug #22327
openRubyVM::ZJIT.reset_stats! aborts the process (Rust panic) when ZJIT is not enabled
Description
RubyVM::ZJIT.reset_stats! aborts the whole process with a Rust panic when it is called while ZJIT is not enabled. The other stats methods (stats, stats_string, stats_enabled?) just return nil/false in the same situation, and RubyVM::YJIT.reset_stats! returns nil when YJIT is disabled, so I think reset_stats! should also be a no-op instead of crashing.
Reproduction¶
$ ruby -e 'p RubyVM::ZJIT.enabled?; RubyVM::ZJIT.reset_stats!; puts "after"'
false
thread '<unnamed>' (1) panicked at /usr/src/ruby/zjit/src/state.rs:200:13:
ZJITState::get_instance called when ZJIT is not enabled
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' (1) panicked at .../library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
(backtrace and bug report dump follow)
Aborted (core dumped)
$ echo $?
134
Expected: after is printed and the process exits with 0 (reset_stats! returns nil, as it does when ZJIT is enabled).
Reproduced with:
- ruby 4.1.0dev (2026-09-15T06:59:41Z master 0c3c61ca82) +PRISM [x86_64-linux] (
ghcr.io/ruby/ruby:master; panic atzjit/src/state.rs:200) - ruby 4.0.7 (2026-09-15 revision 229531a6cf) +PRISM [x86_64-linux] (
ghcr.io/ruby/ruby:4.0.7; panic atzjit/src/state.rs:168)
For comparison, these do not crash:
$ ruby -e 'p RubyVM::ZJIT.stats, RubyVM::ZJIT.stats_string, RubyVM::ZJIT.stats_enabled?'
nil
nil
false
$ ruby -e 'p RubyVM::YJIT.enabled?, RubyVM::YJIT.reset_stats!'
false
nil
$ ruby --zjit -e 'p RubyVM::ZJIT.enabled?, RubyVM::ZJIT.reset_stats!'
true
nil
Cause¶
rb_zjit_reset_stats_bang in zjit/src/stats.rs calls ZJITState::get_counters() etc. unconditionally, and ZJITState::get_instance panics when the state has not been initialized. rb_zjit_stats in the same file starts with if !zjit_enabled_p() { return Qnil; }; adding the same guard to rb_zjit_reset_stats_bang would fix this.
🤖 Generated with Claude Code
No data to display