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.
This commit is contained in:
卜部昌平 2020-05-27 22:36:12 +09:00
Родитель 973883aaa1
Коммит 36322942db
1 изменённых файлов: 33 добавлений и 8 удалений

Просмотреть файл

@ -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