diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-05 17:51:10 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-05 17:51:10 +0000 |
commit | 0d2346f9a1bec6824863404cb371492336c673e4 (patch) | |
tree | 530e371b108e4a193b9859aad5e1f1c95ee24392 | |
parent | 1d3d8d89fc68fdc4de82482f57a9c97ed05abe5c (diff) | |
download | ruby-0d2346f9a1bec6824863404cb371492336c673e4.tar.gz |
Speedup `Proc#call` [Feature #14318]
* vm_insnhelper.c (vm_call_opt_call): do same process of `yield` instead of
invoking `Proc`.
* vm_insnhelper.c (vm_invoke_block): invoke given block handler instead of
using a block handler in the current frame.
Also do not check blcok handler here (caller should check it).
* insns.def (invokeblock): catch up this fix.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61624 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | insns.def | 9 | ||||
-rw-r--r-- | vm_insnhelper.c | 34 |
2 files changed, 20 insertions, 23 deletions
@@ -947,11 +947,18 @@ invokeblock (VALUE val) // inc += 1 - ci->orig_argc; { struct rb_calling_info calling; + VALUE block_handler; + calling.argc = ci->orig_argc; calling.block_handler = VM_BLOCK_HANDLER_NONE; calling.recv = Qundef; /* should not be used */ - val = vm_invoke_block(ec, GET_CFP(), &calling, ci); + block_handler = VM_CF_BLOCK_HANDLER(GET_CFP()); + if (block_handler == VM_BLOCK_HANDLER_NONE) { + rb_vm_localjump_error("no block given (yield)", Qnil, 0); + } + + val = vm_invoke_block(ec, GET_CFP(), &calling, ci, block_handler); if (val == Qundef) { RESTORE_REGS(); NEXT_INSN(); 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: |