From: Nobuyoshi Nakada Date: 2007-02-26T02:07:47+09:00 Subject: [ruby-dev:30420] Re: unsupported: th_call0 in 1.9 なかだです。 At Wed, 21 Feb 2007 22:33:56 +0900, KUBO Takehiro wrote in [ruby-dev:30396]: > ruby 1.9 で以下の条件のとき、[BUG] unsupported: th_call0 となりました。 > > 1. private なメソッドをサブクラスで public にする。 > 2. 拡張ライブラリからサブクラスで public にしたメソッドを rb_funcall > で呼び出す。 これでどうでしょうか。 Index: eval.c =================================================================== --- eval.c (revision 11883) +++ eval.c (working copy) @@ -1550,6 +1550,6 @@ rb_method_missing(int argc, const VALUE } -static VALUE -method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) +VALUE +rb_call_method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) { VALUE *nargv; @@ -1588,6 +1588,6 @@ rb_call(VALUE klass, VALUE recv, ID mid, if (ent->mid == mid && ent->klass == klass) { if (!ent->method) - return method_missing(recv, mid, argc, argv, - scope == 2 ? NOEX_VCALL : 0); + return rb_call_method_missing(recv, mid, argc, argv, + scope == 2 ? NOEX_VCALL : 0); id = ent->mid0; noex = ent->method->nd_noex; @@ -1602,13 +1602,13 @@ rb_call(VALUE klass, VALUE recv, ID mid, else { if (scope == 3) { - return method_missing(recv, mid, argc, argv, NOEX_SUPER); + return rb_call_method_missing(recv, mid, argc, argv, NOEX_SUPER); } - return method_missing(recv, mid, argc, argv, - scope == 2 ? NOEX_VCALL : 0); + return rb_call_method_missing(recv, mid, argc, argv, + scope == 2 ? NOEX_VCALL : 0); } if (mid != missing) { /* receiver specified form for private method */ if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) { - return method_missing(recv, mid, argc, argv, NOEX_PRIVATE); + return rb_call_method_missing(recv, mid, argc, argv, NOEX_PRIVATE); } @@ -1623,5 +1623,5 @@ rb_call(VALUE klass, VALUE recv, ID mid, if (!rb_obj_is_kind_of(rb_frame_self(), rb_class_real(defined_class))) { - return method_missing(recv, mid, argc, argv, NOEX_PROTECTED); + return rb_call_method_missing(recv, mid, argc, argv, NOEX_PROTECTED); } } Index: intern.h =================================================================== --- intern.h (revision 11883) +++ intern.h (working copy) @@ -250,4 +250,5 @@ VALUE rb_binding_new(void); VALUE rb_obj_method(VALUE, VALUE); VALUE rb_method_call(int, VALUE*, VALUE); +VALUE rb_call_method_missing(VALUE, ID, int, const VALUE *, int); int rb_mod_method_arity(VALUE, ID); int rb_obj_method_arity(VALUE, ID); Index: vm.c =================================================================== --- vm.c (revision 11883) +++ vm.c (working copy) @@ -502,4 +502,6 @@ th_invoke_bmethod(rb_thread_t *th, ID id } +static VALUE th_call_super(rb_thread_t *, int, const VALUE *); + VALUE th_call0(rb_thread_t *th, VALUE klass, VALUE recv, @@ -521,63 +523,67 @@ th_call0(rb_thread_t *th, VALUE klass, V switch (nd_type(body)) { case RUBY_VM_METHOD_NODE:{ - rb_control_frame_t *reg_cfp; - int i; - const int flag = 0; - - th_set_finish_env(th); - reg_cfp = th->cfp; - for (i = 0; i < argc; i++) { - *reg_cfp->sp++ = argv[i]; - } - macro_eval_invoke_func(body->nd_body, recv, klass, blockptr, - argc); - val = th_eval_body(th); - break; + rb_control_frame_t *reg_cfp; + int i; + const int flag = 0; + + th_set_finish_env(th); + reg_cfp = th->cfp; + for (i = 0; i < argc; i++) { + *reg_cfp->sp++ = argv[i]; + } + macro_eval_invoke_func(body->nd_body, recv, klass, blockptr, + argc); + val = th_eval_body(th); + break; } - case NODE_CFUNC: { - rb_control_frame_t *reg_cfp = th->cfp; - rb_control_frame_t *cfp = + case NODE_CFUNC:{ + rb_control_frame_t *reg_cfp = th->cfp; + rb_control_frame_t *cfp = push_frame(th, 0, FRAME_MAGIC_CFUNC, recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); - cfp->callee_id = oid; - cfp->method_id = id; - cfp->method_klass = klass; - - val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv); - - if (reg_cfp != th->cfp + 1) { - SDR2(reg_cfp); - SDR2(th->cfp-5); - rb_bug("cfp consistency error - call0"); - th->cfp = reg_cfp; - } - pop_frame(th); + cfp->callee_id = oid; + cfp->method_id = id; + cfp->method_klass = klass; + + val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv); + + if (reg_cfp != th->cfp + 1) { + SDR2(reg_cfp); + SDR2(th->cfp-5); + rb_bug("cfp consistency error - call0"); + th->cfp = reg_cfp; + } + pop_frame(th); - break; + break; } case NODE_ATTRSET:{ - if (argc != 1) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", - argc); - } - val = rb_ivar_set(recv, body->nd_vid, argv[0]); - break; + if (argc != 1) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", + argc); + } + val = rb_ivar_set(recv, body->nd_vid, argv[0]); + break; + } + case NODE_IVAR:{ + if (argc != 0) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", + argc); + } + val = rb_attr_get(recv, body->nd_vid); + break; } - case NODE_IVAR: { - if (argc != 0) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", - argc); - } - val = rb_attr_get(recv, body->nd_vid); - break; + case NODE_ZSUPER:{ + val = th_call_super(th, argc, argv); + break; } case NODE_BMETHOD:{ - val = th_invoke_bmethod(th, id, body->nd_cval, - recv, klass, argc, (VALUE *)argv); - break; + val = th_invoke_bmethod(th, id, body->nd_cval, + recv, klass, argc, (VALUE *)argv); + break; } default: - rb_bug("unsupported: th_call0"); + rb_bug("unsupported: th_call0(%s)", ruby_node_name(nd_type(body))); } RUBY_VM_CHECK_INTS(); @@ -614,5 +620,5 @@ th_call_super(rb_thread_t *th, int argc, rb_control_frame_t *cfp = th->cfp; - if (!th->cfp->iseq) { + if (!cfp->iseq) { klass = cfp->method_klass; klass = RCLASS(klass)->super; @@ -634,4 +640,5 @@ th_call_super(rb_thread_t *th, int argc, } else { + rb_call_method_missing(recv, id, argc, (VALUE *)argv, NOEX_SUPER); dp(recv); dp(klass); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦