Skip to content

Commit df7d981

Browse files
authored
ZJIT: Prepare non-leaf calls for SetGlobal (#14197)
When trace_var is used, setting a global variable can cause exceptions to be raised. We need to prepare for that.
1 parent 1afc07e commit df7d981

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

test/ruby/test_zjit.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ def test(n) = n
6161
}
6262
end
6363

64+
def test_setglobal
65+
assert_compiles '1', %q{
66+
def test
67+
$a = 1
68+
$a
69+
end
70+
71+
test
72+
}, insns: [:setglobal]
73+
end
74+
75+
def test_setglobal_with_trace_var_exception
76+
assert_compiles '"rescued"', %q{
77+
def test
78+
$a = 1
79+
rescue
80+
"rescued"
81+
end
82+
83+
trace_var(:$a) { raise }
84+
test
85+
}, insns: [:setglobal]
86+
end
87+
6488
def test_setlocal
6589
assert_compiles '3', %q{
6690
def test(n)

zjit/src/codegen.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
367367
Insn::PatchPoint { invariant, state } => return gen_patch_point(jit, asm, invariant, &function.frame_state(*state)),
368368
Insn::CCall { cfun, args, name: _, return_type: _, elidable: _ } => gen_ccall(asm, *cfun, opnds!(args))?,
369369
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
370-
Insn::SetGlobal { id, val, state: _ } => return Some(gen_setglobal(asm, *id, opnd!(val))),
370+
Insn::SetGlobal { id, val, state } => return gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state)),
371371
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
372372
&Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level)?,
373373
Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, opnd!(val), *ep_offset, *level),
@@ -592,8 +592,12 @@ fn gen_getglobal(asm: &mut Assembler, id: ID) -> Opnd {
592592
}
593593

594594
/// Set global variables
595-
fn gen_setglobal(asm: &mut Assembler, id: ID, val: Opnd) {
595+
fn gen_setglobal(jit: &mut JITState, asm: &mut Assembler, id: ID, val: Opnd, state: &FrameState) -> Option<()> {
596+
// When trace_var is used, setting a global variable can cause exceptions
597+
gen_prepare_non_leaf_call(jit, asm, state)?;
598+
596599
asm_ccall!(asm, rb_gvar_set, id.0.into(), val);
600+
Some(())
597601
}
598602

599603
/// Side-exit into the interpreter

0 commit comments

Comments
 (0)