Skip to content

Commit 8dd7300

Browse files
authored
ZJIT: Replace Option<i32> with Recompile enum for side exit recompilation (ruby#16665)
1 parent 70e8654 commit 8dd7300

3 files changed

Lines changed: 26 additions & 20 deletions

File tree

zjit/src/backend/lir.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -558,14 +558,11 @@ pub struct SideExit {
558558
}
559559

560560
/// Arguments for the recompile callback on side exit.
561-
/// Used for both no-profile sends (argc >= 0) and shape guard failures (argc = -1).
562561
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
563562
pub struct SideExitRecompile {
564563
pub iseq: Opnd,
565564
pub insn_idx: u32,
566-
/// Number of arguments (not including receiver) for send profiling.
567-
/// -1 means profile self from CFP for shape guard exits.
568-
pub argc: i32,
565+
pub strategy: hir::Recompile,
569566
}
570567

571568
/// Branch target (something that we can jump to)
@@ -2687,7 +2684,10 @@ impl Assembler
26872684
EC,
26882685
recompile.iseq,
26892686
Opnd::UImm(recompile.insn_idx as u64),
2690-
Opnd::Imm(recompile.argc as i64)
2687+
Opnd::Imm(match recompile.strategy {
2688+
hir::Recompile::ProfileSend { argc } => argc as i64,
2689+
hir::Recompile::ProfileSelf => -1,
2690+
})
26912691
);
26922692
}
26932693
compile_exit_return(asm);

zjit/src/codegen.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::stats::{counter_ptr, with_time_stat, Counter, Counter::{compile_time_
2121
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
2222
use crate::backend::lir::{self, Assembler, C_ARG_OPNDS, C_RET_OPND, CFP, EC, NATIVE_STACK_PTR, Opnd, SP, SideExit, SideExitRecompile, Target, asm_ccall, asm_comment};
2323
use crate::hir::{iseq_to_hir, BlockId, Invariant, RangeType, SideExitReason::{self, *}, SpecialBackrefSymbol, SpecialObjectType};
24-
use crate::hir::{BlockHandler, Const, FrameState, Function, Insn, InsnId, SendFallbackReason};
24+
use crate::hir::{BlockHandler, Const, FrameState, Function, Insn, InsnId, Recompile, SendFallbackReason};
2525
use crate::hir_type::{types, Type};
2626
use crate::options::{get_option, PerfMap};
2727
use crate::cast::IntoUsize;
@@ -1238,7 +1238,7 @@ fn gen_setglobal(jit: &mut JITState, asm: &mut Assembler, id: ID, val: Opnd, sta
12381238
}
12391239

12401240
/// Side-exit into the interpreter
1241-
fn gen_side_exit(jit: &mut JITState, asm: &mut Assembler, reason: &SideExitReason, recompile: Option<i32>, state: &FrameState) {
1241+
fn gen_side_exit(jit: &mut JITState, asm: &mut Assembler, reason: &SideExitReason, recompile: Option<Recompile>, state: &FrameState) {
12421242
asm.jmp(side_exit_with_recompile(jit, state, *reason, recompile));
12431243
}
12441244

@@ -2631,7 +2631,7 @@ fn gen_guard_type_not(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, g
26312631
}
26322632

26332633
/// Compile an identity check with a side exit
2634-
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: crate::hir::Const, reason: SideExitReason, recompile: Option<i32>, state: &FrameState) -> lir::Opnd {
2634+
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: crate::hir::Const, reason: SideExitReason, recompile: Option<Recompile>, state: &FrameState) -> lir::Opnd {
26352635
if matches!(reason, SideExitReason::GuardShape(_) ) {
26362636
gen_incr_counter(asm, Counter::guard_shape_count);
26372637
}
@@ -2977,13 +2977,12 @@ fn side_exit(jit: &JITState, state: &FrameState, reason: SideExitReason) -> Targ
29772977
}
29782978

29792979
/// Build a Target::SideExit that optionally triggers exit_recompile on the exit path.
2980-
/// When `recompile` is Some(argc), the side exit calls exit_recompile with that argc.
2981-
fn side_exit_with_recompile(jit: &JITState, state: &FrameState, reason: SideExitReason, recompile: Option<i32>) -> Target {
2980+
fn side_exit_with_recompile(jit: &JITState, state: &FrameState, reason: SideExitReason, recompile: Option<Recompile>) -> Target {
29822981
let mut exit = build_side_exit(jit, state);
2983-
exit.recompile = recompile.map(|argc| SideExitRecompile {
2982+
exit.recompile = recompile.map(|strategy| SideExitRecompile {
29842983
iseq: Opnd::Value(VALUE::from(jit.iseq)),
29852984
insn_idx: state.insn_idx() as u32,
2986-
argc,
2985+
strategy,
29872986
});
29882987
Target::SideExit { exit, reason }
29892988
}

zjit/src/hir.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,15 @@ pub enum SideExitReason {
540540
InvokeBlockNotIfunc,
541541
}
542542

543+
/// Controls how a side exit triggers recompilation.
544+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
545+
pub enum Recompile {
546+
/// Profile receiver + arguments from the stack (for sends without profile data).
547+
ProfileSend { argc: i32 },
548+
/// Profile self from the CFP (for shape guard failures).
549+
ProfileSelf,
550+
}
551+
543552
#[derive(Debug, Clone, Copy)]
544553
pub enum MethodType {
545554
Iseq,
@@ -1090,9 +1099,7 @@ pub enum Insn {
10901099
GuardType { val: InsnId, guard_type: Type, state: InsnId },
10911100
GuardTypeNot { val: InsnId, guard_type: Type, state: InsnId },
10921101
/// Side-exit if val is not the expected Const.
1093-
/// `recompile`: if Some(argc), the side exit triggers exit_recompile.
1094-
/// argc >= 0 profiles receiver + args from stack; argc == -1 profiles self from CFP.
1095-
GuardBitEquals { val: InsnId, expected: Const, reason: SideExitReason, state: InsnId, recompile: Option<i32> },
1102+
GuardBitEquals { val: InsnId, expected: Const, reason: SideExitReason, state: InsnId, recompile: Option<Recompile> },
10961103
/// Side-exit if (val & mask) == 0
10971104
GuardAnyBitSet { val: InsnId, mask: Const, mask_name: Option<ID>, reason: SideExitReason, state: InsnId },
10981105
/// Side-exit if (val & mask) != 0
@@ -1107,9 +1114,9 @@ pub enum Insn {
11071114
PatchPoint { invariant: Invariant, state: InsnId },
11081115

11091116
/// Side-exit into the interpreter.
1110-
/// If `recompile` is set, the side exit will profile the send and invalidate the ISEQ
1117+
/// If recompile is not None, the side exit will profile and invalidate the ISEQ
11111118
/// so that it gets recompiled with the new profile data.
1112-
SideExit { state: InsnId, reason: SideExitReason, recompile: Option<i32> },
1119+
SideExit { state: InsnId, reason: SideExitReason, recompile: Option<Recompile> },
11131120

11141121
/// Increment a counter in ZJIT stats
11151122
IncrCounter(Counter),
@@ -4392,7 +4399,7 @@ impl Function {
43924399
})
43934400
}
43944401

4395-
fn guard_shape(&mut self, block: BlockId, val: InsnId, expected: ShapeId, state: InsnId, recompile: Option<i32>) -> InsnId {
4402+
fn guard_shape(&mut self, block: BlockId, val: InsnId, expected: ShapeId, state: InsnId, recompile: Option<Recompile>) -> InsnId {
43964403
self.push_insn(block, Insn::GuardBitEquals {
43974404
val,
43984405
expected: Const::CShape(expected),
@@ -4543,7 +4550,7 @@ impl Function {
45434550
}
45444551
let self_val = self.load_ivar_guard_type(block, self_val, recv_type, state);
45454552
let shape = self.load_shape(block, self_val);
4546-
self.guard_shape(block, shape, recv_type.shape(), state, Some(-1));
4553+
self.guard_shape(block, shape, recv_type.shape(), state, Some(Recompile::ProfileSelf));
45474554
let replacement = self.load_ivar(block, self_val, recv_type, id, state);
45484555
self.make_equal_to(insn_id, replacement);
45494556
}
@@ -5178,7 +5185,7 @@ impl Function {
51785185
match self.find(insn_id) {
51795186
Insn::Send { cd, state, reason: SendFallbackReason::SendWithoutBlockNoProfiles | SendFallbackReason::SendNoProfiles, .. } => {
51805187
let argc = unsafe { vm_ci_argc((*cd).ci) } as i32;
5181-
self.push_insn(block, Insn::SideExit { state, reason: SideExitReason::NoProfileSend, recompile: Some(argc) });
5188+
self.push_insn(block, Insn::SideExit { state, reason: SideExitReason::NoProfileSend, recompile: Some(Recompile::ProfileSend { argc }) });
51825189
// SideExit is a terminator; don't add remaining instructions
51835190
break;
51845191
}

0 commit comments

Comments
 (0)