From cc97a270080d2c6eb9dbdd2b9793ab549b6bb44d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 3 Jun 2024 14:20:04 -0700 Subject: Add two new instructions for forwarding calls This commit adds `sendforward` and `invokesuperforward` for forwarding parameters to calls Co-authored-by: Matt Valentine-House --- vm_args.c | 60 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'vm_args.c') diff --git a/vm_args.c b/vm_args.c index 6d31187ea4..4d35b00e4a 100644 --- a/vm_args.c +++ b/vm_args.c @@ -1061,52 +1061,54 @@ vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t * static void vm_adjust_stack_forwarding(const struct rb_execution_context_struct *ec, struct rb_control_frame_struct *cfp, CALL_INFO callers_info, VALUE splat); static VALUE -vm_caller_setup_args(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, +vm_caller_setup_fwd_args(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, CALL_DATA *cd, const rb_iseq_t *blockiseq, const int is_super, struct rb_forwarding_call_data *adjusted_cd, struct rb_callinfo *adjusted_ci) { CALL_INFO site_ci = (*cd)->ci; VALUE bh = Qundef; - if (vm_ci_flag(site_ci) & VM_CALL_FORWARDING) { - RUBY_ASSERT(ISEQ_BODY(ISEQ_BODY(GET_ISEQ())->local_iseq)->param.flags.forwardable); - CALL_INFO caller_ci = (CALL_INFO)TOPN(0); + RUBY_ASSERT(ISEQ_BODY(ISEQ_BODY(GET_ISEQ())->local_iseq)->param.flags.forwardable); + CALL_INFO caller_ci = (CALL_INFO)TOPN(0); - unsigned int forwarding_argc = vm_ci_argc(site_ci); - VALUE splat = Qfalse; + unsigned int forwarding_argc = vm_ci_argc(site_ci); + VALUE splat = Qfalse; - if (vm_ci_flag(site_ci) & VM_CALL_ARGS_SPLAT) { - // If we're called with args_splat, the top 1 should be an array - splat = TOPN(1); - forwarding_argc += (RARRAY_LEN(splat) - 1); - } + if (vm_ci_flag(site_ci) & VM_CALL_ARGS_SPLAT) { + // If we're called with args_splat, the top 1 should be an array + splat = TOPN(1); + forwarding_argc += (RARRAY_LEN(splat) - 1); + } - // Need to setup the block in case of e.g. `super { :block }` - if (is_super && blockiseq) { - bh = vm_caller_setup_arg_block(ec, GET_CFP(), site_ci, blockiseq, is_super); - } - else { - bh = VM_ENV_BLOCK_HANDLER(GET_LEP()); - } + // Need to setup the block in case of e.g. `super { :block }` + if (is_super && blockiseq) { + bh = vm_caller_setup_arg_block(ec, GET_CFP(), site_ci, blockiseq, is_super); + } + else { + bh = VM_ENV_BLOCK_HANDLER(GET_LEP()); + } - vm_adjust_stack_forwarding(ec, GET_CFP(), caller_ci, splat); + vm_adjust_stack_forwarding(ec, GET_CFP(), caller_ci, splat); - *adjusted_ci = VM_CI_ON_STACK( + *adjusted_ci = VM_CI_ON_STACK( vm_ci_mid(site_ci), (vm_ci_flag(caller_ci) | (vm_ci_flag(site_ci) & (VM_CALL_FCALL | VM_CALL_FORWARDING))), forwarding_argc + vm_ci_argc(caller_ci), vm_ci_kwarg(caller_ci) - ); + ); - adjusted_cd->cd.ci = adjusted_ci; - adjusted_cd->cd.cc = (*cd)->cc; - adjusted_cd->caller_ci = caller_ci; + adjusted_cd->cd.ci = adjusted_ci; + adjusted_cd->cd.cc = (*cd)->cc; + adjusted_cd->caller_ci = caller_ci; - *cd = &adjusted_cd->cd; - } - else { - bh = vm_caller_setup_arg_block(ec, GET_CFP(), site_ci, blockiseq, is_super); - } + *cd = &adjusted_cd->cd; return bh; } + +static VALUE +vm_caller_setup_args(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, + CALL_DATA *cd, const rb_iseq_t *blockiseq, const int is_super) +{ + return vm_caller_setup_arg_block(ec, GET_CFP(), (*cd)->ci, blockiseq, is_super); +} -- cgit v1.2.3