diff --git a/ChangeLog b/ChangeLog index d5c501db2b..0ab5402906 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +Sun Jun 24 22:00:17 2007 Koichi Sasada + + * insn_send.ci: removed. + + * common.mk: ditto. + + * vm.c (vm_call_bmethod), isnsn.def: added. fix to use this + function instead of using goto. + + * vm.c (vm_call_bmethod): renamed from th_invoke_bmethod(). + + * vm.c (vm_method_missing): renamed from eval_methdo_missing(). + + * vm_evalbody.ci: remove tmp_* variables. + + * insnhelper.h: add some macros. + + * insns.def: forbid zsuper from method defined by define_method(). + + * test/ruby/test_super.rb: ditto. + Sun Jun 24 20:01:08 2007 Koichi Sasada * vm_macro.def: removed. diff --git a/common.mk b/common.mk index af8a93f476..e2df6060aa 100644 --- a/common.mk +++ b/common.mk @@ -552,21 +552,20 @@ compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \ {$(VPATH)}compile.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \ {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}signal.h \ - {$(VPATH)}insns.inc {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \ + {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \ {$(VPATH)}opt_sc.inc {$(VPATH)}optunifs.inc {$(VPATH)}vm_opts.h \ {$(VPATH)}thread_$(THREAD_MODEL).h iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h \ {$(VPATH)}ruby.h {$(VPATH)}defines.h {$(VPATH)}missing.h \ {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}signal.h \ {$(VPATH)}gc.h {$(VPATH)}vm_opts.h {$(VPATH)}config.h {$(VPATH)}node.h \ - {$(VPATH)}thread_$(THREAD_MODEL).h\ - {$(VPATH)}insns.inc {$(VPATH)}insns_info.inc + {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns_info.inc vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}insnhelper.h \ {$(VPATH)}yarvcore.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h\ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}dln.h \ {$(VPATH)}vm_evalbody.ci {$(VPATH)}call_cfunc.ci \ {$(VPATH)}insns.inc {$(VPATH)}vm.inc {$(VPATH)}vmtc.inc \ - {$(VPATH)}insn_send.ci {$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \ + {$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \ {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \ {$(VPATH)}gc.h {$(VPATH)}thread_$(THREAD_MODEL).h vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}yarvcore.h {$(VPATH)}vm.h \ diff --git a/insn_send.ci b/insn_send.ci deleted file mode 100644 index a37336f557..0000000000 --- a/insn_send.ci +++ /dev/null @@ -1,226 +0,0 @@ -/* -*-c-*- */ -/* send instruction body */ - -{ - NODE *mn; - VALUE recv; - VALUE klass; - rb_block_t *blockptr = 0; - rb_num_t num; - rb_num_t flag = op_flag; - ID id = op_id; - - num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr); - - if (flag & VM_CALL_FCALL_BIT) { - /* method(...) */ - recv = GET_SELF(); - } - else { - /* recv.method(...) */ - recv = TOPN(num); - } - - klass = CLASS_OF(recv); - - mn = eval_method_search(id, klass, ic); - - if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) { - NODE *node = mn->nd_body; - extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv); - extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv); - - if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) { - int i; - VALUE sym = TOPN(num - 1); - id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym); - - /* shift arguments */ - for (i=num-1; i>0; i--) { - TOPN(i) = TOPN(i-1); - } - - mn = rb_method_node(klass, id); - - num -= 1; - DEC_SP(1); - } - - if (node->nd_cfnc == rb_f_funcall) { - flag |= VM_CALL_FCALL_BIT; - } - } - -#if CURRENT_INSN_send || CURRENT_INSN_send_SC_xx_ax -#if !YARV_AOT_COMPILED - if (0) { - if (0) { - LABEL_IS_SC(start_init_in_send_for_opt_1): - num = 1; - recv = TOPN(1); - } - else if (0) { - LABEL_IS_SC(start_init_in_send_for_opt_2): - num = 2; - recv = TOPN(2); - } - flag = 0; - id = tmp_id; - klass = CLASS_OF(recv); - blockptr = 0; - mn = rb_method_node(klass, id); - } - if (0) { - LABEL_IS_SC(start_init_in_super): - { - rb_iseq_t *iseq = GET_ISEQ(); - rb_iseq_t *ip = iseq; - - num = tmp_num; - flag = VM_CALL_FCALL_BIT; - recv = GET_SELF(); - - while (ip && !ip->klass) { - ip = ip->parent_iseq; - } - - if (ip == 0) { - rb_raise(rb_eNoMethodError, "super called outside of method"); - } - - id = ip->defined_method_id; - - if (ip != ip->local_iseq) { - /* defined by Module#define_method() */ - rb_control_frame_t *lcfp = GET_CFP(); - - while (lcfp->iseq != ip) { - VALUE *tdfp = GET_PREV_DFP(lcfp->dfp); - while (1) { - lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp); - if (lcfp->dfp == tdfp) { - break; - } - } - } - - id = lcfp->method_id; - klass = search_super_klass(lcfp->method_klass, recv); - - if (TOPN(num) == Qfalse) { - /* for ZSUPER */ - int i; - POPN(num); - num = ip->argc; - for (i = 0; i < ip->argc; i++) { - PUSH(lcfp->dfp[i - ip->local_size]); - } - } - } - else { - klass = search_super_klass(ip->klass, recv); - } - - flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; - blockptr = tmp_blockptr; - mn = rb_method_node(klass, id); - } - } - LABEL_IS_SC(start_method_dispatch): -#endif -#endif - /* method missing */ - if (mn == 0) { - /* temporarily */ - if (id == idMethodMissing) { - rb_bug("method missing"); - } - else { - int stat = 0; - if (flag & VM_CALL_VCALL_BIT) { - stat |= NOEX_VCALL; - } - if (flag & VM_CALL_SUPER_BIT) { - stat |= NOEX_SUPER; - } - val = eval_method_missing(th, id, recv, num, blockptr, stat); - } - } - else if (!(flag & VM_CALL_FCALL_BIT) && - (mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) { - int stat = NOEX_PRIVATE; - if (flag & VM_CALL_VCALL_BIT) { - stat |= NOEX_VCALL; - } - val = eval_method_missing(th, id, recv, num, blockptr, stat); - } - else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) { - VALUE defined_class = mn->nd_clss; - - if (TYPE(defined_class) == T_ICLASS) { - defined_class = RBASIC(defined_class)->klass; - } - if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(defined_class))) { - val = - eval_method_missing(th, id, recv, num, blockptr, - NOEX_PROTECTED); - } - else { - goto INSN_LABEL(normal_method_dispatch); - } - } - else { - NODE *node; - INSN_LABEL(normal_method_dispatch): - - node = mn->nd_body; - switch (nd_type(node)) { - case RUBY_VM_METHOD_NODE:{ - vm_setup_method(th, GET_CFP(), num, blockptr, flag, (VALUE)node->nd_body, recv, klass); - RESTORE_REGS(); - NEXT_INSN(); - } - case NODE_CFUNC:{ - val = vm_call_cfunc(th, GET_CFP(), num, id, recv, klass, node, blockptr); - break; - } - case NODE_ATTRSET:{ - val = rb_ivar_set(recv, node->nd_vid, TOPN(0)); - POPN(2); - break; - } - case NODE_IVAR:{ - val = rb_ivar_get(recv, node->nd_vid); - POP(); - break; - } - case NODE_BMETHOD:{ - VALUE *argv = GET_SP() - num; - val = th_invoke_bmethod(th, id, node->nd_cval, - recv, klass, num, argv); - INC_SP(-num-1); - break; - } - case NODE_ZSUPER:{ - klass = RCLASS(mn->nd_clss)->super; - mn = rb_method_node(klass, id); - - if (mn != 0) { - goto INSN_LABEL(normal_method_dispatch); - } - else { - goto LABEL_IS_SC(start_method_dispatch); - } - } - default:{ - printf("node: %s\n", ruby_node_name(nd_type(node))); - rb_bug("eval_invoke_method: unreachable"); - /* unreachable */ - break; - } - } - } - - RUBY_VM_CHECK_INTS(); -} - diff --git a/insnhelper.h b/insnhelper.h index 3801e5a41b..1fe19128b7 100644 --- a/insnhelper.h +++ b/insnhelper.h @@ -146,4 +146,20 @@ while (0) #define BASIC_OP_UNREDEFINED_P(op) ((yarv_redefined_flag & (op)) == 0) #define HEAP_CLASS_OF(obj) RBASIC(obj)->klass +#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass) do { \ + VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass); \ + if (v == Qundef) { \ + RESTORE_REGS(); \ + NEXT_INSN(); \ + } \ + else { \ + val = v; \ + } \ +} while (0) + +#define CALL_SIMPLE_METHOD(num, id, recv) do { \ + VALUE klass = CLASS_OF(recv); \ + CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv)); \ +} while (0) + #endif /* _INSNHELPER_H_INCLUDED_ */ diff --git a/insns.def b/insns.def index 4b16695877..6d16fe1b59 100644 --- a/insns.def +++ b/insns.def @@ -1152,7 +1152,55 @@ send (...) (VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); { -#include "insn_send.ci" + NODE *mn; + VALUE recv, klass, v; + rb_block_t *blockptr = 0; + rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr); + rb_num_t flag = op_flag; + ID id = op_id; + + /* get receiver */ + if (flag & VM_CALL_FCALL_BIT) { + /* method(...) */ + recv = GET_SELF(); + } + else { + /* recv.method(...) */ + recv = TOPN(num); + } + + klass = CLASS_OF(recv); + + mn = eval_method_search(id, klass, ic); + + /* send/funcall optimization */ + if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) { + NODE *node = mn->nd_body; + extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv); + extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv); + + if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) { + int i; + VALUE sym = TOPN(num - 1); + id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym); + + /* shift arguments */ + for (i=num-1; i>0; i--) { + TOPN(i) = TOPN(i-1); + } + + mn = rb_method_node(klass, id); + + num -= 1; + DEC_SP(1); + } + + if (node->nd_cfnc == rb_f_funcall) { + flag |= VM_CALL_FCALL_BIT; + } + } + + CALL_METHOD(num, blockptr, flag, id, mn, recv, klass); } /** @@ -1162,21 +1210,65 @@ send */ DEFINE_INSN invokesuper -(rb_num_t op_argc, ISEQ blockiseq, rb_num_t flag) +(rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag) (...) (VALUE val) // inc += - op_argc; { -#if YARV_AOT_COMPILED - /* TODO: */ - rb_bug("..."); -#else - tmp_blockptr = 0; - tmp_num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &tmp_blockptr); - if (!tmp_blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) { - tmp_blockptr = GET_BLOCK_PTR(); + rb_block_t *blockptr = 0; + VALUE flag = op_flag; + int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr); + rb_iseq_t *iseq = GET_ISEQ(); + rb_iseq_t *ip = iseq; + VALUE recv, klass; + ID id; + NODE *mn; + + if (!blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) { + blockptr = GET_BLOCK_PTR(); } - goto LABEL_IS_SC(start_init_in_super); -#endif + + recv = GET_SELF(); + + while (ip && !ip->klass) { + ip = ip->parent_iseq; + } + + if (ip == 0) { + rb_raise(rb_eNoMethodError, "super called outside of method"); + } + + id = ip->defined_method_id; + + if (ip != ip->local_iseq) { + /* defined by Module#define_method() */ + rb_control_frame_t *lcfp = GET_CFP(); + + while (lcfp->iseq != ip) { + VALUE *tdfp = GET_PREV_DFP(lcfp->dfp); + while (1) { + lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp); + if (lcfp->dfp == tdfp) { + break; + } + } + } + + id = lcfp->method_id; + klass = search_super_klass(lcfp->method_klass, recv); + + if (TOPN(num) == Qfalse) { + /* zsuper */ + rb_raise(rb_eRuntimeError, "zsuper from method defined by define_method() is not supported. Specify all arguments."); + } + } + else { + klass = search_super_klass(ip->klass, recv); + } + + flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; + mn = rb_method_node(klass, id); + + CALL_METHOD(num, blockptr, flag, id, mn, recv, klass); } /** @@ -1581,15 +1673,9 @@ opt_plus } else { INSN_LABEL(normal_dispatch): - -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idPLUS, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idPLUS; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idPLUS, recv); } } @@ -1619,14 +1705,9 @@ opt_minus } else { /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idMINUS, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idMINUS; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idMINUS, recv); } } @@ -1675,16 +1756,9 @@ opt_mult } else { INSN_LABEL(normal_dispatch): - - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idMULT, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idMULT; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idMULT, recv); } } @@ -1746,16 +1820,9 @@ opt_div } else { INSN_LABEL(normal_dispatch): - - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idDIV, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idDIV; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idDIV, recv); } } @@ -1837,16 +1904,9 @@ opt_mod } else { INSN_LABEL(normal_dispatch): - - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idMOD, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idMOD; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idMOD, recv); } } @@ -1916,14 +1976,9 @@ opt_eq else { INSN_LABEL(normal_dispatch): /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idEq, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idEq; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idEq, recv); } } @@ -1951,15 +2006,9 @@ opt_lt } } else { - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idLT, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idLT; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idLT, recv); } } @@ -1987,14 +2036,9 @@ opt_le } else { /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idLE, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idLE; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idLE, recv); } } @@ -2021,15 +2065,9 @@ opt_gt } } else { - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idGT, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idGT; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idGT, recv); } } @@ -2056,15 +2094,9 @@ opt_ge } } else { - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idGE, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idGE; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idGE, recv); } } @@ -2096,15 +2128,9 @@ opt_ltlt } else { INSN_LABEL(normal_dispatch): - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idLTLT, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idLTLT; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idLTLT, recv); } } @@ -2132,15 +2158,9 @@ opt_aref } else { INSN_LABEL(normal_dispatch): - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idAREF, 1, obj); -#else PUSH(recv); PUSH(obj); - tmp_id = idAREF; - goto LABEL_IS_SC(start_init_in_send_for_opt_1); -#endif + CALL_SIMPLE_METHOD(1, idAREF, recv); } } @@ -2171,16 +2191,10 @@ opt_aset } else { INSN_LABEL(normal_dispatch): - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idASET, 2, obj, set); -#else PUSH(recv); PUSH(obj); PUSH(set); - tmp_id = idASET; - goto LABEL_IS_SC(start_init_in_send_for_opt_2); -#endif + CALL_SIMPLE_METHOD(2, idASET, recv); } } @@ -2212,12 +2226,8 @@ opt_length } else { INSN_LABEL(normal_dispatch): - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idLength, 0); -#else - val = rb_funcall(recv, idLength, 0); -#endif + PUSH(recv); + CALL_SIMPLE_METHOD(0, idLength, recv); } } @@ -2262,12 +2272,8 @@ opt_succ } if (0) { INSN_LABEL(normal_dispatch): - /* other */ -#ifdef YARV_AOT_COMPILED - val = rb_funcall(recv, idSucc, 0); -#else - val = rb_funcall(recv, idSucc, 0); -#endif + PUSH(recv); + CALL_SIMPLE_METHOD(0, idSucc, recv); } } diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index 900fe997e6..d64fef514e 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -120,7 +120,7 @@ class TestSuper < Test::Unit::TestCase def uu(a) class << self define_method(:tt) do |sym| - super + super(sym) end end end diff --git a/vm.c b/vm.c index b8acd9e523..8ac65d0e35 100644 --- a/vm.c +++ b/vm.c @@ -371,6 +371,38 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, int num, return val; } +static inline VALUE +vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv, + VALUE klass, int argc, VALUE *argv) +{ + rb_control_frame_t *cfp = th->cfp; + rb_proc_t *proc; + VALUE val; + + /* control block frame */ + (cfp-2)->method_id = id; + (cfp-2)->method_klass = klass; + + GetProcPtr(procval, proc); + val = th_invoke_proc(th, proc, recv, argc, argv); + return val; +} + +static inline VALUE +vm_method_missing(rb_thread_t *th, ID id, VALUE recv, int num, + rb_block_t *blockptr, int opt) +{ + rb_control_frame_t *reg_cfp = th->cfp; + VALUE *argv = STACK_ADDR_FROM_TOP(num + 1); + VALUE val; + argv[0] = ID2SYM(id); + th->method_missing_reason = opt; + th->passed_block = blockptr; + val = rb_funcall2(recv, idMethodMissing, num + 1, argv); + POPN(num + 1); + return val; +} + static inline void vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, int argc, rb_block_t *blockptr, VALUE flag, @@ -428,6 +460,110 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, } } +static inline VALUE +vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, + int num, rb_block_t *blockptr, VALUE flag, + ID id, NODE *mn, VALUE recv, VALUE klass) +{ + VALUE val; + + start_method_dispatch: + + /* method missing */ + if (mn == 0) { + if (id == idMethodMissing) { + rb_bug("method missing"); + } + else { + int stat = 0; + if (flag & VM_CALL_VCALL_BIT) { + stat |= NOEX_VCALL; + } + if (flag & VM_CALL_SUPER_BIT) { + stat |= NOEX_SUPER; + } + val = vm_method_missing(th, id, recv, num, blockptr, stat); + } + } + else if (!(flag & VM_CALL_FCALL_BIT) && + (mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) { + int stat = NOEX_PRIVATE; + if (flag & VM_CALL_VCALL_BIT) { + stat |= NOEX_VCALL; + } + val = vm_method_missing(th, id, recv, num, blockptr, stat); + } + else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) { + VALUE defined_class = mn->nd_clss; + + if (TYPE(defined_class) == T_ICLASS) { + defined_class = RBASIC(defined_class)->klass; + } + + if (!rb_obj_is_kind_of(cfp->self, rb_class_real(defined_class))) { + val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED); + } + else { + goto normal_method_dispatch; + } + } + + /* dispatch method */ + else { + NODE *node; + normal_method_dispatch: + + node = mn->nd_body; + switch (nd_type(node)) { + case RUBY_VM_METHOD_NODE:{ + vm_setup_method(th, cfp, num, blockptr, flag, (VALUE)node->nd_body, recv, klass); + return Qundef; + } + case NODE_CFUNC:{ + val = vm_call_cfunc(th, cfp, num, id, recv, klass, node, blockptr); + break; + } + case NODE_ATTRSET:{ + val = rb_ivar_set(recv, node->nd_vid, *(cfp->sp - 1)); + cfp->sp -= 2; + break; + } + case NODE_IVAR:{ + val = rb_ivar_get(recv, node->nd_vid); + cfp->sp -= 1; + break; + } + case NODE_BMETHOD:{ + VALUE *argv = cfp->sp - num; + val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv); + cfp->sp += - num - 1; + break; + } + case NODE_ZSUPER:{ + klass = RCLASS(mn->nd_clss)->super; + mn = rb_method_node(klass, id); + + if (mn != 0) { + goto normal_method_dispatch; + } + else { + goto start_method_dispatch; + } + } + default:{ + printf("node: %s\n", ruby_node_name(nd_type(node))); + rb_bug("eval_invoke_method: unreachable"); + /* unreachable */ + break; + } + } + } + + RUBY_VM_CHECK_INTS(); + return val; +} + + /* Env */ static void @@ -735,23 +871,6 @@ th_make_proc(rb_thread_t *th, return procval; } -static inline VALUE -th_invoke_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv, - VALUE klass, int argc, VALUE *argv) -{ - rb_control_frame_t *cfp = th->cfp; - rb_proc_t *proc; - VALUE val; - - /* control block frame */ - (cfp-2)->method_id = id; - (cfp-2)->method_klass = klass; - - GetProcPtr(procval, proc); - val = th_invoke_proc(th, proc, recv, argc, argv); - return val; -} - VALUE th_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid, int argc, const VALUE *argv, @@ -829,8 +948,8 @@ th_call0(rb_thread_t *th, VALUE klass, VALUE recv, break; } case NODE_BMETHOD:{ - val = th_invoke_bmethod(th, id, body->nd_cval, - recv, klass, argc, (VALUE *)argv); + val = vm_call_bmethod(th, id, body->nd_cval, + recv, klass, argc, (VALUE *)argv); break; } default: @@ -1555,21 +1674,6 @@ eval_define_method(rb_thread_t *th, VALUE obj, INC_VM_STATE_VERSION(); } -EVALBODY_HELPER_FUNCTION VALUE -eval_method_missing(rb_thread_t *th, ID id, VALUE recv, int num, - rb_block_t *blockptr, int opt) -{ - rb_control_frame_t *reg_cfp = th->cfp; - VALUE *argv = STACK_ADDR_FROM_TOP(num + 1); - VALUE val; - argv[0] = ID2SYM(id); - th->method_missing_reason = opt; - th->passed_block = blockptr; - val = rb_funcall2(recv, idMethodMissing, num + 1, argv); - POPN(num + 1); - return val; -} - EVALBODY_HELPER_FUNCTION NODE * eval_method_search(VALUE id, VALUE klass, IC ic) { diff --git a/vm_evalbody.ci b/vm_evalbody.ci index 3497ac7ff1..d0c45b3a5b 100644 --- a/vm_evalbody.ci +++ b/vm_evalbody.ci @@ -76,10 +76,6 @@ th_eval(rb_thread_t *th, VALUE initial) #define SET_PC(x) (reg_cfp->pc = REG_PC = (x)) #endif - ID tmp_id; - rb_block_t *tmp_blockptr; - rb_num_t tmp_num; - #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE #include "vmtc.inc" if (th == 0) {