From 36322942dbce6dedaf67626b152dbf893d42e082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?= Date: Wed, 27 May 2020 22:36:12 +0900 Subject: vm_invoke_symbol_block: call vm_call_opt_send Symbol#to_proc and Object#send are closely related each other. Why not share their implementations. By doing so we can skip recursive call of vm_exec(), which could benefit for speed. --- vm_insnhelper.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index baf682ba85..3a19a45783 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3412,14 +3412,39 @@ vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_callinfo *ci, MAYBE_UNUSED(bool is_lambda), VALUE block_handler) { - VALUE val; - int argc; - VALUE symbol = VM_BH_TO_SYMBOL(block_handler); - CALLER_SETUP_ARG(ec->cfp, calling, ci); - argc = calling->argc; - val = vm_yield_with_symbol(ec, symbol, argc, STACK_ADDR_FROM_TOP(argc), calling->kw_splat, calling->block_handler); - POPN(argc); - return val; + int argc = calling->argc; + + if (argc < 1) { + rb_raise(rb_eArgError, "no receiver given"); + } + else if (argc > 1) { + /* E.g. when argc == 3 + * + * | | | | TOPN + * | | +------+ + * | | +---> | arg1 | -1 + * +------+ | +------+ + * | arg1 | -+ +-> | arg0 | 0 + * +------+ | +------+ + * | arg0 | ---+ | BH | 1 + * +------+ +------+ + * | recv | | recv | 2 + * --+------+--------+------+------ + * + * INC_SP is done immediately below. + */ + MEMMOVE(&TOPN(argc - 3), &TOPN(argc - 2), VALUE, argc - 1); + } + + TOPN(argc - 2) = VM_BH_TO_SYMBOL(block_handler); + calling->recv = TOPN(argc - 1); + INC_SP(1); + return vm_call_opt_send(ec, reg_cfp, calling, + &(struct rb_call_data) { + .ci = ci, + .cc = NULL, + } + ); } static VALUE -- cgit v1.2.3