diff options
author | Aaron Patterson <[email protected]> | 2024-06-03 14:20:04 -0700 |
---|---|---|
committer | Aaron Patterson <[email protected]> | 2024-06-18 09:28:25 -0700 |
commit | cc97a270080d2c6eb9dbdd2b9793ab549b6bb44d (patch) | |
tree | f50ddd82e8aa7192211b20afe9e37ea287a40c90 /vm_args.c | |
parent | a25dd5b12c550a152d9875720b423e141f36dfb0 (diff) |
Add two new instructions for forwarding calls
This commit adds `sendforward` and `invokesuperforward` for forwarding
parameters to calls
Co-authored-by: Matt Valentine-House <[email protected]>
Diffstat (limited to 'vm_args.c')
-rw-r--r-- | vm_args.c | 60 |
1 files changed, 31 insertions, 29 deletions
@@ -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); +} |