summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashi.kokubun@shopify.com>2025-08-29 11:43:33 -0700
committerGitHub <noreply@github.com>2025-08-29 11:43:33 -0700
commit39f3cab80d7b469793a1a3cf091ed875c54c3c86 (patch)
tree9df776d3a6841ea873db9ebd257b8775531a662d
parent99bf47ab8c3fc4332b7324310615af147a4da560 (diff)
YJIT: Stop sharing rb_vm_send among different instructions (#14393)
-rw-r--r--vm_insnhelper.c27
-rw-r--r--yjit/src/codegen.rs19
2 files changed, 32 insertions, 14 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 0fb4d086b7..eee20cd9d4 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -6095,25 +6095,26 @@ VALUE
rb_vm_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
{
stack_check(ec);
+ VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, false);
+ VALUE val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
+ VM_EXEC(ec, val);
+ return val;
+}
+
+VALUE
+rb_vm_sendforward(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA cd, ISEQ blockiseq)
+{
+ stack_check(ec);
struct rb_forwarding_call_data adjusted_cd;
struct rb_callinfo adjusted_ci;
- VALUE bh;
- VALUE val;
-
- if (vm_ci_flag(cd->ci) & VM_CALL_FORWARDING) {
- bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, false, &adjusted_cd, &adjusted_ci);
+ VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, false, &adjusted_cd, &adjusted_ci);
- val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
+ VALUE val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
- if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
- RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
- }
- }
- else {
- bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, false);
- val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
+ if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
+ RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
}
VM_EXEC(ec, val);
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 9e9759e781..8b472efdfd 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -9564,7 +9564,24 @@ fn gen_sendforward(
jit: &mut JITState,
asm: &mut Assembler,
) -> Option<CodegenStatus> {
- return gen_send(jit, asm);
+ // Generate specialized code if possible
+ let cd = jit.get_arg(0).as_ptr();
+ let block = jit.get_arg(1).as_optional_ptr().map(|iseq| BlockHandler::BlockISeq(iseq));
+ if let Some(status) = perf_call! { gen_send_general(jit, asm, cd, block) } {
+ return Some(status);
+ }
+
+ // Otherwise, fallback to dynamic dispatch using the interpreter's implementation of sendforward
+ let blockiseq = jit.get_arg(1).as_iseq();
+ gen_send_dynamic(jit, asm, cd, unsafe { rb_yjit_sendish_sp_pops((*cd).ci) }, |asm| {
+ extern "C" {
+ fn rb_vm_sendforward(ec: EcPtr, cfp: CfpPtr, cd: VALUE, blockiseq: IseqPtr) -> VALUE;
+ }
+ asm.ccall(
+ rb_vm_sendforward as *const u8,
+ vec![EC, CFP, (cd as usize).into(), VALUE(blockiseq as usize).into()],
+ )
+ })
}
fn gen_invokeblock(