diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-05-27 22:36:12 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-06-03 16:13:47 +0900 |
commit | 36322942dbce6dedaf67626b152dbf893d42e082 (patch) | |
tree | f8cbfb11b6211925670f9bb6fd591a8469e41f73 /vm_insnhelper.c | |
parent | 973883aaa16bde8ba41caceb56569b52adb4c74f (diff) | |
download | ruby-36322942dbce6dedaf67626b152dbf893d42e082.tar.gz |
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.
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 41 |
1 files 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 |