Project

General

Profile

control_frame_change-r29944-20101127.diff

a patch to add klass to rb_control_frame_t - shugo (Shugo Maeda), 11/27/2010 01:39 PM

View differences:

class.c
1387 1387
int
1388 1388
rb_obj_basic_to_s_p(VALUE obj)
1389 1389
{
1390
    const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
1390
    const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"), 0);
1391 1391
    if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
1392 1392
	me->def->body.cfunc.func == rb_any_to_s)
1393 1393
	return 1;
insns.def
792 792
	break;
793 793
      case DEFINED_METHOD:{
794 794
	VALUE klass = CLASS_OF(v);
795
	const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj));
795
	const rb_method_entry_t *me = rb_method_entry(klass, SYM2ID(obj), 0);
796 796

  
797 797
	if (me) {
798 798
	    if (!(me->flag & NOEX_PRIVATE)) {
......
964 964

  
965 965
    /* enter scope */
966 966
    vm_push_frame(th, class_iseq,
967
		  VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(),
967
		  VM_FRAME_MAGIC_CLASS, klass, 0, (VALUE) GET_BLOCK_PTR(),
968 968
		  class_iseq->iseq_encoded, GET_SP(), 0,
969 969
		  class_iseq->local_size);
970 970
    RESTORE_REGS();
......
996 996
(VALUE val) // inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
997 997
{
998 998
    const rb_method_entry_t *me;
999
    VALUE recv, klass;
999
    VALUE recv, klass, defined_class;
1000 1000
    rb_block_t *blockptr = 0;
1001 1001
    VALUE flag = op_flag;
1002 1002
    int num = caller_setup_args(th, GET_CFP(), flag, (int)op_argc,
......
1006 1006
    /* get receiver */
1007 1007
    recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
1008 1008
    klass = CLASS_OF(recv);
1009
    me = vm_method_search(id, klass, ic);
1010
    CALL_METHOD(num, blockptr, flag, id, me, recv);
1009
    me = vm_method_search(id, klass, ic, &defined_class);
1010
    CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class);
1011 1011
}
1012 1012

  
1013 1013
/**
......
1030 1030
    VALUE recv, klass;
1031 1031
    ID id;
1032 1032
    const rb_method_entry_t *me;
1033
    rb_iseq_t *ip;
1033 1034

  
1034 1035
    flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
1035 1036

  
1036 1037
    recv = GET_SELF();
1037 1038
    vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass);
1038 1039

  
1039
    /* temporary measure for [Bug #2402] [Bug #2502] [Bug #3136] */
1040
    if (!rb_obj_is_kind_of(recv, klass)) {
1041
	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");
1040
    ip = GET_ISEQ();
1041
    while (ip && !ip->klass) {
1042
	ip = ip->parent_iseq;
1043
    }
1044
  again:
1045
    me = rb_method_entry(klass, id, &klass);
1046
    if (me && me->def->type == VM_METHOD_TYPE_ISEQ &&
1047
	me->def->body.iseq == ip) {
1048
	klass = RCLASS_SUPER(klass);
1049
	goto again;
1042 1050
    }
1043 1051

  
1044
    me = rb_method_entry(klass, id);
1045

  
1046
    CALL_METHOD(num, blockptr, flag, id, me, recv);
1052
    CALL_METHOD(num, blockptr, flag, id, me, recv, klass);
1047 1053
}
1048 1054

  
1049 1055
/**
......
1668 1674
(VALUE val)
1669 1675
{
1670 1676
    extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
1671
    const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic);
1677
    const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic, 0);
1672 1678
    val = Qundef;
1673 1679

  
1674 1680
    if (check_cfunc(me, rb_obj_not_equal)) {
......
2069 2075
(VALUE val)
2070 2076
{
2071 2077
    extern VALUE rb_obj_not(VALUE obj);
2072
    const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic);
2078
    const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic, 0);
2073 2079

  
2074 2080
    if (check_cfunc(me, rb_obj_not)) {
2075 2081
	val = RTEST(recv) ? Qfalse : Qtrue;
method.h
89 89

  
90 90
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
91 91
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
92
rb_method_entry_t *rb_method_entry(VALUE klass, ID id);
92
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
93 93

  
94
rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id);
94
rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr);
95 95
rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex);
96 96

  
97 97
int rb_method_entry_arity(const rb_method_entry_t *me);
proc.c
15 15
struct METHOD {
16 16
    VALUE recv;
17 17
    VALUE rclass;
18
    VALUE defined_class;
18 19
    ID id;
19 20
    rb_method_entry_t me;
20 21
};
......
861 862
bm_mark(void *ptr)
862 863
{
863 864
    struct METHOD *data = ptr;
865
    rb_gc_mark(data->defined_class);
864 866
    rb_gc_mark(data->rclass);
865 867
    rb_gc_mark(data->recv);
866 868
    rb_mark_method_entry(&data->me);
......
903 905
mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
904 906
{
905 907
    VALUE method;
906
    VALUE rclass = klass;
908
    VALUE rclass = klass, defined_class;
907 909
    ID rid = id;
908 910
    struct METHOD *data;
909 911
    rb_method_entry_t *me, meb;
......
911 913
    rb_method_flag_t flag = NOEX_UNDEF;
912 914

  
913 915
  again:
914
    me = rb_method_entry(klass, id);
916
    me = rb_method_entry(klass, id, &defined_class);
915 917
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
916 918
	ID rmiss = rb_intern("respond_to_missing?");
917 919
	VALUE sym = ID2SYM(id);
......
953 955
	}
954 956
    }
955 957
    if (def && def->type == VM_METHOD_TYPE_ZSUPER) {
956
	klass = RCLASS_SUPER(me->klass);
958
	klass = RCLASS_SUPER(defined_class);
957 959
	id = def->original_id;
958 960
	goto again;
959 961
    }
960 962

  
961
    klass = me->klass;
963
    klass = defined_class;
962 964

  
963 965
    while (rclass != klass &&
964 966
	   (FL_TEST(rclass, FL_SINGLETON) || TYPE(rclass) == T_ICLASS)) {
......
974 976

  
975 977
    data->recv = obj;
976 978
    data->rclass = rclass;
979
    data->defined_class = defined_class;
977 980
    data->id = rid;
978 981
    data->me = *me;
979 982
    if (def) def->alias_count++;
......
1085 1088
    data->me = orig->me;
1086 1089
    if (orig->me.def) orig->me.def->alias_count++;
1087 1090
    data->rclass = orig->rclass;
1091
    data->defined_class = orig->defined_class;
1088 1092
    OBJ_INFECT(method, obj);
1089 1093

  
1090 1094
    return method;
......
1421 1425
    if ((state = EXEC_TAG()) == 0) {
1422 1426
	rb_thread_t *th = GET_THREAD();
1423 1427
	VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
1424
			 const rb_method_entry_t *me);
1428
			 const rb_method_entry_t *me, VALUE defined_class);
1425 1429

  
1426 1430
	PASS_PASSED_BLOCK_TH(th);
1427
	result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me);
1431
	result = rb_vm_call(th, data->recv, data->id,  argc, argv, &data->me, data->defined_class);
1428 1432
    }
1429 1433
    POP_TAG();
1430 1434
    if (safe >= 0)
......
1648 1652
int
1649 1653
rb_mod_method_arity(VALUE mod, ID id)
1650 1654
{
1651
    rb_method_entry_t *me = rb_method_entry(mod, id);
1655
    rb_method_entry_t *me = rb_method_entry(mod, id, 0);
1652 1656
    return rb_method_entry_arity(me);
1653 1657
}
1654 1658

  
vm.c
70 70
rb_vm_set_finish_env(rb_thread_t * th)
71 71
{
72 72
    vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH,
73
		  Qnil, th->cfp->lfp[0], 0,
73
		  Qnil, Qnil, th->cfp->lfp[0], 0,
74 74
		  th->cfp->sp, 0, 1);
75 75
    th->cfp->pc = (VALUE *)&finish_insn_seq[0];
76 76
    return Qtrue;
......
90 90
    rb_vm_set_finish_env(th);
91 91

  
92 92
    vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP,
93
		  th->top_self, 0, iseq->iseq_encoded,
93
		  th->top_self, rb_cObject, 0, iseq->iseq_encoded,
94 94
		  th->cfp->sp, 0, iseq->local_size);
95 95

  
96 96
    CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
......
105 105

  
106 106
    /* for return */
107 107
    rb_vm_set_finish_env(th);
108
    vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self,
108
    vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self, block->klass,
109 109
		  GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
110 110
		  th->cfp->sp, block->lfp, iseq->local_size);
111 111

  
......
490 490
    GetProcPtr(procval, proc);
491 491
    proc->blockprocval = blockprocval;
492 492
    proc->block.self = block->self;
493
    proc->block.klass = block->klass;
493 494
    proc->block.lfp = block->lfp;
494 495
    proc->block.dfp = block->dfp;
495 496
    proc->block.iseq = block->iseq;
......
539 540
				     type == VM_FRAME_MAGIC_LAMBDA);
540 541

  
541 542
	ncfp = vm_push_frame(th, iseq, type,
542
			     self, GC_GUARDED_PTR(block->dfp),
543
			     self, th->passed_defined_class,
544
			     GC_GUARDED_PTR(block->dfp),
543 545
			     iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
544 546
			     iseq->local_size - arg_size);
547
	th->passed_defined_class = 0;
545 548
	ncfp->me = th->passed_me;
546 549
	th->passed_me = 0;
547 550
	th->passed_block = blockptr;
......
1317 1320
	    /* push block frame */
1318 1321
	    cfp->sp[0] = err;
1319 1322
	    vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
1320
			  cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
1323
			  cfp->self, cfp->klass,
1324
			  (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
1321 1325
			  cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
1322 1326

  
1323 1327
	    state = 0;
......
1455 1459
    VALUE val;
1456 1460

  
1457 1461
    vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
1458
		  recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
1462
		  recv, CLASS_OF(recv), (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
1459 1463

  
1460 1464
    val = (*func)(arg);
1461 1465

  
......
1668 1672
	RUBY_MARK_UNLESS_NULL(th->root_fiber);
1669 1673
	RUBY_MARK_UNLESS_NULL(th->stat_insn_usage);
1670 1674
	RUBY_MARK_UNLESS_NULL(th->last_status);
1675
	RUBY_MARK_UNLESS_NULL(th->passed_defined_class);
1671 1676

  
1672 1677
	RUBY_MARK_UNLESS_NULL(th->locking_mutex);
1673 1678

  
......
1779 1784

  
1780 1785
    th->cfp = (void *)(th->stack + th->stack_size);
1781 1786

  
1782
    vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0,
1787
    vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, Qnil, 0, 0,
1783 1788
		  th->stack, 0, 1);
1784 1789

  
1785 1790
    th->status = THREAD_RUNNABLE;
vm_core.h
132 132
	rb_method_entry_t *method;
133 133
	long index;
134 134
    } ic_value;
135
    union {
136
	VALUE defined_class;
137
    } ic_value2;
135 138
};
136 139

  
137 140
#if 1
......
325 328
    VALUE *bp;			/* cfp[2] */
326 329
    rb_iseq_t *iseq;		/* cfp[3] */
327 330
    VALUE flag;			/* cfp[4] */
328
    VALUE self;			/* cfp[5] / block[0] */
329
    VALUE *lfp;			/* cfp[6] / block[1] */
330
    VALUE *dfp;			/* cfp[7] / block[2] */
331
    rb_iseq_t *block_iseq;	/* cfp[8] / block[3] */
332
    VALUE proc;			/* cfp[9] / block[4] */
333
    const rb_method_entry_t *me;/* cfp[10] */
331
    VALUE self;			/* cfp[5]  / block[0] */
332
    VALUE klass;		/* cfp[6]  / block[1] */
333
    VALUE *lfp;			/* cfp[7]  / block[2] */
334
    VALUE *dfp;			/* cfp[8]  / block[3] */
335
    rb_iseq_t *block_iseq;	/* cfp[9]  / block[4] */
336
    VALUE proc;			/* cfp[10] / block[5] */
337
    const rb_method_entry_t *me;/* cfp[11] */
334 338
} rb_control_frame_t;
335 339

  
336 340
typedef struct rb_block_struct {
337 341
    VALUE self;			/* share with method frame if it's only block */
342
    VALUE klass;		/* share with method frame if it's only block */
338 343
    VALUE *lfp;			/* share with method frame if it's only block */
339 344
    VALUE *dfp;			/* share with method frame if it's only block */
340 345
    rb_iseq_t *iseq;
......
392 397

  
393 398
    /* for bmethod */
394 399
    const rb_method_entry_t *passed_me;
400
    VALUE passed_defined_class;
395 401

  
396 402
    /* for load(true) */
397 403
    VALUE top_self;
vm_eval.c
33 33

  
34 34
static inline VALUE
35 35
vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
36
	 const rb_method_entry_t *me)
36
	 const rb_method_entry_t *me, VALUE defined_class)
37 37
{
38 38
    const rb_method_definition_t *def = me->def;
39 39
    VALUE val;
40
    VALUE klass = me->klass;
40
    VALUE klass = defined_class;
41 41
    const rb_block_t *blockptr = 0;
42 42

  
43 43
    if (!def) return Qnil;
......
62 62
	    *reg_cfp->sp++ = argv[i];
63 63
	}
64 64

  
65
	vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me);
65
	vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me, klass);
66 66
	val = vm_exec(th);
67 67
	break;
68 68
      }
......
73 73
	    rb_control_frame_t *reg_cfp = th->cfp;
74 74
	    rb_control_frame_t *cfp =
75 75
		vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
76
			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
76
			      recv, klass, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
77 77

  
78 78
	    cfp->me = me;
79 79
	    val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
......
101 101
	break;
102 102
      }
103 103
      case VM_METHOD_TYPE_BMETHOD: {
104
	val = vm_call_bmethod(th, recv, argc, argv, blockptr, me);
104
	val = vm_call_bmethod(th, recv, argc, argv, blockptr, me, klass);
105 105
	break;
106 106
      }
107 107
      case VM_METHOD_TYPE_ZSUPER: {
108 108
	klass = RCLASS_SUPER(klass);
109
	if (!klass || !(me = rb_method_entry(klass, id))) {
109
	if (!klass || !(me = rb_method_entry(klass, id, &klass))) {
110 110
	    return method_missing(recv, id, argc, argv, NOEX_SUPER);
111 111
	}
112 112
	RUBY_VM_CHECK_INTS();
......
149 149

  
150 150
VALUE
151 151
rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv,
152
	   const rb_method_entry_t *me)
152
	   const rb_method_entry_t *me, VALUE defined_class)
153 153
{
154
    return vm_call0(th, recv, id, argc, argv, me);
154
    return vm_call0(th, recv, id, argc, argv, me, defined_class);
155 155
}
156 156

  
157 157
static inline VALUE
......
163 163
    rb_method_entry_t *me;
164 164
    rb_control_frame_t *cfp = th->cfp;
165 165

  
166
    if (!cfp->iseq) {
167
	klass = cfp->me->klass;
168
	klass = RCLASS_SUPER(klass);
166
    if (!cfp->iseq && !NIL_P(cfp->klass)) {
167
	klass = RCLASS_SUPER(cfp->klass);
169 168

  
170 169
	if (klass == 0) {
171 170
	    klass = vm_search_normal_superclass(cfp->me->klass, recv);
......
176 175
	rb_bug("vm_call_super: should not be reached");
177 176
    }
178 177

  
179
    me = rb_method_entry(klass, id);
178
    me = rb_method_entry(klass, id, &klass);
180 179
    if (!me) {
181 180
	return method_missing(recv, id, argc, argv, NOEX_SUPER);
182 181
    }
183 182

  
184
    return vm_call0(th, recv, id, argc, argv, me);
183
    return vm_call0(th, recv, id, argc, argv, me, klass);
185 184
}
186 185

  
187 186
VALUE
......
202 201
    }
203 202
}
204 203

  
205
static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
204
static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr);
206 205
static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self);
207 206
#define NOEX_OK NOEX_NOSUPER
208 207

  
......
224 223
rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
225 224
	 call_type scope, VALUE self)
226 225
{
227
    rb_method_entry_t *me = rb_search_method_entry(recv, mid);
226
    VALUE defined_class;
227
    rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class);
228 228
    rb_thread_t *th = GET_THREAD();
229 229
    int call_status = rb_method_call_status(th, me, scope, self);
230 230

  
......
232 232
	return method_missing(recv, mid, argc, argv, call_status);
233 233
    }
234 234
    stack_check();
235
    return vm_call0(th, recv, mid, argc, argv, me);
235
    return vm_call0(th, recv, mid, argc, argv, me, defined_class);
236 236
}
237 237

  
238 238
struct rescue_funcall_args {
......
265 265
static VALUE
266 266
check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
267 267
{
268
    rb_method_entry_t *me = rb_search_method_entry(recv, mid);
268
    VALUE defined_class;
269
    rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class);
269 270
    rb_thread_t *th = GET_THREAD();
270 271
    int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
271 272

  
......
287 288
	}
288 289
    }
289 290
    stack_check();
290
    return vm_call0(th, recv, mid, argc, argv, me);
291
    return vm_call0(th, recv, mid, argc, argv, me, defined_class);
291 292
}
292 293

  
293 294
VALUE
......
332 333
}
333 334

  
334 335
static inline rb_method_entry_t *
335
rb_search_method_entry(VALUE recv, ID mid)
336
rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr)
336 337
{
337 338
    VALUE klass = CLASS_OF(recv);
338 339

  
......
371 372
                         rb_id2name(mid), type, (void *)recv, flags, klass);
372 373
        }
373 374
    }
374
    return rb_method_entry(klass, mid);
375
    return rb_method_entry(klass, mid, defined_class_ptr);
375 376
}
376 377

  
377 378
static inline int
vm_insnhelper.c
23 23

  
24 24
static inline rb_control_frame_t *
25 25
vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq,
26
	      VALUE type, VALUE self, VALUE specval,
26
	      VALUE type, VALUE self, VALUE klass, VALUE specval,
27 27
	      const VALUE *pc, VALUE *sp, VALUE *lfp,
28 28
	      int local_size)
29 29
{
......
62 62
    cfp->block_iseq = 0;
63 63
    cfp->proc = 0;
64 64
    cfp->me = 0;
65
    if (klass) {
66
	cfp->klass = klass;
67
    }
68
    else {
69
	rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
70
	if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, prev_cfp)) {
71
	    cfp->klass = Qnil;
72
	}
73
	else {
74
	    cfp->klass = prev_cfp->klass;
75
	}
76
    }
65 77

  
66 78
#define COLLECT_PROFILE 0
67 79
#if COLLECT_PROFILE
......
387 399
static inline VALUE
388 400
vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
389 401
	      int num, VALUE recv, const rb_block_t *blockptr,
390
	      const rb_method_entry_t *me)
402
	      const rb_method_entry_t *me, VALUE defined_class)
391 403
{
392 404
    VALUE val = 0;
393 405
    const rb_method_definition_t *def = me->def;
......
396 408
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
397 409

  
398 410
    cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
399
			recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
411
			recv, defined_class, (VALUE) blockptr,
412
		       	0, reg_cfp->sp, 0, 1);
400 413
    cfp->me = me;
401 414
    reg_cfp->sp -= num + 1;
402 415

  
......
415 428

  
416 429
static inline VALUE
417 430
vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv,
418
		const rb_block_t *blockptr, const rb_method_entry_t *me)
431
		const rb_block_t *blockptr, const rb_method_entry_t *me,
432
		VALUE defined_class)
419 433
{
420 434
    rb_proc_t *proc;
421 435
    VALUE val;
422 436

  
423 437
    /* control block frame */
424 438
    th->passed_me = me;
439
    th->passed_defined_class = defined_class;
425 440

  
426 441
    GetProcPtr(me->def->body.proc, proc);
427 442
    val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr);
......
452 467
static inline void
453 468
vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
454 469
		VALUE recv, int argc, const rb_block_t *blockptr, VALUE flag,
455
		const rb_method_entry_t *me)
470
		const rb_method_entry_t *me, VALUE defined_class)
456 471
{
457 472
    int opt_pc, i;
458 473
    VALUE *sp, *rsp = cfp->sp - argc;
......
475 490
	}
476 491

  
477 492
	vm_push_frame(th, iseq,
478
		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
493
		      VM_FRAME_MAGIC_METHOD, recv, defined_class,
494
		      (VALUE) blockptr,
479 495
		      iseq->iseq_encoded + opt_pc, sp, 0, 0);
480 496

  
481 497
	cfp->sp = rsp - 1 /* recv */;
......
498 514
	}
499 515

  
500 516
	vm_push_frame(th, iseq,
501
		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
517
		      VM_FRAME_MAGIC_METHOD, recv, defined_class,
518
		      (VALUE) blockptr,
502 519
		      iseq->iseq_encoded + opt_pc, sp, 0, 0);
503 520
    }
504 521
}
......
506 523
static inline VALUE
507 524
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
508 525
	       int num, const rb_block_t *blockptr, VALUE flag,
509
	       ID id, const rb_method_entry_t *me, VALUE recv)
526
	       ID id, const rb_method_entry_t *me,
527
	       VALUE recv, VALUE defined_class)
510 528
{
511 529
    VALUE val;
512 530

  
......
517 535
	  normal_method_dispatch:
518 536
	    switch (me->def->type) {
519 537
	      case VM_METHOD_TYPE_ISEQ:{
520
		vm_setup_method(th, cfp, recv, num, blockptr, flag, me);
538
		vm_setup_method(th, cfp, recv, num, blockptr, flag, me,
539
			       	defined_class);
521 540
		return Qundef;
522 541
	      }
523 542
	      case VM_METHOD_TYPE_NOTIMPLEMENTED:
524 543
	      case VM_METHOD_TYPE_CFUNC:{
525
		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me);
544
		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me,
545
				    defined_class);
526 546
		break;
527 547
	      }
528 548
	      case VM_METHOD_TYPE_ATTRSET:{
......
553 573
		VALUE *argv = ALLOCA_N(VALUE, num);
554 574
		MEMCPY(argv, cfp->sp - num, VALUE, num);
555 575
		cfp->sp += - num - 1;
556
		val = vm_call_bmethod(th, recv, num, argv, blockptr, me);
576
		val = vm_call_bmethod(th, recv, num, argv, blockptr, me,
577
				      defined_class);
557 578
		break;
558 579
	      }
559 580
	      case VM_METHOD_TYPE_ZSUPER:{
560 581
		VALUE klass = RCLASS_SUPER(me->klass);
561
		me = rb_method_entry(klass, id);
582
		me = rb_method_entry(klass, id, &defined_class);
562 583

  
563 584
		if (me != 0) {
564 585
		    goto normal_method_dispatch;
......
584 605
		    if (i > 0) {
585 606
			MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
586 607
		    }
587
		    me = rb_method_entry(CLASS_OF(recv), id);
608
		    me = rb_method_entry(CLASS_OF(recv), id, &defined_class);
588 609
		    num -= 1;
589 610
		    DEC_SP(1);
590 611
		    flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT;
......
627 648
		val = vm_method_missing(th, id, recv, num, blockptr, stat);
628 649
	    }
629 650
	    else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
630
		VALUE defined_class = me->klass;
631

  
632 651
		if (TYPE(defined_class) == T_ICLASS) {
633 652
		    defined_class = RBASIC(defined_class)->klass;
634 653
		}
......
720 739
    }
721 740

  
722 741
    vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
723
		  self, (VALUE)block->dfp,
742
		  self, 0, (VALUE)block->dfp,
724 743
		  0, th->cfp->sp, block->lfp, 1);
725 744

  
726 745
    if (blockargptr) {
......
938 957
				     block_proc_is_lambda(block->proc));
939 958

  
940 959
	vm_push_frame(th, iseq,
941
		      VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
960
		      VM_FRAME_MAGIC_BLOCK, block->self, block->klass,
961
		      (VALUE) block->dfp,
942 962
		      iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
943 963
		      iseq->local_size - arg_size);
944 964

  
......
1333 1353
}
1334 1354

  
1335 1355
static inline const rb_method_entry_t *
1336
vm_method_search(VALUE id, VALUE klass, IC ic)
1356
vm_method_search(VALUE id, VALUE klass, IC ic, VALUE *defined_class_ptr)
1337 1357
{
1338 1358
    rb_method_entry_t *me;
1339 1359
#if OPT_INLINE_METHOD_CACHE
1340 1360
    if (LIKELY(klass == ic->ic_class) &&
1341 1361
	LIKELY(GET_VM_STATE_VERSION() == ic->ic_vmstat)) {
1342 1362
	me = ic->ic_value.method;
1363
	if (defined_class_ptr)
1364
	    *defined_class_ptr = ic->ic_value2.defined_class;
1343 1365
    }
1344 1366
    else {
1345
	me = rb_method_entry(klass, id);
1367
	VALUE defined_class;
1368
	me = rb_method_entry(klass, id, &defined_class);
1369
	if (defined_class_ptr)
1370
	    *defined_class_ptr = defined_class;
1346 1371
	ic->ic_class = klass;
1347 1372
	ic->ic_value.method = me;
1373
	ic->ic_value2.defined_class = defined_class;
1348 1374
	ic->ic_vmstat = GET_VM_STATE_VERSION();
1349 1375
    }
1350 1376
#else
1351
    me = rb_method_entry(klass, id);
1377
    me = rb_method_entry(klass, id, defined_class_ptr);
1352 1378
#endif
1353 1379
    return me;
1354 1380
}
......
1356 1382
static inline VALUE
1357 1383
vm_search_normal_superclass(VALUE klass, VALUE recv)
1358 1384
{
1359
    if (BUILTIN_TYPE(klass) == T_CLASS) {
1385
    if (BUILTIN_TYPE(klass) == T_CLASS || BUILTIN_TYPE(klass) == T_ICLASS) {
1360 1386
	return RCLASS_SUPER(klass);
1361 1387
    }
1362 1388
    else if (BUILTIN_TYPE(klass) == T_MODULE) {
......
1417 1443
	}
1418 1444

  
1419 1445
	id = lcfp->me->def->original_id;
1420
	klass = vm_search_normal_superclass(lcfp->me->klass, recv);
1446
	klass = vm_search_normal_superclass(lcfp->klass, recv);
1421 1447
    }
1422 1448
    else {
1423
	klass = vm_search_normal_superclass(iseq->klass, recv);
1449
	klass = vm_search_normal_superclass(reg_cfp->klass, recv);
1424 1450
    }
1425 1451

  
1426 1452
    *idp = id;
......
1690 1716
    }
1691 1717

  
1692 1718
    {
1693
	const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic);
1719
	const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic, 0);
1694 1720
	extern VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
1695 1721

  
1696 1722
	if (check_cfunc(me, rb_obj_equal)) {
vm_insnhelper.h
156 156
  c1->nd_next = __tmp_c2->nd_next; \
157 157
} while (0)
158 158

  
159
#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \
160
    VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, me, recv); \
159
#define CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class) do { \
160
    VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, me, recv, defined_class); \
161 161
    if (v == Qundef) { \
162 162
	RESTORE_REGS(); \
163 163
	NEXT_INSN(); \
......
192 192
#if USE_IC_FOR_SPECIALIZED_METHOD
193 193

  
194 194
#define CALL_SIMPLE_METHOD(num, id, recv) do { \
195
    VALUE klass = CLASS_OF(recv); \
196
    CALL_METHOD(num, 0, 0, id, vm_method_search(id, klass, ic), recv); \
195
    VALUE klass = CLASS_OF(recv), defined_class; \
196
    const rb_method_entry_t *me = vm_method_search(id, klass, ic, &defined_class); \
197
    CALL_METHOD(num, 0, 0, id, me, recv, defined_class); \
197 198
} while (0)
198 199

  
199 200
#else
vm_method.c
16 16
    ID mid;			/* method's id */
17 17
    VALUE klass;		/* receiver's class */
18 18
    rb_method_entry_t *me;
19
    VALUE defined_class;
19 20
};
20 21

  
21 22
static struct cache_entry cache[CACHE_SIZE];
......
381 382
{
382 383
    rb_method_entry_t *me;
383 384
    Check_Type(klass, T_CLASS);
384
    me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR);
385
    me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR, 0);
385 386

  
386 387
    if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) {
387 388
	return (rb_alloc_func_t)me->def->body.cfunc.func;
......
392 393
}
393 394

  
394 395
static rb_method_entry_t*
395
search_method(VALUE klass, ID id)
396
search_method(VALUE klass, ID id, VALUE *defined_class_ptr)
396 397
{
397 398
    st_data_t body;
398 399
    if (!klass) {
......
406 407
	}
407 408
    }
408 409

  
410
    if (defined_class_ptr)
411
	*defined_class_ptr = klass;
409 412
    return (rb_method_entry_t *)body;
410 413
}
411 414

  
......
416 419
 * rb_method_entry() simply.
417 420
 */
418 421
rb_method_entry_t *
419
rb_method_entry_get_without_cache(VALUE klass, ID id)
422
rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *defined_class_ptr)
420 423
{
421
    rb_method_entry_t *me = search_method(klass, id);
424
    VALUE defined_class;
425
    rb_method_entry_t *me;
426

  
427
    me = search_method(klass, id, &defined_class);
422 428

  
423 429
    if (ruby_running) {
424 430
	struct cache_entry *ent;
425 431
	ent = cache + EXPR1(klass, id);
426 432
	ent->klass = klass;
433
	ent->defined_class = defined_class;
427 434

  
428 435
	if (UNDEFINED_METHOD_ENTRY_P(me)) {
429 436
	    ent->mid = id;
......
436 443
	}
437 444
    }
438 445

  
446
    if (defined_class_ptr)
447
	*defined_class_ptr = defined_class;
439 448
    return me;
440 449
}
441 450

  
442 451
rb_method_entry_t *
443
rb_method_entry(VALUE klass, ID id)
452
rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
444 453
{
445 454
    struct cache_entry *ent;
446 455

  
447 456
    ent = cache + EXPR1(klass, id);
448 457
    if (ent->mid == id && ent->klass == klass) {
458
	if (defined_class_ptr)
459
	    *defined_class_ptr = ent->defined_class;
449 460
	return ent->me;
450 461
    }
451 462

  
452
    return rb_method_entry_get_without_cache(klass, id);
463
    return rb_method_entry_get_without_cache(klass, id, defined_class_ptr);
453 464
}
454 465

  
455 466
static void
......
535 546
rb_export_method(VALUE klass, ID name, rb_method_flag_t noex)
536 547
{
537 548
    rb_method_entry_t *me;
549
    VALUE defined_class;
538 550

  
539 551
    if (klass == rb_cObject) {
540 552
	rb_secure(4);
541 553
    }
542 554

  
543
    me = search_method(klass, name);
555
    me = search_method(klass, name, &defined_class);
544 556
    if (!me && TYPE(klass) == T_MODULE) {
545
	me = search_method(rb_cObject, name);
557
	me = search_method(rb_cObject, name, &defined_class);
546 558
    }
547 559

  
548 560
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
......
552 564
    if (me->flag != noex) {
553 565
	rb_vm_check_redefinition_opt_method(me);
554 566

  
555
	if (klass == me->klass) {
567
	if (klass == defined_class) {
556 568
	    me->flag = noex;
557 569
	}
558 570
	else {
......
564 576
int
565 577
rb_method_boundp(VALUE klass, ID id, int ex)
566 578
{
567
    rb_method_entry_t *me = rb_method_entry(klass, id);
579
    rb_method_entry_t *me = rb_method_entry(klass, id, 0);
568 580

  
569 581
    if (me != 0) {
570 582
	if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) {
......
643 655
	rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
644 656
    }
645 657

  
646
    me = search_method(klass, id);
658
    me = search_method(klass, id, 0);
647 659

  
648 660
    if (UNDEFINED_METHOD_ENTRY_P(me)) {
649 661
	const char *s0 = " class";
......
766 778
check_definition(VALUE mod, ID mid, rb_method_flag_t noex)
767 779
{
768 780
    const rb_method_entry_t *me;
769
    me = rb_method_entry(mod, mid);
781
    me = rb_method_entry(mod, mid, 0);
770 782
    if (me) {
771 783
	if (VISI_CHECK(me->flag, noex))
772 784
	    return Qtrue;
......
927 939
    }
928 940

  
929 941
  again:
930
    orig_me = search_method(klass, def);
942
    orig_me = search_method(klass, def, 0);
931 943

  
932 944
    if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
933 945
	if ((TYPE(klass) != T_MODULE) ||
934
	    (orig_me = search_method(rb_cObject, def), UNDEFINED_METHOD_ENTRY_P(orig_me))) {
946
	    (orig_me = search_method(rb_cObject, def, 0),
947
				     UNDEFINED_METHOD_ENTRY_P(orig_me))) {
935 948
	    rb_print_undef(klass, def, 0);
936 949
	}
937 950
    }
......
1192 1205

  
1193 1206
	id = rb_to_id(argv[i]);
1194 1207
	for (;;) {
1195
	    me = search_method(m, id);
1208
	    me = search_method(m, id, 0);
1196 1209
	    if (me == 0) {
1197
		me = search_method(rb_cObject, id);
1210
		me = search_method(rb_cObject, id, 0);
1198 1211
	    }
1199 1212
	    if (UNDEFINED_METHOD_ENTRY_P(me)) {
1200 1213
		rb_print_undef(module, id, 0);
......
1214 1227
int
1215 1228
rb_method_basic_definition_p(VALUE klass, ID id)
1216 1229
{
1217
    const rb_method_entry_t *me = rb_method_entry(klass, id);
1230
    const rb_method_entry_t *me = rb_method_entry(klass, id, 0);
1218 1231
    if (me && (me->flag & NOEX_BASIC))
1219 1232
	return 1;
1220 1233
    return 0;