mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
1d3d8d89fc
commit
0d2346f9a1
2 changed files with 20 additions and 23 deletions
|
@ -947,11 +947,18 @@ invokeblock
|
||||||
(VALUE val) // inc += 1 - ci->orig_argc;
|
(VALUE val) // inc += 1 - ci->orig_argc;
|
||||||
{
|
{
|
||||||
struct rb_calling_info calling;
|
struct rb_calling_info calling;
|
||||||
|
VALUE block_handler;
|
||||||
|
|
||||||
calling.argc = ci->orig_argc;
|
calling.argc = ci->orig_argc;
|
||||||
calling.block_handler = VM_BLOCK_HANDLER_NONE;
|
calling.block_handler = VM_BLOCK_HANDLER_NONE;
|
||||||
calling.recv = Qundef; /* should not be used */
|
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) {
|
if (val == Qundef) {
|
||||||
RESTORE_REGS();
|
RESTORE_REGS();
|
||||||
NEXT_INSN();
|
NEXT_INSN();
|
||||||
|
|
|
@ -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);
|
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
|
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;
|
VALUE procval = calling->recv;
|
||||||
int argc;
|
int argc = calling->argc;
|
||||||
VALUE *argv;
|
|
||||||
|
|
||||||
CALLER_SETUP_ARG(cfp, calling, ci);
|
/* remove self */
|
||||||
|
if (argc > 0) MEMMOVE(&TOPN(argc), &TOPN(argc-1), VALUE, argc);
|
||||||
|
DEC_SP(1);
|
||||||
|
|
||||||
argc = calling->argc;
|
return vm_invoke_block(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
|
||||||
argv = ALLOCA_N(VALUE, argc);
|
|
||||||
GetProcPtr(calling->recv, proc);
|
|
||||||
MEMCPY(argv, cfp->sp - argc, VALUE, argc);
|
|
||||||
cfp->sp -= argc + 1;
|
|
||||||
|
|
||||||
return rb_vm_invoke_proc(ec, proc, argc, argv, calling->block_handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -2654,7 +2651,7 @@ vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
int argc;
|
int argc;
|
||||||
CALLER_SETUP_ARG(ec->cfp, calling, ci);
|
CALLER_SETUP_ARG(ec->cfp, calling, ci);
|
||||||
argc = calling->argc;
|
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);
|
POPN(argc);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -2668,7 +2665,7 @@ vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
|
||||||
int argc;
|
int argc;
|
||||||
CALLER_SETUP_ARG(ec->cfp, calling, ci);
|
CALLER_SETUP_ARG(ec->cfp, calling, ci);
|
||||||
argc = calling->argc;
|
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? */
|
POPN(argc); /* TODO: should put before C/yield? */
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -2693,17 +2690,10 @@ vm_proc_to_block_handler(VALUE procval)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
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;
|
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:
|
again:
|
||||||
switch (vm_block_handler_type(block_handler)) {
|
switch (vm_block_handler_type(block_handler)) {
|
||||||
case block_handler_type_iseq:
|
case block_handler_type_iseq:
|
||||||
|
|
Loading…
Add table
Reference in a new issue