ruby-changes:12951
From: nobu <ko1@a...>
Date: Fri, 28 Aug 2009 11:48:05 +0900 (JST)
Subject: [ruby-changes:12951] Ruby:r24691 (trunk): * method.h (rb_method_definition_t): split from rb_method_entry_t
nobu 2009-08-28 11:45:41 +0900 (Fri, 28 Aug 2009) New Revision: 24691 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24691 Log: * method.h (rb_method_definition_t): split from rb_method_entry_t to deal aliases. [ruby-dev:39165] * proc.c (struct METHOD): contains rb_method_entry_t copy. Modified files: trunk/ChangeLog trunk/class.c trunk/eval.c trunk/gc.c trunk/method.h trunk/proc.c trunk/vm.c trunk/vm_dump.c trunk/vm_eval.c trunk/vm_insnhelper.c trunk/vm_method.c Index: method.h =================================================================== --- method.h (revision 24690) +++ method.h (revision 24691) @@ -49,12 +49,9 @@ typedef struct rb_iseq_struct rb_iseq_t; -typedef struct rb_method_entry_struct { - rb_method_flag_t flag; +typedef struct rb_method_definition_struct { rb_method_type_t type; /* method type */ - ID called_id; ID original_id; - VALUE klass; /* should be mark */ union { rb_iseq_t *iseq; /* should be mark */ rb_method_cfunc_t cfunc; @@ -66,13 +63,23 @@ } optimize_type; } body; int alias_count; +} rb_method_definition_t; + +typedef struct rb_method_entry_struct { + rb_method_flag_t flag; + rb_method_definition_t *def; + ID called_id; + VALUE klass; /* should be mark */ } rb_method_entry_t; +#define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF) + 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); -void rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex); +rb_method_entry_t *rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_flag_t noex); rb_method_entry_t *rb_method_entry(VALUE klass, ID id); int rb_method_entry_arity(const rb_method_entry_t *me); void rb_gc_mark_method_entry(const rb_method_entry_t *me); +void rb_free_method_entry(rb_method_entry_t *me); #endif /* METHOD_H */ Index: ChangeLog =================================================================== --- ChangeLog (revision 24690) +++ ChangeLog (revision 24691) @@ -1,3 +1,10 @@ +Fri Aug 28 11:45:33 2009 Nobuyoshi Nakada <nobu@r...> + + * method.h (rb_method_definition_t): split from rb_method_entry_ + to deal aliases. [ruby-dev:39165] + + * proc.c (struct METHOD): contains rb_method_entry_t copy. + Fri Aug 28 10:21:30 2009 Nobuyoshi Nakada <nobu@r...> * iseq.c (iseq_mark): skip outdated cache entries. Index: vm_eval.c =================================================================== --- vm_eval.c (revision 24690) +++ vm_eval.c (revision 24691) @@ -33,17 +33,19 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_method_entry_t *me) { + const rb_method_definition_t *def = me->def; VALUE val; VALUE klass = me->klass; const rb_block_t *blockptr = 0; + if (!def) return Qnil; if (th->passed_block) { blockptr = th->passed_block; th->passed_block = 0; } again: - switch (me->type) { + switch (def->type) { case VM_METHOD_TYPE_ISEQ: { rb_control_frame_t *reg_cfp; int i; @@ -71,7 +73,7 @@ recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1); cfp->me = me; - val = call_cfunc(me->body.cfunc.func, recv, me->body.cfunc.argc, argc, argv); + val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv); if (reg_cfp != th->cfp + 1) { rb_bug("cfp consistency error - call0"); @@ -85,14 +87,14 @@ if (argc != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } - val = rb_ivar_set(recv, me->body.attr_id, argv[0]); + val = rb_ivar_set(recv, def->body.attr_id, argv[0]); break; } case VM_METHOD_TYPE_IVAR: { if (argc != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } - val = rb_attr_get(recv, me->body.attr_id); + val = rb_attr_get(recv, def->body.attr_id); break; } case VM_METHOD_TYPE_BMETHOD: { @@ -105,10 +107,11 @@ return method_missing(recv, id, argc, argv, 0); } RUBY_VM_CHECK_INTS(); + if (!(def = me->def)) return Qnil; goto again; } case VM_METHOD_TYPE_OPTIMIZED: { - switch (me->body.optimize_type) { + switch (def->body.optimize_type) { case OPTIMIZED_METHOD_TYPE_SEND: val = send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE); break; @@ -119,14 +122,14 @@ break; } default: - rb_bug("vm_call0: unsupported optimized method type (%d)", me->body.optimize_type); + rb_bug("vm_call0: unsupported optimized method type (%d)", def->body.optimize_type); val = Qundef; break; } break; } default: - rb_bug("vm_call0: unsupported method type (%d)", me->type); + rb_bug("vm_call0: unsupported method type (%d)", def->type); val = Qundef; } RUBY_VM_CHECK_INTS(); @@ -156,7 +159,7 @@ if (klass == 0) { klass = vm_search_normal_superclass(cfp->me->klass, recv); } - id = cfp->me->original_id; + id = cfp->me->def->original_id; } else { rb_bug("vm_call_super: should not be reached"); @@ -212,14 +215,14 @@ ent = cache + EXPR1(klass, mid); if (ent->mid == mid && ent->klass == klass) { - if (!ent->me) { - return method_missing(recv, mid, argc, argv, - scope == CALL_VCALL ? NOEX_VCALL : 0); + me = ent->me; + if (UNDEFINED_METHOD_ENTRY_P(me)) { + return method_missing(recv, mid, argc, argv, + scope == CALL_VCALL ? NOEX_VCALL : 0); } - me = ent->me; klass = me->klass; } - else if ((me = rb_method_entry(klass, mid)) != 0) { + else if ((me = rb_method_entry(klass, mid)) != 0 && me->def) { klass = me->klass; } else { @@ -230,7 +233,7 @@ scope == CALL_VCALL ? NOEX_VCALL : 0); } - oid = me->original_id; + oid = me->def->original_id; noex = me->flag; if (oid != idMethodMissing) { Index: proc.c =================================================================== --- proc.c (revision 24690) +++ proc.c (revision 24691) @@ -16,7 +16,7 @@ VALUE recv; VALUE rclass; ID id; - rb_method_entry_t *me; + rb_method_entry_t me; }; VALUE rb_cUnboundMethod; @@ -843,9 +843,20 @@ struct METHOD *data = ptr; rb_gc_mark(data->rclass); rb_gc_mark(data->recv); - rb_gc_mark_method_entry(data->me); + rb_gc_mark_method_entry(&data->me); } +static void +bm_free(void *ptr) +{ + struct METHOD *data = ptr; + rb_method_definition_t *def = data->me.def; + if (def->alias_count == 0) + xfree(def); + else if (def->alias_count > 0) + def->alias_count--; +} + static size_t bm_memsize(void *ptr) { @@ -855,7 +866,7 @@ static const rb_data_type_t method_data_type = { "method", bm_mark, - RUBY_TYPED_DEFAULT_FREE, + bm_free, bm_memsize, }; @@ -873,18 +884,20 @@ ID rid = id; struct METHOD *data; rb_method_entry_t *me; + rb_method_definition_t *def; again: me = rb_method_entry(klass, id); - if (!me) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { rb_print_undef(klass, id, 0); } + def = me->def; if (scope && (me->flag & NOEX_MASK) != NOEX_PUBLIC) { - rb_print_undef(rclass, me->original_id, (int)(me->flag & NOEX_MASK)); + rb_print_undef(rclass, def->original_id, (int)(me->flag & NOEX_MASK)); } - if (me->type == VM_METHOD_TYPE_ZSUPER) { + if (def->type == VM_METHOD_TYPE_ZSUPER) { klass = RCLASS_SUPER(me->klass); - id = me->original_id; + id = def->original_id; goto again; } @@ -904,7 +917,8 @@ data->recv = obj; data->rclass = rclass; data->id = rid; - data->me = me; + data->me = *me; + if (def) def->alias_count++; OBJ_INFECT(method, klass); @@ -959,7 +973,7 @@ m1 = (struct METHOD *)DATA_PTR(method); m2 = (struct METHOD *)DATA_PTR(other); - if (!rb_method_entry_eq(m1->me, m2->me) || + if (!rb_method_entry_eq(&m1->me, &m2->me) || m1->rclass != m2->rclass || m1->recv != m2->recv) { return Qfalse; @@ -984,7 +998,7 @@ TypedData_Get_Struct(method, struct METHOD, &method_data_type, m); hash = (long)m->rclass; hash ^= (long)m->recv; - hash ^= (long)m->me; + hash ^= (long)m->me.def; return INT2FIX(hash); } @@ -1010,6 +1024,7 @@ data->recv = Qundef; data->id = orig->id; data->me = orig->me; + if (orig->me.def) orig->me.def->alias_count++; data->rclass = orig->rclass; OBJ_INFECT(method, obj); @@ -1061,7 +1076,7 @@ struct METHOD *data; TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data); - return data->me->klass; + return data->me.klass; } /* @@ -1223,7 +1238,7 @@ rb_class2name(rclass)); } } - rb_add_method_me(mod, id, method->me, noex); + rb_add_method_me(mod, id, &method->me, noex); } else if (rb_obj_is_proc(body)) { rb_proc_t *proc; @@ -1294,6 +1309,7 @@ clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data); CLONESETUP(clone, self); *data = *orig; + if (data->me.def) data->me.def->alias_count++; return clone; } @@ -1336,7 +1352,7 @@ const rb_method_entry_t *me); 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); } POP_TAG(); if (safe >= 0) @@ -1456,6 +1472,7 @@ method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound); *bound = *data; + if (bound->me.def) bound->me.def->alias_count++; bound->recv = recv; bound->rclass = CLASS_OF(recv); @@ -1465,11 +1482,13 @@ int rb_method_entry_arity(const rb_method_entry_t *me) { - switch (me->type) { + const rb_method_definition_t *def = me->def; + if (!def) return 0; + switch (def->type) { case VM_METHOD_TYPE_CFUNC: - if (me->body.cfunc.argc < 0) + if (def->body.cfunc.argc < 0) return -1; - return check_argc(me->body.cfunc.argc); + return check_argc(def->body.cfunc.argc); case VM_METHOD_TYPE_ZSUPER: return -1; case VM_METHOD_TYPE_ATTRSET: @@ -1477,9 +1496,9 @@ case VM_METHOD_TYPE_IVAR: return 0; case VM_METHOD_TYPE_BMETHOD: - return rb_proc_arity(me->body.proc); + return rb_proc_arity(def->body.proc); case VM_METHOD_TYPE_ISEQ: { - rb_iseq_t *iseq = me->body.iseq; + rb_iseq_t *iseq = def->body.iseq; if (iseq->arg_rest == -1 && iseq->arg_opts == 0) { return iseq->argc; } @@ -1491,7 +1510,7 @@ case VM_METHOD_TYPE_NOTIMPLEMENTED: return 0; case VM_METHOD_TYPE_OPTIMIZED: { - switch (me->body.optimize_type) { + switch (def->body.optimize_type) { case OPTIMIZED_METHOD_TYPE_SEND: return -1; default: @@ -1499,7 +1518,7 @@ } } } - rb_bug("rb_method_entry_arity: invalid method entry type (%d)", me->type); + rb_bug("rb_method_entry_arity: invalid method entry type (%d)", def->type); } /* @@ -1548,7 +1567,7 @@ struct METHOD *data; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - return rb_method_entry_arity(data->me); + return rb_method_entry_arity(&data->me); } int @@ -1568,16 +1587,16 @@ rb_method_get_iseq(VALUE method) { struct METHOD *data; - rb_method_entry_t *me; + rb_method_definition_t *def; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - me = data->me; + def = data->me.def; - switch (me->type) { + switch (def->type) { case VM_METHOD_TYPE_BMETHOD: - return get_proc_iseq(me->body.proc, 0); + return get_proc_iseq(def->body.proc, 0); case VM_METHOD_TYPE_ISEQ: - return me->body.iseq; + return def->body.iseq; default: return 0; } @@ -1638,11 +1657,11 @@ rb_str_buf_cat2(str, s); rb_str_buf_cat2(str, ": "); - if (FL_TEST(data->me->klass, FL_SINGLETON)) { - VALUE v = rb_iv_get(data->me->klass, "__attached__"); + if (FL_TEST(data->me.klass, FL_SINGLETON)) { + VALUE v = rb_iv_get(data->me.klass, "__attached__"); if (data->recv == Qundef) { - rb_str_buf_append(str, rb_inspect(data->me->klass)); + rb_str_buf_append(str, rb_inspect(data->me.klass)); } else if (data->recv == v) { rb_str_buf_append(str, rb_inspect(v)); @@ -1658,15 +1677,15 @@ } else { rb_str_buf_cat2(str, rb_class2name(data->rclass)); - if (data->rclass != data->me->klass) { + if (data->rclass != data->me.klass) { rb_str_buf_cat2(str, "("); - rb_str_buf_cat2(str, rb_class2name(data->me->klass)); + rb_str_buf_cat2(str, rb_class2name(data->me.klass)); rb_str_buf_cat2(str, ")"); } } rb_str_buf_cat2(str, sharp); - rb_str_append(str, rb_id2str(data->me->original_id)); - if (data->me->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { + rb_str_append(str, rb_id2str(data->me.def->original_id)); + if (data->me.def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { rb_str_buf_cat2(str, " (not-implemented)"); } rb_str_buf_cat2(str, ">"); Index: vm_method.c =================================================================== --- vm_method.c (revision 24690) +++ vm_method.c (revision 24691) @@ -126,9 +126,24 @@ } } -rb_method_entry_t * -rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) +void +rb_free_method_entry(rb_method_entry_t *me) { + rb_method_definition_t *def = me->def; + + if (def) { + if (def->alias_count == 0) + xfree(def); + else if (def->alias_count > 0) + def->alias_count--; + me->def = 0; + } + xfree(me); +} + +static rb_method_entry_t * +rb_add_method_def(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_flag_t noex) +{ rb_method_entry_t *me; st_table *mtbl; st_data_t data; @@ -156,60 +171,34 @@ if (OBJ_FROZEN(klass)) { rb_error_frozen("class/module"); } - rb_clear_cache_by_id(mid); - me = ALLOC(rb_method_entry_t); - me->type = type; - me->original_id = me->called_id = mid; - me->klass = klass; - me->flag = NOEX_WITH_SAFE(noex); - me->alias_count = 0; - - switch (type) { - case VM_METHOD_TYPE_ISEQ: - me->body.iseq = (rb_iseq_t *)opts; - break; - case VM_METHOD_TYPE_CFUNC: - me->body.cfunc = *(rb_method_cfunc_t *)opts; - break; - case VM_METHOD_TYPE_ATTRSET: - case VM_METHOD_TYPE_IVAR: - me->body.attr_id = (ID)opts; - break; - case VM_METHOD_TYPE_BMETHOD: - me->body.proc = (VALUE)opts; - break; - case VM_METHOD_TYPE_NOTIMPLEMENTED: - me->body.cfunc.func = rb_f_notimplement; - me->body.cfunc.argc = -1; - break; - case VM_METHOD_TYPE_OPTIMIZED: - me->body.optimize_type = (enum method_optimized_type)opts; - break; - case VM_METHOD_TYPE_ZSUPER: - case VM_METHOD_TYPE_UNDEF: - break; - default: - rb_bug("rb_add_method: unsupported method type (%d)\n", type); - } - mtbl = RCLASS_M_TBL(klass); /* check re-definition */ if (st_lookup(mtbl, mid, &data)) { rb_method_entry_t *old_me = (rb_method_entry_t *)data; + rb_method_definition_t *old_def = old_me->def; + + if (old_def == def) return old_me; rb_vm_check_redefinition_opt_method(old_me); if (RTEST(ruby_verbose) && - old_me->alias_count == 0 && - old_me->type != VM_METHOD_TYPE_UNDEF) { + old_def->alias_count == 0 && + old_def->type != VM_METHOD_TYPE_UNDEF) { rb_warning("method redefined; discarding old %s", rb_id2name(mid)); } -#if defined(__cplusplus) || (__STDC_VERSION__ >= 199901L) - // TODO: free old_me -#endif + rb_free_method_entry(old_me); } + rb_clear_cache_by_id(mid); + + me = ALLOC(rb_method_entry_t); + me->flag = NOEX_WITH_SAFE(noex); + me->called_id = mid; + me->klass = klass; + me->def = def; + if (def) def->alias_count++; + /* check mid */ if (klass == rb_cObject && mid == idInitialize) { rb_warn("redefining Object#initialize may cause infinite loop"); @@ -235,6 +224,52 @@ return me; } +rb_method_entry_t * +rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) +{ + rb_method_entry_t *me = rb_add_method_def(klass, mid, type, 0, noex); + rb_method_definition_t *def = ALLOC(rb_method_definition_t); + me->def = def; + def->type = type; + def->original_id = mid; + def->alias_count = 0; + switch (type) { + case VM_METHOD_TYPE_ISEQ: + def->body.iseq = (rb_iseq_t *)opts; + break; + case VM_METHOD_TYPE_CFUNC: + def->body.cfunc = *(rb_method_cfunc_t *)opts; + break; + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + def->body.attr_id = (ID)opts; + break; + case VM_METHOD_TYPE_BMETHOD: + def->body.proc = (VALUE)opts; + break; + case VM_METHOD_TYPE_NOTIMPLEMENTED: + def->body.cfunc.func = rb_f_notimplement; + def->body.cfunc.argc = -1; + break; + case VM_METHOD_TYPE_OPTIMIZED: + def->body.optimize_type = (enum method_optimized_type)opts; + break; + case VM_METHOD_TYPE_ZSUPER: + case VM_METHOD_TYPE_UNDEF: + break; + default: + rb_bug("rb_add_method: unsupported method type (%d)\n", type); + } + return me; +} + +rb_method_entry_t * +rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex) +{ + rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF; + return rb_add_method_def(klass, mid, type, me->def, noex); +} + void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) { @@ -257,8 +292,8 @@ Check_Type(klass, T_CLASS); me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR); - if (me && me->type == VM_METHOD_TYPE_CFUNC) { - return (rb_alloc_func_t)me->body.cfunc.func; + if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) { + return (rb_alloc_func_t)me->def->body.cfunc.func; } else { return 0; @@ -299,7 +334,7 @@ ent = cache + EXPR1(klass, id); ent->klass = klass; - if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { ent->mid = id; ent->me = 0; me = 0; @@ -346,7 +381,7 @@ if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) { me = (rb_method_entry_t *)data; - if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + if (!me || (me->def && me->def->type == VM_METHOD_TYPE_UNDEF)) { me = 0; } else { @@ -360,6 +395,7 @@ rb_vm_check_redefinition_opt_method(me); rb_clear_cache_for_undef(klass, mid); + rb_free_method_entry(me); if (FL_TEST(klass, FL_SINGLETON)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid)); @@ -425,7 +461,7 @@ me = search_method(rb_cObject, name); } - if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { rb_print_undef(klass, name, 0); } @@ -450,7 +486,7 @@ if (ex && (me->flag & NOEX_PRIVATE)) { return Qfalse; } - if (me->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { + if (!me->def || me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { return Qfalse; } return Qtrue; @@ -520,7 +556,7 @@ me = search_method(klass, id); - if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { const char *s0 = " class"; VALUE c = klass; @@ -746,63 +782,36 @@ return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED); } -static void * -me_opts(const rb_method_entry_t *me) -{ - switch (me->type) { - case VM_METHOD_TYPE_ISEQ: - return me->body.iseq; - case VM_METHOD_TYPE_CFUNC: - return (void *)&me->body.cfunc; - case VM_METHOD_TYPE_ATTRSET: - case VM_METHOD_TYPE_IVAR: - return (void *)me->body.attr_id; - case VM_METHOD_TYPE_BMETHOD: - return (void *)me->body.proc; - case VM_METHOD_TYPE_ZSUPER: - case VM_METHOD_TYPE_NOTIMPLEMENTED: - case VM_METHOD_TYPE_UNDEF: - return 0; - case VM_METHOD_TYPE_OPTIMIZED: - return (void *)me->body.optimize_type; - default: - rb_bug("rb_add_method: unsupported method type (%d)\n", me->type); - return 0; - } -} - -void -rb_add_method_me(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex) -{ - rb_add_method(klass, mid, me->type, me_opts(me), noex); -} - int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) { - if (m1->type != m2->type) { + const rb_method_definition_t *d1 = m1->def, *d2 = m2->def; + if (!d1) { + return !d2; + } + if (d1->type != d2->type) { return 0; } - switch (m1->type) { + switch (d1->type) { case VM_METHOD_TYPE_ISEQ: - return m1->body.iseq == m2->body.iseq; + return d1->body.iseq == d2->body.iseq; case VM_METHOD_TYPE_CFUNC: return - m1->body.cfunc.func == m2->body.cfunc.func && - m1->body.cfunc.argc == m2->body.cfunc.argc; + d1->body.cfunc.func == d2->body.cfunc.func && + d1->body.cfunc.argc == d2->body.cfunc.argc; case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: - return m1->body.attr_id == m2->body.attr_id; + return d1->body.attr_id == d2->body.attr_id; case VM_METHOD_TYPE_BMETHOD: - return m1->body.proc == m2->body.proc; + return d1->body.proc == d2->body.proc; case VM_METHOD_TYPE_ZSUPER: case VM_METHOD_TYPE_NOTIMPLEMENTED: case VM_METHOD_TYPE_UNDEF: return 1; case VM_METHOD_TYPE_OPTIMIZED: - return m1->body.optimize_type == m2->body.optimize_type; + return d1->body.optimize_type == d2->body.optimize_type; default: - rb_bug("rb_add_method: unsupported method type (%d)\n", m1->type); + rb_bug("rb_add_method: unsupported method type (%d)\n", d1->type); return 0; } } @@ -810,7 +819,7 @@ void rb_alias(VALUE klass, ID name, ID def) { - rb_method_entry_t *orig_me, *me; + rb_method_entry_t *orig_me; VALUE singleton = 0; rb_frozen_class_p(klass); @@ -820,11 +829,9 @@ orig_me = search_method(klass, def); - if (!orig_me || orig_me->type == VM_METHOD_TYPE_UNDEF) { - if (TYPE(klass) == T_MODULE) { - orig_me = search_method(rb_cObject, def); - } - if (!orig_me || !orig_me->type == VM_METHOD_TYPE_UNDEF) { + 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))) { rb_print_undef(klass, def, 0); } } @@ -832,9 +839,7 @@ singleton = rb_iv_get(klass, "__attached__"); } - orig_me->alias_count++; - me = rb_add_method(klass, name, orig_me->type, me_opts(orig_me), orig_me->flag); - me->original_id = def; + rb_add_method_me(klass, name, orig_me, orig_me->flag); if (!ruby_running) return; @@ -1098,10 +1103,10 @@ if (me == 0) { me = search_method(rb_cObject, id); } - if (me == 0 || me->type == VM_METHOD_TYPE_UNDEF) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { rb_print_undef(module, id, 0); } - if (me->type != VM_METHOD_TYPE_ZSUPER) { + if (me->def->type != VM_METHOD_TYPE_ZSUPER) { break; /* normal case: need not to follow 'super' link */ } m = RCLASS_SUPER(m); Index: eval.c =================================================================== --- eval.c (revision 24690) +++ eval.c (revision 24691) @@ -693,7 +693,7 @@ { rb_iseq_t *iseq = cfp->iseq; if (!iseq) { - return cfp->me->original_id; + return cfp->me->def->original_id; } while (iseq) { if (RUBY_VM_IFUNC_P(iseq)) { Index: gc.c =================================================================== --- gc.c (revision 24690) +++ gc.c (revision 24691) @@ -1377,13 +1377,16 @@ static void mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me, int lev) { + const rb_method_definition_t *def = me->def; + gc_mark(objspace, me->klass, lev); - switch (me->type) { + if (!def) return; + switch (def->type) { case VM_METHOD_TYPE_ISEQ: - gc_mark(objspace, me->body.iseq->self, lev); + gc_mark(objspace, def->body.iseq->self, lev); break; case VM_METHOD_TYPE_BMETHOD: - gc_mark(objspace, me->body.proc, lev); + gc_mark(objspace, def->body.proc, lev); break; default: break; /* ignore */ @@ -1417,7 +1420,7 @@ static int free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) { - xfree(me); + rb_free_method_entry(me); return ST_CONTINUE; } Index: class.c =================================================================== --- class.c (revision 24690) +++ class.c (revision 24691) @@ -126,17 +126,14 @@ static int clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) { - switch (me->type) { - case VM_METHOD_TYPE_ISEQ: { - VALUE newiseqval = rb_iseq_clone(me->body.iseq->self, data->klass); - rb_iseq_t *iseq; - GetISeqPtr(newiseqval, iseq); - rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - break; - } - default: + if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { + VALUE newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); + rb_iseq_t *iseq; + GetISeqPtr(newiseqval, iseq); + rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); + } + else { rb_add_method_me(data->klass, mid, me, me->flag); - break; } return ST_CONTINUE; } @@ -683,7 +680,7 @@ } if (!st_lookup(list, key, 0)) { - if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + if (UNDEFINED_METHOD_ENTRY_P(me)) { type = -1; /* none */ } else { Index: vm.c =================================================================== --- vm.c (revision 24690) +++ vm.c (revision 24691) @@ -735,7 +735,7 @@ } else if (RUBYVM_CFUNC_FRAME_P(cfp)) { if (NIL_P(file)) file = rb_str_new_cstr("ruby"); - if ((*iter)(arg, file, line_no, rb_id2str(cfp->me->original_id))) break; + if ((*iter)(arg, file, line_no, rb_id2str(cfp->me->def->original_id))) break; } cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp); } @@ -937,7 +937,7 @@ rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me) { VALUE bop; - if (me->type == VM_METHOD_TYPE_CFUNC) { + if (!me->def || me->def->type == VM_METHOD_TYPE_CFUNC) { if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) { ruby_vm_redefined_flag[bop] = 1; } @@ -948,8 +948,8 @@ add_opt_method(VALUE klass, ID mid, VALUE bop) { rb_method_entry_t *me; - if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && - me->type == VM_METHOD_TYPE_CFUNC) { + if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && + me->def->type == VM_METHOD_TYPE_CFUNC) { st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); } else { @@ -1338,7 +1338,7 @@ rb_control_frame_t *cfp = th->cfp; rb_iseq_t *iseq = cfp->iseq; if (!iseq) { - if (idp) *idp = cfp->me->original_id; + if (idp) *idp = cfp->me->def->original_id; if (klassp) *klassp = cfp->me->klass; return 1; } @@ -1382,10 +1382,10 @@ file, line_no, RSTRING_PTR(iseq->name)); } } - else if (cfp->me->original_id) { + else if (cfp->me->def->original_id) { str = rb_sprintf("`%s#%s' (cfunc)", RSTRING_PTR(rb_class_name(cfp->me->klass)), - rb_id2name(cfp->me->original_id)); + rb_id2name(cfp->me->def->original_id)); } return str; Index: vm_dump.c =================================================================== --- vm_dump.c (revision 24690) +++ vm_dump.c (revision 24691) @@ -113,8 +113,8 @@ } } else if (cfp->me) { - iseq_name = rb_id2name(cfp->me->original_id); - snprintf(posbuf, MAX_POSBUF, ":%s", rb_id2name(cfp->me->original_id)); + iseq_name = rb_id2name(cfp->me->def->original_id); + snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name); line = -1; } Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 24690) +++ vm_insnhelper.c (revision 24691) @@ -361,15 +361,14 @@ { VALUE val = 0; int state = 0; + const rb_method_definition_t *def = me->def; VALUE klass = me->klass; ID id = me->called_id; EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass); TH_PUSH_TAG(th); -#if defined(__cplusplus) || (__STDC_VERSION__ >= 199901L) - // TODO: fix me. separate event -#endif + /* TODO: fix me. separate event */ if (th->event_flags & (RUBY_EVENT_C_RETURN | RUBY_EVENT_VM)) { state = TH_EXEC_TAG(); } @@ -384,7 +383,7 @@ cfp->me = me; reg_cfp->sp -= num + 1; - val = call_cfunc(me->body.cfunc.func, recv, (int)me->body.cfunc.argc, num, reg_cfp->sp + 1); + val = call_cfunc(def->body.cfunc.func, recv, (int)def->body.cfunc.argc, num, reg_cfp->sp + 1); if (reg_cfp != th->cfp + 1) { rb_bug("cfp consistency error - send"); @@ -410,7 +409,7 @@ /* control block frame */ (cfp-2)->me = me; - GetProcPtr(me->body.proc, proc); + GetProcPtr(me->def->body.proc, proc); val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr); return val; } @@ -443,7 +442,7 @@ { int opt_pc, i; VALUE *sp, *rsp = cfp->sp - argc; - rb_iseq_t *iseq = me->body.iseq; + rb_iseq_t *iseq = me->def->body.iseq; VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, rsp, &blockptr); @@ -502,7 +501,7 @@ if (me != 0) { if ((me->flag == 0)) { normal_method_dispatch: - switch (me->type) { + switch (me->def->type) { case VM_METHOD_TYPE_ISEQ:{ vm_setup_method(th, cfp, recv, num, blockptr, flag, me); return Qundef; @@ -516,7 +515,7 @@ if (num != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num); } - val = rb_ivar_set(recv, me->body.attr_id, *(cfp->sp - 1)); + val = rb_ivar_set(recv, me->def->body.attr_id, *(cfp->sp - 1)); cfp->sp -= 2; break; } @@ -524,7 +523,7 @@ if (num != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num); } - val = rb_attr_get(recv, me->body.attr_id); + val = rb_attr_get(recv, me->def->body.attr_id); cfp->sp -= 1; break; } @@ -547,7 +546,7 @@ } } case VM_METHOD_TYPE_OPTIMIZED:{ - switch (me->body.optimize_type) { + switch (me->def->body.optimize_type) { case OPTIMIZED_METHOD_TYPE_SEND: { rb_control_frame_t *reg_cfp = cfp; rb_num_t i = num - 1; @@ -583,12 +582,12 @@ } default: rb_bug("eval_invoke_method: unsupported optimized method type (%d)", - me->body.optimize_type); + me->def->body.optimize_type); } break; } default:{ - rb_bug("eval_invoke_method: unsupported method type (%d)", me->type); + rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type); break; } } @@ -1309,7 +1308,7 @@ } } - id = lcfp->me->original_id; + id = lcfp->me->def->original_id; klass = vm_search_normal_superclass(lcfp->me->klass, recv); } else { @@ -1531,8 +1530,8 @@ static inline int check_cfunc(const rb_method_entry_t *me, VALUE (*func)()) { - if (me && me->type == VM_METHOD_TYPE_CFUNC && - me->body.cfunc.func == func) { + if (me && me->def->type == VM_METHOD_TYPE_CFUNC && + me->def->body.cfunc.func == func) { return 1; } else { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/