diff options
author | shugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-08-02 11:08:44 +0000 |
---|---|---|
committer | shugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-08-02 11:08:44 +0000 |
commit | 319088e9c7ae9836efd242592ea80c9794a45002 (patch) | |
tree | 4af392612508133a1f7aa015c9781aac88479982 /insns.def | |
parent | 14bf66f25210248334f4730784ad00c18b7d651e (diff) | |
download | ruby-319088e9c7ae9836efd242592ea80c9794a45002.tar.gz |
* class.c, insns.def, method.h, proc.c, vm.c, vm_core.h, vm_eval.c,
vm_insnhelper.c, vm_insnhelper.h, vm_method.c: add klass to
rb_control_frame_t to implement super correctly.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'insns.def')
-rw-r--r-- | insns.def | 32 |
1 files changed, 19 insertions, 13 deletions
@@ -798,7 +798,7 @@ defined break; case DEFINED_METHOD:{ VALUE klass = CLASS_OF(v); - const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj)); + const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj), 0); if (me) { if (!(me->flag & NOEX_PRIVATE)) { @@ -967,7 +967,7 @@ defineclass /* enter scope */ vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, - klass, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), + klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), class_iseq->iseq_encoded, GET_SP(), class_iseq->local_size, 0); RESTORE_REGS(); @@ -999,7 +999,7 @@ send (VALUE val) // inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); { const rb_method_entry_t *me; - VALUE recv, klass; + VALUE recv, klass, defined_class; rb_block_t *blockptr = 0; VALUE flag = op_flag; int num = caller_setup_args(th, GET_CFP(), flag, (int)op_argc, @@ -1009,8 +1009,8 @@ send /* get receiver */ recv = TOPN(num); klass = CLASS_OF(recv); - me = vm_method_search(id, klass, ic); - CALL_METHOD(num, blockptr, flag, id, me, recv); + me = vm_method_search(id, klass, ic, &defined_class); + CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class); } /** @@ -1033,20 +1033,26 @@ invokesuper VALUE recv, klass; ID id; const rb_method_entry_t *me; + rb_iseq_t *ip; flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT; recv = GET_SELF(); vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass); - /* temporary measure for [Bug #2402] [Bug #2502] [Bug #3136] */ - if (!rb_obj_is_kind_of(recv, klass)) { - rb_raise(rb_eNotImpError, "super from singleton method that is defined to multiple classes is not supported; this will be fixed in 1.9.3 or later"); + ip = GET_ISEQ(); + while (ip && !ip->klass) { + ip = ip->parent_iseq; + } + again: + me = rb_method_entry(klass, id, &klass); + if (me && me->def->type == VM_METHOD_TYPE_ISEQ && + me->def->body.iseq == ip) { + klass = RCLASS_SUPER(klass); + goto again; } - me = rb_method_entry(klass, id); - - CALL_METHOD(num, blockptr, flag, id, me, recv); + CALL_METHOD(num, blockptr, flag, id, me, recv, klass); } /** @@ -1652,7 +1658,7 @@ opt_neq (VALUE val) { extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); - const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic); + const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic, 0); val = Qundef; if (check_cfunc(me, rb_obj_not_equal)) { @@ -2056,7 +2062,7 @@ opt_not (VALUE val) { extern VALUE rb_obj_not(VALUE obj); - const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic); + const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic, 0); if (check_cfunc(me, rb_obj_not)) { val = RTEST(recv) ? Qfalse : Qtrue; |