From: "znz (Kazuhiro NISHIYAMA) via ruby-core" Date: 2026-10-12T04:59:30+00:00 Subject: [ruby-core:127073] [Ruby Bug#22427] `--enable=zjit` does not enable ZJIT Issue #22427 has been reported by znz (Kazuhiro NISHIYAMA). ---------------------------------------- Bug #22427: `--enable=zjit` does not enable ZJIT https://bugs.ruby-lang.org/issues/22427 * Author: znz (Kazuhiro NISHIYAMA) * Status: Open * Assignee: jit * ruby -v: ruby 4.1.0dev (2026-10-11T13:56:36Z v4.1.0-preview1 2d08b5f42f) +PRISM [x86_64-linux] * Backport: 3.3: DONTNEED, 3.4: DONTNEED, 4.0: REQUIRED ---------------------------------------- `ruby --help` lists `zjit` under "Features" (`zjit Method-based JIT compiler (default: disabled).`), but `--enable=zjit` alone does not enable ZJIT, while `--enable=yjit` does enable YJIT. ``` $ ruby -v ruby 4.0.7 (2026-09-15 revision 229531a6cf) +PRISM [x86_64-linux] $ ruby --enable=yjit -v ruby 4.0.7 (2026-09-15 revision 229531a6cf) +YJIT +PRISM [x86_64-linux] $ ruby --enable=yjit -e 'p RubyVM::YJIT.enabled?' true $ ruby --enable=zjit -v ruby 4.0.7 (2026-09-15 revision 229531a6cf) +PRISM [x86_64-linux] $ ruby --enable=zjit -e 'p RubyVM::ZJIT.enabled?' false $ ruby --zjit -v ruby 4.0.7 (2026-09-15 revision 229531a6cf) +ZJIT +PRISM [x86_64-linux] $ ruby --zjit -e 'p RubyVM::ZJIT.enabled?' true ``` The same happens with `--enable-zjit` and with `RUBYOPT=--enable=zjit`. ZJIT is enabled as soon as any `--zjit-*` option is added (for example `--enable=zjit --zjit-call-threshold=30`), and also with `RUBY_ZJIT_ENABLE=1`. The cause is in `ruby.c`. `--enable=zjit` only sets the feature bit. Later, `opt->zjit` is computed as ```c #if USE_ZJIT if (FEATURE_SET_P(opt->features, zjit)) { bool rb_zjit_option_enable(void); opt->zjit = rb_zjit_option_enable(); // set opt->zjit for Init_ruby_description() and calling rb_zjit_init() } #endif ``` and `rb_zjit_option_enable()` (zjit/src/options.rs) returns true only when the Rust-side `OPTIONS` has been initialized (`OPTIONS.as_ref().is_some_and(|opts| !opts.disable)`). `OPTIONS` is initialized by `rb_zjit_prepare_options()`, which is called for `--zjit*` (through `setup_zjit_options()`) and for `RUBY_ZJIT_ENABLE`, but not for `--enable=zjit`. So `opt->zjit` stays false and `rb_zjit_init(false)` is called. The YJIT counterpart, `rb_yjit_option_disable()`, has no such dependency, which is why `--enable=yjit` works. Judging from the diff, this was introduced by commit:f84bbb4238 ("ZJIT: add support for lazy `RubyVM::ZJIT.enable`", 2025-11-17, included in 4.0.0). Before it, the code was ```c if (FEATURE_SET_P(opt->features, zjit) && !opt->zjit) { extern void rb_zjit_prepare_options(void); rb_zjit_prepare_options(); opt->zjit = true; } ``` A possible fix is to prepare the options when the feature bit is set, before asking whether ZJIT should be enabled: ```c #if USE_ZJIT if (FEATURE_SET_P(opt->features, zjit)) { // --enable=zjit sets the feature bit without going through setup_zjit_options() extern void rb_zjit_prepare_options(void); rb_zjit_prepare_options(); bool rb_zjit_option_enable(void); opt->zjit = rb_zjit_option_enable(); } #endif ``` `rb_zjit_prepare_options()` already handles the already-initialized case, so `--zjit-*` options and `--zjit-disable` keep working. test/ruby/test_rubyoptions.rb does not exercise `--enable=yjit` or `--enable=zjit`, so a test for the `--enable=` form would also help. Reproduced in the `ghcr.io/ruby/ruby:4.0` (4.0.7) and `ghcr.io/ruby/ruby:master` (4.1.0dev 2d08b5f42f) Docker images (x86_64-linux). -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/