Skip to content

Commit f1280b8

Browse files
committed
ZJIT: Reuse gen_push_frame
1 parent 5a3847f commit f1280b8

1 file changed

Lines changed: 36 additions & 49 deletions

File tree

zjit/src/codegen.rs

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -643,42 +643,6 @@ fn gen_ccall(asm: &mut Assembler, cfun: *const u8, args: Vec<Opnd>) -> lir::Opnd
643643
asm.ccall(cfun, args)
644644
}
645645

646-
/// Push a C frame for cfunc calls
647-
fn gen_push_cfunc_frame(asm: &mut Assembler, recv: Opnd, cme: *const rb_callable_method_entry_t, sp_offset: i32) {
648-
asm_comment!(asm, "push C frame");
649-
650-
let new_sp = asm.lea(Opnd::mem(64, SP, sp_offset * SIZEOF_VALUE_I32));
651-
// sp[-3]: cme
652-
asm.store(Opnd::mem(64, SP, (sp_offset - 3) * SIZEOF_VALUE_I32), VALUE::from(cme).into());
653-
// sp[-2]: block_handler (specval)
654-
asm.store(Opnd::mem(64, SP, (sp_offset - 2) * SIZEOF_VALUE_I32), VM_BLOCK_HANDLER_NONE.into());
655-
// sp[-1]: frame type (must be a valid FIXNUM)
656-
let frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
657-
asm.store(Opnd::mem(64, SP, (sp_offset - 1) * SIZEOF_VALUE_I32), frame_type.into());
658-
659-
fn cfp_opnd(offset: i32) -> Opnd {
660-
Opnd::mem(64, CFP, offset - (RUBY_SIZEOF_CONTROL_FRAME as i32))
661-
}
662-
663-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_PC), 0.into()); // C frames don't have a PC
664-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_SP), new_sp); // SP for new frame
665-
666-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_ISEQ), 0.into()); // C frames don't have an iseq
667-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_SELF), recv);
668-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_BLOCK_CODE), 0.into());
669-
670-
let ep = asm.sub(new_sp, SIZEOF_VALUE.into());
671-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_EP), ep);
672-
}
673-
674-
/// Pop a C frame after cfunc call
675-
fn gen_pop_cfunc_frame(asm: &mut Assembler) {
676-
asm_comment!(asm, "pop C frame");
677-
let new_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
678-
asm.mov(CFP, new_cfp);
679-
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
680-
}
681-
682646
/// Generate code for a variadic C function call
683647
/// func(int argc, VALUE *argv, VALUE recv)
684648
fn gen_ccall_variadic(
@@ -692,16 +656,22 @@ fn gen_ccall_variadic(
692656
) -> lir::Opnd {
693657
gen_prepare_non_leaf_call(jit, asm, state);
694658

695-
asm_comment!(asm, "pushing C frame for cme=0x{:x}", cme as usize);
696-
// Following YJIT: allocate 3 slots for frame metadata (cme, block_handler, frame_type)
697-
// The new frame's SP will be at current_stack_size + 3
698-
let sp_offset = state.stack().len() as i32 + 3;
699-
gen_push_cfunc_frame(asm, recv, cme, sp_offset);
659+
gen_push_frame(asm, args.len(), state, ControlFrame {
660+
recv,
661+
iseq: None,
662+
cme,
663+
frame_type: VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL,
664+
});
665+
666+
asm_comment!(asm, "switch to new SP register");
667+
let sp_offset = (state.stack().len() - args.len() + VM_ENV_DATA_SIZE.as_usize()) * SIZEOF_VALUE;
668+
let new_sp = asm.add(SP, sp_offset.into());
669+
asm.mov(SP, new_sp);
700670

701-
// Move to the new frame
702-
let new_cfp = asm.lea(Opnd::mem(64, CFP, -(RUBY_SIZEOF_CONTROL_FRAME as i32)));
671+
asm_comment!(asm, "switch to new CFP");
672+
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
703673
asm.mov(CFP, new_cfp);
704-
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), new_cfp);
674+
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
705675

706676
let argc = args.len();
707677

@@ -711,7 +681,14 @@ fn gen_ccall_variadic(
711681
let result = asm.ccall(cfun, vec![argc.into(), argv_ptr, recv]);
712682
gen_pop_opnds(asm, &args);
713683

714-
gen_pop_cfunc_frame(asm);
684+
asm_comment!(asm, "pop C frame");
685+
let new_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
686+
asm.mov(CFP, new_cfp);
687+
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
688+
689+
asm_comment!(asm, "restore SP register for the caller");
690+
let new_sp = asm.sub(SP, sp_offset.into());
691+
asm.mov(SP, new_sp);
715692

716693
result
717694
}
@@ -1126,7 +1103,7 @@ fn gen_send_without_block_direct(
11261103
// TODO: Lazily materialize caller frames on side exits or when needed
11271104
gen_push_frame(asm, args.len(), state, ControlFrame {
11281105
recv,
1129-
iseq,
1106+
iseq: Some(iseq),
11301107
cme,
11311108
frame_type: VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL,
11321109
});
@@ -1646,7 +1623,7 @@ fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameS
16461623
/// Frame metadata written by gen_push_frame()
16471624
struct ControlFrame {
16481625
recv: Opnd,
1649-
iseq: IseqPtr,
1626+
iseq: Option<IseqPtr>,
16501627
cme: *const rb_callable_method_entry_t,
16511628
frame_type: u32,
16521629
}
@@ -1658,7 +1635,11 @@ fn gen_push_frame(asm: &mut Assembler, argc: usize, state: &FrameState, frame: C
16581635
// See vm_push_frame() for details
16591636
asm_comment!(asm, "push cme, specval, frame type");
16601637
// ep[-2]: cref of cme
1661-
let local_size = unsafe { get_iseq_body_local_table_size(frame.iseq) } as i32;
1638+
let local_size = if let Some(iseq) = frame.iseq {
1639+
(unsafe { get_iseq_body_local_table_size(iseq) }) as i32
1640+
} else {
1641+
0
1642+
};
16621643
let ep_offset = state.stack().len() as i32 + local_size - argc as i32 + VM_ENV_DATA_SIZE as i32 - 1;
16631644
asm.store(Opnd::mem(64, SP, (ep_offset - 2) * SIZEOF_VALUE_I32), VALUE::from(frame.cme).into());
16641645
// ep[-1]: block_handler or prev EP
@@ -1673,9 +1654,15 @@ fn gen_push_frame(asm: &mut Assembler, argc: usize, state: &FrameState, frame: C
16731654
}
16741655

16751656
asm_comment!(asm, "push callee control frame");
1657+
1658+
let pc = if let Some(iseq) = frame.iseq {
1659+
VALUE::from(iseq).into()
1660+
} else {
1661+
0.into()
1662+
};
16761663
// cfp_opnd(RUBY_OFFSET_CFP_PC): written by the callee frame on side-exits or non-leaf calls
16771664
// cfp_opnd(RUBY_OFFSET_CFP_SP): written by the callee frame on side-exits or non-leaf calls
1678-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_ISEQ), VALUE::from(frame.iseq).into());
1665+
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_ISEQ), pc);
16791666
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_SELF), frame.recv);
16801667
let ep = asm.lea(Opnd::mem(64, SP, ep_offset * SIZEOF_VALUE_I32));
16811668
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_EP), ep);

0 commit comments

Comments
 (0)