diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-10-17 07:12:40 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-10-17 07:12:40 +0000 |
commit | 9a82db49eb5d464d6d0adc3c7c3ebf4574d5d025 (patch) | |
tree | ce8b90945b8a2ffad7160b180afa62b40f4f2e74 | |
parent | 7254573c551f83a83cf3f2d6e97de8ebe72e16fa (diff) | |
download | ruby-9a82db49eb5d464d6d0adc3c7c3ebf4574d5d025.tar.gz |
* vm_insnhelper.c (vm_call_method_missing): make a refactoring
about method_missing process. Use `vm_call_method()' to invoke
`method_missing' method instead of `rb_funcall2()'.
In `vm_call_method()', set fastpath to `vm_call_method_missing()'
if it can be cached.
* vm_core.h (rb_call_info_t): add new field
`rb_call_info_t::aux::missing_reasion' to pass the reason to
`vm_call_method_missing()'.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37243 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | vm_core.h | 1 | ||||
-rw-r--r-- | vm_insnhelper.c | 54 |
3 files changed, 44 insertions, 23 deletions
@@ -1,3 +1,15 @@ +Wed Oct 17 16:03:54 2012 Koichi Sasada <ko1@atdot.net> + + * vm_insnhelper.c (vm_call_method_missing): make a refactoring + about method_missing process. Use `vm_call_method()' to invoke + `method_missing' method instead of `rb_funcall2()'. + In `vm_call_method()', set fastpath to `vm_call_method_missing()' + if it can be cached. + + * vm_core.h (rb_call_info_t): add new field + `rb_call_info_t::aux::missing_reasion' to pass the reason to + `vm_call_method_missing()'. + Wed Oct 17 15:33:12 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> * configure.in (opt-dir): allow multiple directories separated by @@ -165,6 +165,7 @@ typedef struct rb_call_info_struct { union { int opt_pc; /* used by iseq */ long index; /* used by ivar */ + int missing_reason; /* used by method_missing */ } aux; VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 5f826b73fc..967ec1b4cb 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1478,6 +1478,7 @@ vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *c } ci->mid = rb_to_id(sym); } + /* shift arguments */ if (i > 0) { MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); @@ -1486,7 +1487,7 @@ vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *c ci->argc -= 1; DEC_SP(1); - ci->flag |= VM_CALL_FCALL | VM_CALL_OPT_SEND; + ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND; return vm_call_method(th, reg_cfp, ci); } @@ -1520,27 +1521,28 @@ vm_call_cfunc_fast_binary(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info } static VALUE -vm_call_missing(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) +vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci) { - VALUE *argv = ALLOCA_N(VALUE, ci->argc+1); - argv[0] = ID2SYM(ci->me->def->original_id); - MEMCPY(argv+1, cfp->sp - ci->argc, VALUE, ci->argc); - cfp->sp += - ci->argc - 1; - th->passed_block = ci->blockptr; - return rb_funcall2(ci->recv, rb_intern("method_missing"), ci->argc+1, argv); -} + VALUE *argv = STACK_ADDR_FROM_TOP(ci->argc); + rb_call_info_t ci_entry; -static VALUE -vm_method_missing(rb_thread_t *th, rb_control_frame_t *const reg_cfp, rb_call_info_t *ci, int opt) -{ - VALUE ret, *argv = STACK_ADDR_FROM_TOP(ci->argc + 1); + ci_entry.flag = VM_CALL_FCALL | VM_CALL_OPT_SEND; + ci_entry.argc = ci->argc+1; + ci_entry.mid = idMethodMissing; + ci_entry.blockptr = ci->blockptr; + ci_entry.recv = ci->recv; + ci_entry.me = rb_method_entry(CLASS_OF(ci_entry.recv), idMethodMissing, &ci_entry.defined_class); - th->method_missing_reason = opt; - th->passed_block = ci->blockptr; + /* shift arguments: m(a, b, c) #=> method_missing(:m, a, b, c) */ + CHECK_STACK_OVERFLOW(reg_cfp, 1); + if (ci->argc > 0) { + MEMMOVE(argv+1, argv, VALUE, ci->argc); + } argv[0] = ID2SYM(ci->mid); - ret = rb_funcall2(ci->recv, idMethodMissing, ci->argc + 1, argv); - POPN(ci->argc + 1); - return ret; + INC_SP(1); + + th->method_missing_reason = ci->aux.missing_reason; + return vm_call_method(th, reg_cfp, &ci_entry); } static VALUE @@ -1575,8 +1577,9 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) return vm_call_ivar(th, cfp, ci); } case VM_METHOD_TYPE_MISSING:{ - CI_SET_FASTPATH(ci, vm_call_missing, enable_fastpath); - return vm_call_missing(th, cfp, ci); + ci->aux.missing_reason = 0; + CI_SET_FASTPATH(ci, vm_call_method_missing, enable_fastpath); + return vm_call_method_missing(th, cfp, ci); } case VM_METHOD_TYPE_BMETHOD:{ CI_SET_FASTPATH(ci, vm_call_bmethod, enable_fastpath); @@ -1638,12 +1641,15 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) if (ci->flag & VM_CALL_VCALL) { stat |= NOEX_VCALL; } - return vm_method_missing(th, cfp, ci, stat); + ci->aux.missing_reason = stat; + CI_SET_FASTPATH(ci, vm_call_method_missing, 1); + return vm_call_method_missing(th, cfp, ci); } else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->flag & NOEX_MASK) & NOEX_PROTECTED) { enable_fastpath = 0; if (!rb_obj_is_kind_of(cfp->self, ci->defined_class)) { - return vm_method_missing(th, cfp, ci, NOEX_PROTECTED); + ci->aux.missing_reason = NOEX_PROTECTED; + return vm_call_method_missing(th, cfp, ci); } else { goto normal_method_dispatch; @@ -1672,7 +1678,9 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) rb_raise_method_missing(th, ci->argc, argv, ci->recv, stat); } else { - return vm_method_missing(th, cfp, ci, stat); + ci->aux.missing_reason = stat; + CI_SET_FASTPATH(ci, vm_call_method_missing, 1); + return vm_call_method_missing(th, cfp, ci); } } |