summaryrefslogtreecommitdiff
path: root/vm_args.c
diff options
context:
space:
mode:
authorAaron Patterson <[email protected]>2024-06-03 14:20:04 -0700
committerAaron Patterson <[email protected]>2024-06-18 09:28:25 -0700
commitcc97a270080d2c6eb9dbdd2b9793ab549b6bb44d (patch)
treef50ddd82e8aa7192211b20afe9e37ea287a40c90 /vm_args.c
parenta25dd5b12c550a152d9875720b423e141f36dfb0 (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.c60
1 files changed, 31 insertions, 29 deletions
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);
+}