summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2025-09-02 11:58:42 -0700
committerGitHub <noreply@github.com>2025-09-02 18:58:42 +0000
commite0a7da93d25cf9a4fced323ce3344fc390b59ad7 (patch)
tree491ee9642fde2d960975736998ea597b856fe0ab
parentbdaff44bae6cd6e5675a37b19341d132b3881bb7 (diff)
ZJIT: Rename gen_save_pc to gen_prepare_call_with_gc (#14427)
-rw-r--r--zjit/src/codegen.rs27
1 files changed, 11 insertions, 16 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index 66ad5ba3a9..de13d306c1 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -943,7 +943,7 @@ fn gen_send(
gen_incr_counter(asm, Counter::dynamic_send_count);
// Save PC and SP
- gen_save_pc(asm, state);
+ gen_prepare_call_with_gc(asm, state);
gen_save_sp(asm, state.stack().len());
// Spill locals and stack
@@ -979,7 +979,7 @@ fn gen_send_without_block(
asm_comment!(asm, "spill frame state");
// Save PC and SP
- gen_save_pc(asm, state);
+ gen_prepare_call_with_gc(asm, state);
gen_save_sp(asm, state.stack().len());
// Spill locals and stack
@@ -1012,7 +1012,7 @@ fn gen_send_without_block_direct(
state: &FrameState,
) -> lir::Opnd {
// Save cfp->pc and cfp->sp for the caller frame
- gen_save_pc(asm, state);
+ gen_prepare_call_with_gc(asm, state);
gen_save_sp(asm, state.stack().len() - args.len() - 1); // -1 for receiver
gen_spill_locals(jit, asm, state);
@@ -1363,9 +1363,13 @@ fn gen_incr_counter(asm: &mut Assembler, counter: Counter) {
}
}
-/// Save the incremented PC on the CFP.
-/// This is necessary when callees can raise or allocate.
-fn gen_save_pc(asm: &mut Assembler, state: &FrameState) {
+/// Save the current PC on the CFP as a preparation for calling a C function
+/// that may allocate objects and trigger GC. Use gen_prepare_non_leaf_call()
+/// if it may raise exceptions or call arbitrary methods.
+///
+/// Unlike YJIT, we don't need to save the stack slots to protect them from GC
+/// because the backend spills all live registers onto the C stack on CCall.
+fn gen_prepare_call_with_gc(asm: &mut Assembler, state: &FrameState) {
let opcode: usize = state.get_opcode().try_into().unwrap();
let next_pc: *const VALUE = unsafe { state.pc.offset(insn_len(opcode) as isize) };
@@ -1409,7 +1413,7 @@ fn gen_spill_stack(jit: &JITState, asm: &mut Assembler, state: &FrameState) {
fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameState) {
// TODO: Lazily materialize caller frames when needed
// Save PC for backtraces and allocation tracing
- gen_save_pc(asm, state);
+ gen_prepare_call_with_gc(asm, state);
// Save SP and spill the virtual stack in case it raises an exception
// and the interpreter uses the stack for handling the exception
@@ -1420,15 +1424,6 @@ fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameS
gen_spill_locals(jit, asm, state);
}
-/// Prepare for calling a C function that may allocate objects and trigger GC.
-/// Use gen_prepare_non_leaf_call() if it may also call an arbitrary method.
-fn gen_prepare_call_with_gc(asm: &mut Assembler, state: &FrameState) {
- // Save PC for allocation tracing
- gen_save_pc(asm, state);
- // Unlike YJIT, we don't need to save the stack to protect them from GC
- // because the backend spills all live registers onto the C stack on asm.ccall().
-}
-
/// Frame metadata written by gen_push_frame()
struct ControlFrame {
recv: Opnd,