diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-06-24 13:05:51 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-06-24 13:05:51 +0000 |
commit | 62deb7dbbda5104c352abd723053bd1b18e50dbf (patch) | |
tree | 4680058ffc0d96cf05e0209aba88ef6cbf767fd4 | |
parent | 904b9e5d547f4f9a9f3236d2633f0cb6d7aae14c (diff) | |
download | ruby-62deb7dbbda5104c352abd723053bd1b18e50dbf.tar.gz |
* 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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | common.mk | 7 | ||||
-rw-r--r-- | insn_send.ci | 226 | ||||
-rw-r--r-- | insnhelper.h | 16 | ||||
-rw-r--r-- | insns.def | 236 | ||||
-rw-r--r-- | test/ruby/test_super.rb | 2 | ||||
-rw-r--r-- | vm.c | 172 | ||||
-rw-r--r-- | vm_evalbody.ci | 4 |
8 files changed, 300 insertions, 384 deletions
@@ -1,3 +1,24 @@ +Sun Jun 24 22:00:17 2007 Koichi Sasada <ko1@atdot.net> + + * 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 <ko1@atdot.net> * vm_macro.def: removed. @@ -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_ */ @@ -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 @@ -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) { |