diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index fdcee3cafd858e..299600eef95d53 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -999,6 +999,26 @@ def test_require_rubygems_with_auto_compact }, call_threshold: 2 end + def test_profile_under_nested_jit_call + assert_compiles '[nil, nil, 3]', %q{ + def profile + 1 + 2 + end + + def jit_call(flag) + if flag + profile + end + end + + def entry(flag) + jit_call(flag) + end + + [entry(false), entry(false), entry(true)] + }, call_threshold: 2 + end + def test_bop_redefinition assert_runs '[3, :+, 100]', %q{ def test diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs index e5453e4d554b67..94c53569b4e95c 100644 --- a/zjit/src/backend/lir.rs +++ b/zjit/src/backend/lir.rs @@ -270,6 +270,14 @@ impl From for Opnd { } } +/// Set of things we need to restore for side exits. +#[derive(Clone, Debug)] +pub struct SideExitContext { + pub pc: *const VALUE, + pub stack: Vec, + pub locals: Vec, +} + /// Branch target (something that we can jump to) /// for branch instructions #[derive(Clone, Debug)] @@ -281,12 +289,14 @@ pub enum Target Label(Label), /// Side exit to the interpreter SideExit { - pc: *const VALUE, - stack: Vec, - locals: Vec, - c_stack_bytes: usize, + /// Context to restore on regular side exits. None for side exits right + /// after JIT-to-JIT calls because we restore them before the JIT call. + context: Option, + /// We use this to enrich asm comments. reason: SideExitReason, - // Some if the side exit should write this label. We use it for patch points. + /// The number of bytes we need to adjust the C stack pointer by. + c_stack_bytes: usize, + /// Some if the side exit should write this label. We use it for patch points. label: Option