summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Lo <stan.lo@shopify.com>2025-08-28 18:50:22 +0100
committerGitHub <noreply@github.com>2025-08-28 17:50:22 +0000
commitfa3c23eb811c7bee7c9ed945c8f12cb40ecd9b6a (patch)
tree2265cd0170060f071aca0827bb0e15a1bb5d3b6d
parentb47ea34a9b9e602e70bb69478c4abd2d9f1651d0 (diff)
ZJIT: Prepare getglobal for non-leaf call (#14387)
Depending on the user's warning level, getting certain global variables may lead to calling `Warning#warn`, which can be redefined by the user. This fixes another `bootstraptest/test_yjit.rb` failure.
-rw-r--r--test/ruby/test_zjit.rb21
-rw-r--r--zjit/src/codegen.rs7
2 files changed, 26 insertions, 2 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index e2a0120eb0..3ff1392ed7 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -78,6 +78,27 @@ class TestZJIT < Test::Unit::TestCase
}
end
+ def test_getglobal_with_warning
+ assert_compiles('"rescued"', %q{
+ Warning[:deprecated] = true
+
+ module Warning
+ def warn(message)
+ raise
+ end
+ end
+
+ def test
+ $=
+ rescue
+ "rescued"
+ end
+
+ $VERBOSE = true
+ test
+ }, insns: [:getglobal])
+ end
+
def test_setglobal
assert_compiles '1', %q{
def test
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index 023498e3be..6c55b3fb5d 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -384,7 +384,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::CCall { cfun, args, name: _, return_type: _, elidable: _ } => gen_ccall(asm, *cfun, opnds!(args)),
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
Insn::SetGlobal { id, val, state } => no_output!(gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state))),
- Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
+ Insn::GetGlobal { id, state } => gen_getglobal(jit, asm, *id, &function.frame_state(*state)),
&Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level),
&Insn::SetLocal { val, ep_offset, level } => no_output!(gen_setlocal_with_ep(asm, opnd!(val), function.type_of(val), ep_offset, level)),
Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state)),
@@ -609,7 +609,10 @@ fn gen_setivar(asm: &mut Assembler, recv: Opnd, id: ID, val: Opnd) {
}
/// Look up global variables
-fn gen_getglobal(asm: &mut Assembler, id: ID) -> Opnd {
+fn gen_getglobal(jit: &mut JITState, asm: &mut Assembler, id: ID, state: &FrameState) -> Opnd {
+ // `Warning` module's method `warn` can be called when reading certain global variables
+ gen_prepare_non_leaf_call(jit, asm, state);
+
asm_ccall!(asm, rb_gvar_get, id.0.into())
}