Skip to content

Commit d5b8b93

Browse files
committed
ZJIT: Reuse gen_push_frame
1 parent 7ed41f1 commit d5b8b93

1 file changed

Lines changed: 37 additions & 54 deletions

File tree

‎zjit/src/codegen.rs‎

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -640,42 +640,6 @@ fn gen_ccall(asm: &mut Assembler, cfun: *const u8, args: Vec<Opnd>) -> lir::Opnd
640640
asm.ccall(cfun, args)
641641
}
642642

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

692-
asm_comment!(asm, "pushing C frame for cme=0x{:x}", cme as usize);
693-
// Following YJIT: allocate 3 slots for frame metadata (cme, block_handler, frame_type)
694-
// The new frame's SP will be at current_stack_size + 3
695-
let sp_offset = state.stack().len() as i32 + 3;
696-
gen_push_cfunc_frame(asm, recv, cme, sp_offset);
697-
698-
// Move to the new frame
699-
let new_cfp = asm.lea(Opnd::mem(64, CFP, -(RUBY_SIZEOF_CONTROL_FRAME as i32)));
700-
asm.mov(CFP, new_cfp);
701-
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), new_cfp);
656+
gen_push_frame(asm, args.len(), state, ControlFrame {
657+
recv,
658+
iseq: None,
659+
cme,
660+
frame_type: VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL,
661+
});
702662

703-
let argc = args.len();
663+
asm_comment!(asm, "switch to new SP register");
664+
let sp_offset = (state.stack().len() - args.len() + VM_ENV_DATA_SIZE.as_usize()) * SIZEOF_VALUE;
665+
let new_sp = asm.add(SP, sp_offset.into());
666+
asm.mov(SP, new_sp);
704667

705-
asm_comment!(asm, "call variadic cfunc: argc={}", argc);
668+
asm_comment!(asm, "switch to new CFP");
669+
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
670+
asm.mov(CFP, new_cfp);
671+
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
706672

707673
let argv_ptr = gen_push_opnds(jit, asm, &args);
708-
let result = asm.ccall(cfun, vec![argc.into(), argv_ptr, recv]);
674+
let result = asm.ccall(cfun, vec![args.len().into(), argv_ptr, recv]);
709675
gen_pop_opnds(asm, &args);
710676

711-
gen_pop_cfunc_frame(asm);
677+
asm_comment!(asm, "pop C frame");
678+
let new_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
679+
asm.mov(CFP, new_cfp);
680+
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
681+
682+
asm_comment!(asm, "restore SP register for the caller");
683+
let new_sp = asm.sub(SP, sp_offset.into());
684+
asm.mov(SP, new_sp);
712685

713686
result
714687
}
@@ -1129,7 +1102,7 @@ fn gen_send_without_block_direct(
11291102
// TODO: Lazily materialize caller frames on side exits or when needed
11301103
gen_push_frame(asm, args.len(), state, ControlFrame {
11311104
recv,
1132-
iseq,
1105+
iseq: Some(iseq),
11331106
cme,
11341107
frame_type: VM_FRAME_MAGIC_METHOD | VM_ENV_FLAG_LOCAL,
11351108
});
@@ -1649,7 +1622,7 @@ fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameS
16491622
/// Frame metadata written by gen_push_frame()
16501623
struct ControlFrame {
16511624
recv: Opnd,
1652-
iseq: IseqPtr,
1625+
iseq: Option<IseqPtr>,
16531626
cme: *const rb_callable_method_entry_t,
16541627
frame_type: u32,
16551628
}
@@ -1661,7 +1634,11 @@ fn gen_push_frame(asm: &mut Assembler, argc: usize, state: &FrameState, frame: C
16611634
// See vm_push_frame() for details
16621635
asm_comment!(asm, "push cme, specval, frame type");
16631636
// ep[-2]: cref of cme
1664-
let local_size = unsafe { get_iseq_body_local_table_size(frame.iseq) } as i32;
1637+
let local_size = if let Some(iseq) = frame.iseq {
1638+
(unsafe { get_iseq_body_local_table_size(iseq) }) as i32
1639+
} else {
1640+
0
1641+
};
16651642
let ep_offset = state.stack().len() as i32 + local_size - argc as i32 + VM_ENV_DATA_SIZE as i32 - 1;
16661643
asm.store(Opnd::mem(64, SP, (ep_offset - 2) * SIZEOF_VALUE_I32), VALUE::from(frame.cme).into());
16671644
// ep[-1]: block_handler or prev EP
@@ -1676,9 +1653,15 @@ fn gen_push_frame(asm: &mut Assembler, argc: usize, state: &FrameState, frame: C
16761653
}
16771654

16781655
asm_comment!(asm, "push callee control frame");
1656+
1657+
let pc = if let Some(iseq) = frame.iseq {
1658+
VALUE::from(iseq).into()
1659+
} else {
1660+
0.into()
1661+
};
16791662
// cfp_opnd(RUBY_OFFSET_CFP_PC): written by the callee frame on side-exits or non-leaf calls
16801663
// cfp_opnd(RUBY_OFFSET_CFP_SP): written by the callee frame on side-exits or non-leaf calls
1681-
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_ISEQ), VALUE::from(frame.iseq).into());
1664+
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_ISEQ), pc);
16821665
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_SELF), frame.recv);
16831666
let ep = asm.lea(Opnd::mem(64, SP, ep_offset * SIZEOF_VALUE_I32));
16841667
asm.mov(cfp_opnd(RUBY_OFFSET_CFP_EP), ep);

0 commit comments

Comments
 (0)