summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c34
1 files changed, 12 insertions, 22 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index e6f7145119..aa808dca7d 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2047,22 +2047,19 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
return vm_call_method(ec, reg_cfp, calling, ci, cc);
}
+static VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler);
+
static VALUE
-vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
+vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
{
- rb_proc_t *proc;
- int argc;
- VALUE *argv;
-
- CALLER_SETUP_ARG(cfp, calling, ci);
+ VALUE procval = calling->recv;
+ int argc = calling->argc;
- argc = calling->argc;
- argv = ALLOCA_N(VALUE, argc);
- GetProcPtr(calling->recv, proc);
- MEMCPY(argv, cfp->sp - argc, VALUE, argc);
- cfp->sp -= argc + 1;
+ /* remove self */
+ if (argc > 0) MEMMOVE(&TOPN(argc), &TOPN(argc-1), VALUE, argc);
+ DEC_SP(1);
- return rb_vm_invoke_proc(ec, proc, argc, argv, calling->block_handler);
+ return vm_invoke_block(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
}
static VALUE
@@ -2654,7 +2651,7 @@ vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
int argc;
CALLER_SETUP_ARG(ec->cfp, calling, ci);
argc = calling->argc;
- val = vm_yield_with_symbol(ec, symbol, argc, STACK_ADDR_FROM_TOP(argc), VM_BLOCK_HANDLER_NONE);
+ val = vm_yield_with_symbol(ec, symbol, argc, STACK_ADDR_FROM_TOP(argc), calling->block_handler);
POPN(argc);
return val;
}
@@ -2668,7 +2665,7 @@ vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
int argc;
CALLER_SETUP_ARG(ec->cfp, calling, ci);
argc = calling->argc;
- val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), VM_BLOCK_HANDLER_NONE);
+ val = vm_yield_with_cfunc(ec, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), calling->block_handler);
POPN(argc); /* TODO: should put before C/yield? */
return val;
}
@@ -2693,17 +2690,10 @@ vm_proc_to_block_handler(VALUE procval)
}
static VALUE
-vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci)
+vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler)
{
- VALUE block_handler = VM_CF_BLOCK_HANDLER(reg_cfp);
- VALUE type = GET_ISEQ()->body->local_iseq->body->type;
int is_lambda = FALSE;
- if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) ||
- block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_vm_localjump_error("no block given (yield)", Qnil, 0);
- }
-
again:
switch (vm_block_handler_type(block_handler)) {
case block_handler_type_iseq: