control_frame_change-r29944-20101127.diff
| b/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; |
| b/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; |
| b/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); |
| b/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 | |
| b/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; |
| b/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; |
| b/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 |
| b/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)) {
|
| b/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 |
| b/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; |