Feature #4085 » control_frame_change-r29944-20101127.diff
| class.c | ||
|---|---|---|
| 
     int 
   | 
||
| 
     rb_obj_basic_to_s_p(VALUE obj) 
   | 
||
| 
     { 
   | 
||
| 
         const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s")); 
   | 
||
| 
         const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"), 0); 
   | 
||
| 
         if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC && 
   | 
||
| 
     	me->def->body.cfunc.func == rb_any_to_s) 
   | 
||
| 
     	return 1; 
   | 
||
| insns.def | ||
|---|---|---|
| 
     	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)) { 
   | 
||
| ... | ... | |
| 
         /* enter scope */ 
   | 
||
| 
         vm_push_frame(th, class_iseq, 
   | 
||
| 
     		  VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(), 
   | 
||
| 
     		  VM_FRAME_MAGIC_CLASS, klass, 0, (VALUE) GET_BLOCK_PTR(), 
   | 
||
| 
     		  class_iseq->iseq_encoded, GET_SP(), 0, 
   | 
||
| 
     		  class_iseq->local_size); 
   | 
||
| 
         RESTORE_REGS(); 
   | 
||
| ... | ... | |
| 
     (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, 
   | 
||
| ... | ... | |
| 
         /* get receiver */ 
   | 
||
| 
         recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : 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); 
   | 
||
| 
     } 
   | 
||
| 
     /** 
   | 
||
| ... | ... | |
| 
         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); 
   | 
||
| 
     } 
   | 
||
| 
     /** 
   | 
||
| ... | ... | |
| 
     (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)) { 
   | 
||
| ... | ... | |
| 
     (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; 
   | 
||
| method.h | ||
|---|---|---|
| 
     void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex); 
   | 
||
| 
     rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex); 
   | 
||
| 
     rb_method_entry_t *rb_method_entry(VALUE klass, ID id); 
   | 
||
| 
     rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr); 
   | 
||
| 
     rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id); 
   | 
||
| 
     rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr); 
   | 
||
| 
     rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex); 
   | 
||
| 
     int rb_method_entry_arity(const rb_method_entry_t *me); 
   | 
||
| proc.c | ||
|---|---|---|
| 
     struct METHOD { 
   | 
||
| 
         VALUE recv; 
   | 
||
| 
         VALUE rclass; 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
         ID id; 
   | 
||
| 
         rb_method_entry_t me; 
   | 
||
| 
     }; 
   | 
||
| ... | ... | |
| 
     bm_mark(void *ptr) 
   | 
||
| 
     { 
   | 
||
| 
         struct METHOD *data = ptr; 
   | 
||
| 
         rb_gc_mark(data->defined_class); 
   | 
||
| 
         rb_gc_mark(data->rclass); 
   | 
||
| 
         rb_gc_mark(data->recv); 
   | 
||
| 
         rb_mark_method_entry(&data->me); 
   | 
||
| ... | ... | |
| 
     mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) 
   | 
||
| 
     { 
   | 
||
| 
         VALUE method; 
   | 
||
| 
         VALUE rclass = klass; 
   | 
||
| 
         VALUE rclass = klass, defined_class; 
   | 
||
| 
         ID rid = id; 
   | 
||
| 
         struct METHOD *data; 
   | 
||
| 
         rb_method_entry_t *me, meb; 
   | 
||
| ... | ... | |
| 
         rb_method_flag_t flag = NOEX_UNDEF; 
   | 
||
| 
       again: 
   | 
||
| 
         me = rb_method_entry(klass, id); 
   | 
||
| 
         me = rb_method_entry(klass, id, &defined_class); 
   | 
||
| 
         if (UNDEFINED_METHOD_ENTRY_P(me)) { 
   | 
||
| 
     	ID rmiss = rb_intern("respond_to_missing?"); 
   | 
||
| 
     	VALUE sym = ID2SYM(id); 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         if (def && def->type == VM_METHOD_TYPE_ZSUPER) { 
   | 
||
| 
     	klass = RCLASS_SUPER(me->klass); 
   | 
||
| 
     	klass = RCLASS_SUPER(defined_class); 
   | 
||
| 
     	id = def->original_id; 
   | 
||
| 
     	goto again; 
   | 
||
| 
         } 
   | 
||
| 
         klass = me->klass; 
   | 
||
| 
         klass = defined_class; 
   | 
||
| 
         while (rclass != klass && 
   | 
||
| 
     	   (FL_TEST(rclass, FL_SINGLETON) || TYPE(rclass) == T_ICLASS)) { 
   | 
||
| ... | ... | |
| 
         data->recv = obj; 
   | 
||
| 
         data->rclass = rclass; 
   | 
||
| 
         data->defined_class = defined_class; 
   | 
||
| 
         data->id = rid; 
   | 
||
| 
         data->me = *me; 
   | 
||
| 
         if (def) def->alias_count++; 
   | 
||
| ... | ... | |
| 
         data->me = orig->me; 
   | 
||
| 
         if (orig->me.def) orig->me.def->alias_count++; 
   | 
||
| 
         data->rclass = orig->rclass; 
   | 
||
| 
         data->defined_class = orig->defined_class; 
   | 
||
| 
         OBJ_INFECT(method, obj); 
   | 
||
| 
         return method; 
   | 
||
| ... | ... | |
| 
         if ((state = EXEC_TAG()) == 0) { 
   | 
||
| 
     	rb_thread_t *th = GET_THREAD(); 
   | 
||
| 
     	VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, 
   | 
||
| 
     			 const rb_method_entry_t *me); 
   | 
||
| 
     			 const rb_method_entry_t *me, VALUE defined_class); 
   | 
||
| 
     	PASS_PASSED_BLOCK_TH(th); 
   | 
||
| 
     	result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me); 
   | 
||
| 
     	result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me, data->defined_class); 
   | 
||
| 
         } 
   | 
||
| 
         POP_TAG(); 
   | 
||
| 
         if (safe >= 0) 
   | 
||
| ... | ... | |
| 
     int 
   | 
||
| 
     rb_mod_method_arity(VALUE mod, ID id) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me = rb_method_entry(mod, id); 
   | 
||
| 
         rb_method_entry_t *me = rb_method_entry(mod, id, 0); 
   | 
||
| 
         return rb_method_entry_arity(me); 
   | 
||
| 
     } 
   | 
||
| vm.c | ||
|---|---|---|
| 
     rb_vm_set_finish_env(rb_thread_t * th) 
   | 
||
| 
     { 
   | 
||
| 
         vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH, 
   | 
||
| 
     		  Qnil, th->cfp->lfp[0], 0, 
   | 
||
| 
     		  Qnil, Qnil, th->cfp->lfp[0], 0, 
   | 
||
| 
     		  th->cfp->sp, 0, 1); 
   | 
||
| 
         th->cfp->pc = (VALUE *)&finish_insn_seq[0]; 
   | 
||
| 
         return Qtrue; 
   | 
||
| ... | ... | |
| 
         rb_vm_set_finish_env(th); 
   | 
||
| 
         vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP, 
   | 
||
| 
     		  th->top_self, 0, iseq->iseq_encoded, 
   | 
||
| 
     		  th->top_self, rb_cObject, 0, iseq->iseq_encoded, 
   | 
||
| 
     		  th->cfp->sp, 0, iseq->local_size); 
   | 
||
| 
         CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); 
   | 
||
| ... | ... | |
| 
         /* for return */ 
   | 
||
| 
         rb_vm_set_finish_env(th); 
   | 
||
| 
         vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self, 
   | 
||
| 
         vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self, block->klass, 
   | 
||
| 
     		  GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded, 
   | 
||
| 
     		  th->cfp->sp, block->lfp, iseq->local_size); 
   | 
||
| ... | ... | |
| 
         GetProcPtr(procval, proc); 
   | 
||
| 
         proc->blockprocval = blockprocval; 
   | 
||
| 
         proc->block.self = block->self; 
   | 
||
| 
         proc->block.klass = block->klass; 
   | 
||
| 
         proc->block.lfp = block->lfp; 
   | 
||
| 
         proc->block.dfp = block->dfp; 
   | 
||
| 
         proc->block.iseq = block->iseq; 
   | 
||
| ... | ... | |
| 
     				     type == VM_FRAME_MAGIC_LAMBDA); 
   | 
||
| 
     	ncfp = vm_push_frame(th, iseq, type, 
   | 
||
| 
     			     self, GC_GUARDED_PTR(block->dfp), 
   | 
||
| 
     			     self, th->passed_defined_class, 
   | 
||
| 
     			     GC_GUARDED_PTR(block->dfp), 
   | 
||
| 
     			     iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp, 
   | 
||
| 
     			     iseq->local_size - arg_size); 
   | 
||
| 
     	th->passed_defined_class = 0; 
   | 
||
| 
     	ncfp->me = th->passed_me; 
   | 
||
| 
     	th->passed_me = 0; 
   | 
||
| 
     	th->passed_block = blockptr; 
   | 
||
| ... | ... | |
| 
     	    /* push block frame */ 
   | 
||
| 
     	    cfp->sp[0] = err; 
   | 
||
| 
     	    vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK, 
   | 
||
| 
     			  cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded, 
   | 
||
| 
     			  cfp->self, cfp->klass, 
   | 
||
| 
     			  (VALUE)cfp->dfp, catch_iseq->iseq_encoded, 
   | 
||
| 
     			  cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1); 
   | 
||
| 
     	    state = 0; 
   | 
||
| ... | ... | |
| 
         VALUE val; 
   | 
||
| 
         vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP, 
   | 
||
| 
     		  recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); 
   | 
||
| 
     		  recv, CLASS_OF(recv), (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); 
   | 
||
| 
         val = (*func)(arg); 
   | 
||
| ... | ... | |
| 
     	RUBY_MARK_UNLESS_NULL(th->root_fiber); 
   | 
||
| 
     	RUBY_MARK_UNLESS_NULL(th->stat_insn_usage); 
   | 
||
| 
     	RUBY_MARK_UNLESS_NULL(th->last_status); 
   | 
||
| 
     	RUBY_MARK_UNLESS_NULL(th->passed_defined_class); 
   | 
||
| 
     	RUBY_MARK_UNLESS_NULL(th->locking_mutex); 
   | 
||
| ... | ... | |
| 
         th->cfp = (void *)(th->stack + th->stack_size); 
   | 
||
| 
         vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0, 
   | 
||
| 
         vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, Qnil, 0, 0, 
   | 
||
| 
     		  th->stack, 0, 1); 
   | 
||
| 
         th->status = THREAD_RUNNABLE; 
   | 
||
| vm_core.h | ||
|---|---|---|
| 
     	rb_method_entry_t *method; 
   | 
||
| 
     	long index; 
   | 
||
| 
         } ic_value; 
   | 
||
| 
         union { 
   | 
||
| 
     	VALUE defined_class; 
   | 
||
| 
         } ic_value2; 
   | 
||
| 
     }; 
   | 
||
| 
     #if 1 
   | 
||
| ... | ... | |
| 
         VALUE *bp;			/* cfp[2] */ 
   | 
||
| 
         rb_iseq_t *iseq;		/* cfp[3] */ 
   | 
||
| 
         VALUE flag;			/* cfp[4] */ 
   | 
||
| 
         VALUE self;			/* cfp[5] / block[0] */ 
   | 
||
| 
         VALUE *lfp;			/* cfp[6] / block[1] */ 
   | 
||
| 
         VALUE *dfp;			/* cfp[7] / block[2] */ 
   | 
||
| 
         rb_iseq_t *block_iseq;	/* cfp[8] / block[3] */ 
   | 
||
| 
         VALUE proc;			/* cfp[9] / block[4] */ 
   | 
||
| 
         const rb_method_entry_t *me;/* cfp[10] */ 
   | 
||
| 
         VALUE self;			/* cfp[5]  / block[0] */ 
   | 
||
| 
         VALUE klass;		/* cfp[6]  / block[1] */ 
   | 
||
| 
         VALUE *lfp;			/* cfp[7]  / block[2] */ 
   | 
||
| 
         VALUE *dfp;			/* cfp[8]  / block[3] */ 
   | 
||
| 
         rb_iseq_t *block_iseq;	/* cfp[9]  / block[4] */ 
   | 
||
| 
         VALUE proc;			/* cfp[10] / block[5] */ 
   | 
||
| 
         const rb_method_entry_t *me;/* cfp[11] */ 
   | 
||
| 
     } rb_control_frame_t; 
   | 
||
| 
     typedef struct rb_block_struct { 
   | 
||
| 
         VALUE self;			/* share with method frame if it's only block */ 
   | 
||
| 
         VALUE klass;		/* share with method frame if it's only block */ 
   | 
||
| 
         VALUE *lfp;			/* share with method frame if it's only block */ 
   | 
||
| 
         VALUE *dfp;			/* share with method frame if it's only block */ 
   | 
||
| 
         rb_iseq_t *iseq; 
   | 
||
| ... | ... | |
| 
         /* for bmethod */ 
   | 
||
| 
         const rb_method_entry_t *passed_me; 
   | 
||
| 
         VALUE passed_defined_class; 
   | 
||
| 
         /* for load(true) */ 
   | 
||
| 
         VALUE top_self; 
   | 
||
| vm_eval.c | ||
|---|---|---|
| 
     static inline VALUE 
   | 
||
| 
     vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, 
   | 
||
| 
     	 const rb_method_entry_t *me) 
   | 
||
| 
     	 const rb_method_entry_t *me, VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         const rb_method_definition_t *def = me->def; 
   | 
||
| 
         VALUE val; 
   | 
||
| 
         VALUE klass = me->klass; 
   | 
||
| 
         VALUE klass = defined_class; 
   | 
||
| 
         const rb_block_t *blockptr = 0; 
   | 
||
| 
         if (!def) return Qnil; 
   | 
||
| ... | ... | |
| 
     	    *reg_cfp->sp++ = argv[i]; 
   | 
||
| 
     	} 
   | 
||
| 
     	vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me); 
   | 
||
| 
     	vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me, klass); 
   | 
||
| 
     	val = vm_exec(th); 
   | 
||
| 
     	break; 
   | 
||
| 
           } 
   | 
||
| ... | ... | |
| 
     	    rb_control_frame_t *reg_cfp = th->cfp; 
   | 
||
| 
     	    rb_control_frame_t *cfp = 
   | 
||
| 
     		vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, 
   | 
||
| 
     			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); 
   | 
||
| 
     			      recv, klass, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); 
   | 
||
| 
     	    cfp->me = me; 
   | 
||
| 
     	    val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv); 
   | 
||
| ... | ... | |
| 
     	break; 
   | 
||
| 
           } 
   | 
||
| 
           case VM_METHOD_TYPE_BMETHOD: { 
   | 
||
| 
     	val = vm_call_bmethod(th, recv, argc, argv, blockptr, me); 
   | 
||
| 
     	val = vm_call_bmethod(th, recv, argc, argv, blockptr, me, klass); 
   | 
||
| 
     	break; 
   | 
||
| 
           } 
   | 
||
| 
           case VM_METHOD_TYPE_ZSUPER: { 
   | 
||
| 
     	klass = RCLASS_SUPER(klass); 
   | 
||
| 
     	if (!klass || !(me = rb_method_entry(klass, id))) { 
   | 
||
| 
     	if (!klass || !(me = rb_method_entry(klass, id, &klass))) { 
   | 
||
| 
     	    return method_missing(recv, id, argc, argv, NOEX_SUPER); 
   | 
||
| 
     	} 
   | 
||
| 
     	RUBY_VM_CHECK_INTS(); 
   | 
||
| ... | ... | |
| 
     VALUE 
   | 
||
| 
     rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, 
   | 
||
| 
     	   const rb_method_entry_t *me) 
   | 
||
| 
     	   const rb_method_entry_t *me, VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         return vm_call0(th, recv, id, argc, argv, me); 
   | 
||
| 
         return vm_call0(th, recv, id, argc, argv, me, defined_class); 
   | 
||
| 
     } 
   | 
||
| 
     static inline VALUE 
   | 
||
| ... | ... | |
| 
         rb_method_entry_t *me; 
   | 
||
| 
         rb_control_frame_t *cfp = th->cfp; 
   | 
||
| 
         if (!cfp->iseq) { 
   | 
||
| 
     	klass = cfp->me->klass; 
   | 
||
| 
     	klass = RCLASS_SUPER(klass); 
   | 
||
| 
         if (!cfp->iseq && !NIL_P(cfp->klass)) { 
   | 
||
| 
     	klass = RCLASS_SUPER(cfp->klass); 
   | 
||
| 
     	if (klass == 0) { 
   | 
||
| 
     	    klass = vm_search_normal_superclass(cfp->me->klass, recv); 
   | 
||
| ... | ... | |
| 
     	rb_bug("vm_call_super: should not be reached"); 
   | 
||
| 
         } 
   | 
||
| 
         me = rb_method_entry(klass, id); 
   | 
||
| 
         me = rb_method_entry(klass, id, &klass); 
   | 
||
| 
         if (!me) { 
   | 
||
| 
     	return method_missing(recv, id, argc, argv, NOEX_SUPER); 
   | 
||
| 
         } 
   | 
||
| 
         return vm_call0(th, recv, id, argc, argv, me); 
   | 
||
| 
         return vm_call0(th, recv, id, argc, argv, me, klass); 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| ... | ... | |
| 
         } 
   | 
||
| 
     } 
   | 
||
| 
     static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid); 
   | 
||
| 
     static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr); 
   | 
||
| 
     static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self); 
   | 
||
| 
     #define NOEX_OK NOEX_NOSUPER 
   | 
||
| ... | ... | |
| 
     rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv, 
   | 
||
| 
     	 call_type scope, VALUE self) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me = rb_search_method_entry(recv, mid); 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
         rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class); 
   | 
||
| 
         rb_thread_t *th = GET_THREAD(); 
   | 
||
| 
         int call_status = rb_method_call_status(th, me, scope, self); 
   | 
||
| ... | ... | |
| 
     	return method_missing(recv, mid, argc, argv, call_status); 
   | 
||
| 
         } 
   | 
||
| 
         stack_check(); 
   | 
||
| 
         return vm_call0(th, recv, mid, argc, argv, me); 
   | 
||
| 
         return vm_call0(th, recv, mid, argc, argv, me, defined_class); 
   | 
||
| 
     } 
   | 
||
| 
     struct rescue_funcall_args { 
   | 
||
| ... | ... | |
| 
     static VALUE 
   | 
||
| 
     check_funcall(VALUE recv, ID mid, int argc, VALUE *argv) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me = rb_search_method_entry(recv, mid); 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
         rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class); 
   | 
||
| 
         rb_thread_t *th = GET_THREAD(); 
   | 
||
| 
         int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef); 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         stack_check(); 
   | 
||
| 
         return vm_call0(th, recv, mid, argc, argv, me); 
   | 
||
| 
         return vm_call0(th, recv, mid, argc, argv, me, defined_class); 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| ... | ... | |
| 
     } 
   | 
||
| 
     static inline rb_method_entry_t * 
   | 
||
| 
     rb_search_method_entry(VALUE recv, ID mid) 
   | 
||
| 
     rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr) 
   | 
||
| 
     { 
   | 
||
| 
         VALUE klass = CLASS_OF(recv); 
   | 
||
| ... | ... | |
| 
                              rb_id2name(mid), type, (void *)recv, flags, klass); 
   | 
||
| 
             } 
   | 
||
| 
         } 
   | 
||
| 
         return rb_method_entry(klass, mid); 
   | 
||
| 
         return rb_method_entry(klass, mid, defined_class_ptr); 
   | 
||
| 
     } 
   | 
||
| 
     static inline int 
   | 
||
| vm_insnhelper.c | ||
|---|---|---|
| 
     static inline rb_control_frame_t * 
   | 
||
| 
     vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq, 
   | 
||
| 
     	      VALUE type, VALUE self, VALUE specval, 
   | 
||
| 
     	      VALUE type, VALUE self, VALUE klass, VALUE specval, 
   | 
||
| 
     	      const VALUE *pc, VALUE *sp, VALUE *lfp, 
   | 
||
| 
     	      int local_size) 
   | 
||
| 
     { 
   | 
||
| ... | ... | |
| 
         cfp->block_iseq = 0; 
   | 
||
| 
         cfp->proc = 0; 
   | 
||
| 
         cfp->me = 0; 
   | 
||
| 
         if (klass) { 
   | 
||
| 
     	cfp->klass = klass; 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     	rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); 
   | 
||
| 
     	if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, prev_cfp)) { 
   | 
||
| 
     	    cfp->klass = Qnil; 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| 
     	    cfp->klass = prev_cfp->klass; 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
     #define COLLECT_PROFILE 0 
   | 
||
| 
     #if COLLECT_PROFILE 
   | 
||
| ... | ... | |
| 
     static inline VALUE 
   | 
||
| 
     vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, 
   | 
||
| 
     	      int num, VALUE recv, const rb_block_t *blockptr, 
   | 
||
| 
     	      const rb_method_entry_t *me) 
   | 
||
| 
     	      const rb_method_entry_t *me, VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         VALUE val = 0; 
   | 
||
| 
         const rb_method_definition_t *def = me->def; 
   | 
||
| ... | ... | |
| 
         EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass); 
   | 
||
| 
         cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, 
   | 
||
| 
     			recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1); 
   | 
||
| 
     			recv, defined_class, (VALUE) blockptr, 
   | 
||
| 
     		       	0, reg_cfp->sp, 0, 1); 
   | 
||
| 
         cfp->me = me; 
   | 
||
| 
         reg_cfp->sp -= num + 1; 
   | 
||
| ... | ... | |
| 
     static inline VALUE 
   | 
||
| 
     vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv, 
   | 
||
| 
     		const rb_block_t *blockptr, const rb_method_entry_t *me) 
   | 
||
| 
     		const rb_block_t *blockptr, const rb_method_entry_t *me, 
   | 
||
| 
     		VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         rb_proc_t *proc; 
   | 
||
| 
         VALUE val; 
   | 
||
| 
         /* control block frame */ 
   | 
||
| 
         th->passed_me = me; 
   | 
||
| 
         th->passed_defined_class = defined_class; 
   | 
||
| 
         GetProcPtr(me->def->body.proc, proc); 
   | 
||
| 
         val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr); 
   | 
||
| ... | ... | |
| 
     static inline void 
   | 
||
| 
     vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, 
   | 
||
| 
     		VALUE recv, int argc, const rb_block_t *blockptr, VALUE flag, 
   | 
||
| 
     		const rb_method_entry_t *me) 
   | 
||
| 
     		const rb_method_entry_t *me, VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         int opt_pc, i; 
   | 
||
| 
         VALUE *sp, *rsp = cfp->sp - argc; 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
     	vm_push_frame(th, iseq, 
   | 
||
| 
     		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, 
   | 
||
| 
     		      VM_FRAME_MAGIC_METHOD, recv, defined_class, 
   | 
||
| 
     		      (VALUE) blockptr, 
   | 
||
| 
     		      iseq->iseq_encoded + opt_pc, sp, 0, 0); 
   | 
||
| 
     	cfp->sp = rsp - 1 /* recv */; 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
     	vm_push_frame(th, iseq, 
   | 
||
| 
     		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, 
   | 
||
| 
     		      VM_FRAME_MAGIC_METHOD, recv, defined_class, 
   | 
||
| 
     		      (VALUE) blockptr, 
   | 
||
| 
     		      iseq->iseq_encoded + opt_pc, sp, 0, 0); 
   | 
||
| 
         } 
   | 
||
| 
     } 
   | 
||
| ... | ... | |
| 
     static inline VALUE 
   | 
||
| 
     vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, 
   | 
||
| 
     	       int num, const rb_block_t *blockptr, VALUE flag, 
   | 
||
| 
     	       ID id, const rb_method_entry_t *me, VALUE recv) 
   | 
||
| 
     	       ID id, const rb_method_entry_t *me, 
   | 
||
| 
     	       VALUE recv, VALUE defined_class) 
   | 
||
| 
     { 
   | 
||
| 
         VALUE val; 
   | 
||
| ... | ... | |
| 
     	  normal_method_dispatch: 
   | 
||
| 
     	    switch (me->def->type) { 
   | 
||
| 
     	      case VM_METHOD_TYPE_ISEQ:{ 
   | 
||
| 
     		vm_setup_method(th, cfp, recv, num, blockptr, flag, me); 
   | 
||
| 
     		vm_setup_method(th, cfp, recv, num, blockptr, flag, me, 
   | 
||
| 
     			       	defined_class); 
   | 
||
| 
     		return Qundef; 
   | 
||
| 
     	      } 
   | 
||
| 
     	      case VM_METHOD_TYPE_NOTIMPLEMENTED: 
   | 
||
| 
     	      case VM_METHOD_TYPE_CFUNC:{ 
   | 
||
| 
     		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me); 
   | 
||
| 
     		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me, 
   | 
||
| 
     				    defined_class); 
   | 
||
| 
     		break; 
   | 
||
| 
     	      } 
   | 
||
| 
     	      case VM_METHOD_TYPE_ATTRSET:{ 
   | 
||
| ... | ... | |
| 
     		VALUE *argv = ALLOCA_N(VALUE, num); 
   | 
||
| 
     		MEMCPY(argv, cfp->sp - num, VALUE, num); 
   | 
||
| 
     		cfp->sp += - num - 1; 
   | 
||
| 
     		val = vm_call_bmethod(th, recv, num, argv, blockptr, me); 
   | 
||
| 
     		val = vm_call_bmethod(th, recv, num, argv, blockptr, me, 
   | 
||
| 
     				      defined_class); 
   | 
||
| 
     		break; 
   | 
||
| 
     	      } 
   | 
||
| 
     	      case VM_METHOD_TYPE_ZSUPER:{ 
   | 
||
| 
     		VALUE klass = RCLASS_SUPER(me->klass); 
   | 
||
| 
     		me = rb_method_entry(klass, id); 
   | 
||
| 
     		me = rb_method_entry(klass, id, &defined_class); 
   | 
||
| 
     		if (me != 0) { 
   | 
||
| 
     		    goto normal_method_dispatch; 
   | 
||
| ... | ... | |
| 
     		    if (i > 0) { 
   | 
||
| 
     			MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); 
   | 
||
| 
     		    } 
   | 
||
| 
     		    me = rb_method_entry(CLASS_OF(recv), id); 
   | 
||
| 
     		    me = rb_method_entry(CLASS_OF(recv), id, &defined_class); 
   | 
||
| 
     		    num -= 1; 
   | 
||
| 
     		    DEC_SP(1); 
   | 
||
| 
     		    flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT; 
   | 
||
| ... | ... | |
| 
     		val = vm_method_missing(th, id, recv, num, blockptr, stat); 
   | 
||
| 
     	    } 
   | 
||
| 
     	    else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) { 
   | 
||
| 
     		VALUE defined_class = me->klass; 
   | 
||
| 
     		if (TYPE(defined_class) == T_ICLASS) { 
   | 
||
| 
     		    defined_class = RBASIC(defined_class)->klass; 
   | 
||
| 
     		} 
   | 
||
| ... | ... | |
| 
         } 
   | 
||
| 
         vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, 
   | 
||
| 
     		  self, (VALUE)block->dfp, 
   | 
||
| 
     		  self, 0, (VALUE)block->dfp, 
   | 
||
| 
     		  0, th->cfp->sp, block->lfp, 1); 
   | 
||
| 
         if (blockargptr) { 
   | 
||
| ... | ... | |
| 
     				     block_proc_is_lambda(block->proc)); 
   | 
||
| 
     	vm_push_frame(th, iseq, 
   | 
||
| 
     		      VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp, 
   | 
||
| 
     		      VM_FRAME_MAGIC_BLOCK, block->self, block->klass, 
   | 
||
| 
     		      (VALUE) block->dfp, 
   | 
||
| 
     		      iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp, 
   | 
||
| 
     		      iseq->local_size - arg_size); 
   | 
||
| ... | ... | |
| 
     } 
   | 
||
| 
     static inline const rb_method_entry_t * 
   | 
||
| 
     vm_method_search(VALUE id, VALUE klass, IC ic) 
   | 
||
| 
     vm_method_search(VALUE id, VALUE klass, IC ic, VALUE *defined_class_ptr) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me; 
   | 
||
| 
     #if OPT_INLINE_METHOD_CACHE 
   | 
||
| 
         if (LIKELY(klass == ic->ic_class) && 
   | 
||
| 
     	LIKELY(GET_VM_STATE_VERSION() == ic->ic_vmstat)) { 
   | 
||
| 
     	me = ic->ic_value.method; 
   | 
||
| 
     	if (defined_class_ptr) 
   | 
||
| 
     	    *defined_class_ptr = ic->ic_value2.defined_class; 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     	me = rb_method_entry(klass, id); 
   | 
||
| 
     	VALUE defined_class; 
   | 
||
| 
     	me = rb_method_entry(klass, id, &defined_class); 
   | 
||
| 
     	if (defined_class_ptr) 
   | 
||
| 
     	    *defined_class_ptr = defined_class; 
   | 
||
| 
     	ic->ic_class = klass; 
   | 
||
| 
     	ic->ic_value.method = me; 
   | 
||
| 
     	ic->ic_value2.defined_class = defined_class; 
   | 
||
| 
     	ic->ic_vmstat = GET_VM_STATE_VERSION(); 
   | 
||
| 
         } 
   | 
||
| 
     #else 
   | 
||
| 
         me = rb_method_entry(klass, id); 
   | 
||
| 
         me = rb_method_entry(klass, id, defined_class_ptr); 
   | 
||
| 
     #endif 
   | 
||
| 
         return me; 
   | 
||
| 
     } 
   | 
||
| ... | ... | |
| 
     static inline VALUE 
   | 
||
| 
     vm_search_normal_superclass(VALUE klass, VALUE recv) 
   | 
||
| 
     { 
   | 
||
| 
         if (BUILTIN_TYPE(klass) == T_CLASS) { 
   | 
||
| 
         if (BUILTIN_TYPE(klass) == T_CLASS || BUILTIN_TYPE(klass) == T_ICLASS) { 
   | 
||
| 
     	return RCLASS_SUPER(klass); 
   | 
||
| 
         } 
   | 
||
| 
         else if (BUILTIN_TYPE(klass) == T_MODULE) { 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
     	id = lcfp->me->def->original_id; 
   | 
||
| 
     	klass = vm_search_normal_superclass(lcfp->me->klass, recv); 
   | 
||
| 
     	klass = vm_search_normal_superclass(lcfp->klass, recv); 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     	klass = vm_search_normal_superclass(iseq->klass, recv); 
   | 
||
| 
     	klass = vm_search_normal_superclass(reg_cfp->klass, recv); 
   | 
||
| 
         } 
   | 
||
| 
         *idp = id; 
   | 
||
| ... | ... | |
| 
         } 
   | 
||
| 
         { 
   | 
||
| 
     	const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic); 
   | 
||
| 
     	const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic, 0); 
   | 
||
| 
     	extern VALUE rb_obj_equal(VALUE obj1, VALUE obj2); 
   | 
||
| 
     	if (check_cfunc(me, rb_obj_equal)) { 
   | 
||
| vm_insnhelper.h | ||
|---|---|---|
| 
       c1->nd_next = __tmp_c2->nd_next; \ 
   | 
||
| 
     } while (0) 
   | 
||
| 
     #define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \ 
   | 
||
| 
         VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, me, recv); \ 
   | 
||
| 
     #define CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class) do { \ 
   | 
||
| 
         VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, me, recv, defined_class); \ 
   | 
||
| 
         if (v == Qundef) { \ 
   | 
||
| 
     	RESTORE_REGS(); \ 
   | 
||
| 
     	NEXT_INSN(); \ 
   | 
||
| ... | ... | |
| 
     #if USE_IC_FOR_SPECIALIZED_METHOD 
   | 
||
| 
     #define CALL_SIMPLE_METHOD(num, id, recv) do { \ 
   | 
||
| 
         VALUE klass = CLASS_OF(recv); \ 
   | 
||
| 
         CALL_METHOD(num, 0, 0, id, vm_method_search(id, klass, ic), recv); \ 
   | 
||
| 
         VALUE klass = CLASS_OF(recv), defined_class; \ 
   | 
||
| 
         const rb_method_entry_t *me = vm_method_search(id, klass, ic, &defined_class); \ 
   | 
||
| 
         CALL_METHOD(num, 0, 0, id, me, recv, defined_class); \ 
   | 
||
| 
     } while (0) 
   | 
||
| 
     #else 
   | 
||
| vm_method.c | ||
|---|---|---|
| 
         ID mid;			/* method's id */ 
   | 
||
| 
         VALUE klass;		/* receiver's class */ 
   | 
||
| 
         rb_method_entry_t *me; 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
     }; 
   | 
||
| 
     static struct cache_entry cache[CACHE_SIZE]; 
   | 
||
| ... | ... | |
| 
     { 
   | 
||
| 
         rb_method_entry_t *me; 
   | 
||
| 
         Check_Type(klass, T_CLASS); 
   | 
||
| 
         me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR); 
   | 
||
| 
         me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR, 0); 
   | 
||
| 
         if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) { 
   | 
||
| 
     	return (rb_alloc_func_t)me->def->body.cfunc.func; 
   | 
||
| ... | ... | |
| 
     } 
   | 
||
| 
     static rb_method_entry_t* 
   | 
||
| 
     search_method(VALUE klass, ID id) 
   | 
||
| 
     search_method(VALUE klass, ID id, VALUE *defined_class_ptr) 
   | 
||
| 
     { 
   | 
||
| 
         st_data_t body; 
   | 
||
| 
         if (!klass) { 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         if (defined_class_ptr) 
   | 
||
| 
     	*defined_class_ptr = klass; 
   | 
||
| 
         return (rb_method_entry_t *)body; 
   | 
||
| 
     } 
   | 
||
| ... | ... | |
| 
      * rb_method_entry() simply. 
   | 
||
| 
      */ 
   | 
||
| 
     rb_method_entry_t * 
   | 
||
| 
     rb_method_entry_get_without_cache(VALUE klass, ID id) 
   | 
||
| 
     rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *defined_class_ptr) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me = search_method(klass, id); 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
         rb_method_entry_t *me; 
   | 
||
| 
         me = search_method(klass, id, &defined_class); 
   | 
||
| 
         if (ruby_running) { 
   | 
||
| 
     	struct cache_entry *ent; 
   | 
||
| 
     	ent = cache + EXPR1(klass, id); 
   | 
||
| 
     	ent->klass = klass; 
   | 
||
| 
     	ent->defined_class = defined_class; 
   | 
||
| 
     	if (UNDEFINED_METHOD_ENTRY_P(me)) { 
   | 
||
| 
     	    ent->mid = id; 
   | 
||
| ... | ... | |
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         if (defined_class_ptr) 
   | 
||
| 
     	*defined_class_ptr = defined_class; 
   | 
||
| 
         return me; 
   | 
||
| 
     } 
   | 
||
| 
     rb_method_entry_t * 
   | 
||
| 
     rb_method_entry(VALUE klass, ID id) 
   | 
||
| 
     rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr) 
   | 
||
| 
     { 
   | 
||
| 
         struct cache_entry *ent; 
   | 
||
| 
         ent = cache + EXPR1(klass, id); 
   | 
||
| 
         if (ent->mid == id && ent->klass == klass) { 
   | 
||
| 
     	if (defined_class_ptr) 
   | 
||
| 
     	    *defined_class_ptr = ent->defined_class; 
   | 
||
| 
     	return ent->me; 
   | 
||
| 
         } 
   | 
||
| 
         return rb_method_entry_get_without_cache(klass, id); 
   | 
||
| 
         return rb_method_entry_get_without_cache(klass, id, defined_class_ptr); 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| ... | ... | |
| 
     rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me; 
   | 
||
| 
         VALUE defined_class; 
   | 
||
| 
         if (klass == rb_cObject) { 
   | 
||
| 
     	rb_secure(4); 
   | 
||
| 
         } 
   | 
||
| 
         me = search_method(klass, name); 
   | 
||
| 
         me = search_method(klass, name, &defined_class); 
   | 
||
| 
         if (!me && TYPE(klass) == T_MODULE) { 
   | 
||
| 
     	me = search_method(rb_cObject, name); 
   | 
||
| 
     	me = search_method(rb_cObject, name, &defined_class); 
   | 
||
| 
         } 
   | 
||
| 
         if (UNDEFINED_METHOD_ENTRY_P(me)) { 
   | 
||
| ... | ... | |
| 
         if (me->flag != noex) { 
   | 
||
| 
     	rb_vm_check_redefinition_opt_method(me); 
   | 
||
| 
     	if (klass == me->klass) { 
   | 
||
| 
     	if (klass == defined_class) { 
   | 
||
| 
     	    me->flag = noex; 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| ... | ... | |
| 
     int 
   | 
||
| 
     rb_method_boundp(VALUE klass, ID id, int ex) 
   | 
||
| 
     { 
   | 
||
| 
         rb_method_entry_t *me = rb_method_entry(klass, id); 
   | 
||
| 
         rb_method_entry_t *me = rb_method_entry(klass, id, 0); 
   | 
||
| 
         if (me != 0) { 
   | 
||
| 
     	if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) { 
   | 
||
| ... | ... | |
| 
     	rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); 
   | 
||
| 
         } 
   | 
||
| 
         me = search_method(klass, id); 
   | 
||
| 
         me = search_method(klass, id, 0); 
   | 
||
| 
         if (UNDEFINED_METHOD_ENTRY_P(me)) { 
   | 
||
| 
     	const char *s0 = " class"; 
   | 
||
| ... | ... | |
| 
     check_definition(VALUE mod, ID mid, rb_method_flag_t noex) 
   | 
||
| 
     { 
   | 
||
| 
         const rb_method_entry_t *me; 
   | 
||
| 
         me = rb_method_entry(mod, mid); 
   | 
||
| 
         me = rb_method_entry(mod, mid, 0); 
   | 
||
| 
         if (me) { 
   | 
||
| 
     	if (VISI_CHECK(me->flag, noex)) 
   | 
||
| 
     	    return Qtrue; 
   | 
||
| ... | ... | |
| 
         } 
   | 
||
| 
       again: 
   | 
||
| 
         orig_me = search_method(klass, def); 
   | 
||
| 
         orig_me = search_method(klass, def, 0); 
   | 
||
| 
         if (UNDEFINED_METHOD_ENTRY_P(orig_me)) { 
   | 
||
| 
     	if ((TYPE(klass) != T_MODULE) || 
   | 
||
| 
     	    (orig_me = search_method(rb_cObject, def), UNDEFINED_METHOD_ENTRY_P(orig_me))) { 
   | 
||
| 
     	    (orig_me = search_method(rb_cObject, def, 0), 
   | 
||
| 
     				     UNDEFINED_METHOD_ENTRY_P(orig_me))) { 
   | 
||
| 
     	    rb_print_undef(klass, def, 0); 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| ... | ... | |
| 
     	id = rb_to_id(argv[i]); 
   | 
||
| 
     	for (;;) { 
   | 
||
| 
     	    me = search_method(m, id); 
   | 
||
| 
     	    me = search_method(m, id, 0); 
   | 
||
| 
     	    if (me == 0) { 
   | 
||
| 
     		me = search_method(rb_cObject, id); 
   | 
||
| 
     		me = search_method(rb_cObject, id, 0); 
   | 
||
| 
     	    } 
   | 
||
| 
     	    if (UNDEFINED_METHOD_ENTRY_P(me)) { 
   | 
||
| 
     		rb_print_undef(module, id, 0); 
   | 
||
| ... | ... | |
| 
     int 
   | 
||
| 
     rb_method_basic_definition_p(VALUE klass, ID id) 
   | 
||
| 
     { 
   | 
||
| 
         const rb_method_entry_t *me = rb_method_entry(klass, id); 
   | 
||
| 
         const rb_method_entry_t *me = rb_method_entry(klass, id, 0); 
   | 
||
| 
         if (me && (me->flag & NOEX_BASIC)) 
   | 
||
| 
     	return 1; 
   | 
||
| 
         return 0; 
   | 
||