From eead83160bcc5f49706e05669e5a7e2620b9b605 Mon Sep 17 00:00:00 2001 From: Daniel Colson Date: Fri, 16 May 2025 13:31:43 -0400 Subject: [PATCH] Prevent enabling yjit when zjit enabled (GH-13358) `ruby --yjit --zjit` already warns and exits, but it was still possible to enable both with `ruby --zjit -e 'RubyVM:YJIT.enable`. This commit prevents that with a warning and an early return. (We could also exit, but that seems a bit unfriendly once we're already running the program.) Co-authored-by: ywenc --- common.mk | 1 + test/ruby/test_yjit.rb | 5 +++++ yjit.c | 1 + yjit.rb | 5 +++++ zjit.h | 1 + 5 files changed, 13 insertions(+) diff --git a/common.mk b/common.mk index 1eaeb31d04..e8c4e8d40e 100644 --- a/common.mk +++ b/common.mk @@ -21737,6 +21737,7 @@ yjit.$(OBJEXT): {$(VPATH)}vm_sync.h yjit.$(OBJEXT): {$(VPATH)}yjit.c yjit.$(OBJEXT): {$(VPATH)}yjit.h yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc +yjit.$(OBJEXT): {$(VPATH)}zjit.h zjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h zjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h zjit.$(OBJEXT): $(CCAN_DIR)/list/list.h diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 7c0524354b..25399d1e62 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -166,6 +166,11 @@ class TestYJIT < Test::Unit::TestCase end end + if JITSupport.zjit_supported? + def test_yjit_enable_with_zjit_enabled + assert_in_out_err(['--zjit'], 'puts RubyVM::YJIT.enable', ['false'], ['Only one JIT can be enabled at the same time.']) + end + end def test_yjit_stats_and_v_no_error _stdout, stderr, _status = invoke_ruby(%w(-v --yjit-stats), '', true, true) diff --git a/yjit.c b/yjit.c index 253b1ec67e..4fa6bf8ce8 100644 --- a/yjit.c +++ b/yjit.c @@ -29,6 +29,7 @@ #include "iseq.h" #include "ruby/debug.h" #include "internal/cont.h" +#include "zjit.h" // For mmapp(), sysconf() #ifndef _WIN32 diff --git a/yjit.rb b/yjit.rb index 045fea2656..e8ba3cdd28 100644 --- a/yjit.rb +++ b/yjit.rb @@ -48,6 +48,11 @@ module RubyVM::YJIT def self.enable(stats: false, log: false, mem_size: nil, call_threshold: nil) return false if enabled? + if Primitive.cexpr! 'RBOOL(rb_zjit_enabled_p)' + warn("Only one JIT can be enabled at the same time.") + return false + end + if mem_size raise ArgumentError, "mem_size must be a Integer" unless mem_size.is_a?(Integer) raise ArgumentError, "mem_size must be between 1 and 2048 MB" unless (1..2048).include?(mem_size) diff --git a/zjit.h b/zjit.h index b4a89d308a..ee9d15468d 100644 --- a/zjit.h +++ b/zjit.h @@ -14,6 +14,7 @@ void rb_zjit_profile_enable(const rb_iseq_t *iseq); void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop); void rb_zjit_invalidate_ep_is_bp(const rb_iseq_t *iseq); #else +#define rb_zjit_enabled_p false static inline void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception) {} static inline void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec) {} static inline void rb_zjit_profile_enable(const rb_iseq_t *iseq) {}