Created
August 27, 2009 09:42
-
-
Save nobu/176200 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: class.c | |
=================================================================== | |
--- class.c (revision 24683) | |
+++ class.c (working copy) | |
@@ -127,15 +127,12 @@ 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; | |
@@ -684,5 +681,5 @@ method_entry(ID key, const rb_method_ent | |
if (!st_lookup(list, key, 0)) { | |
- if (!me || me->type == VM_METHOD_TYPE_UNDEF) { | |
+ if (UNDEFINED_METHOD_ENTRY_P(me)) { | |
type = -1; /* none */ | |
} | |
Index: eval.c | |
=================================================================== | |
--- eval.c (revision 24683) | |
+++ eval.c (working copy) | |
@@ -694,5 +694,5 @@ frame_func_id(rb_control_frame_t *cfp) | |
rb_iseq_t *iseq = cfp->iseq; | |
if (!iseq) { | |
- return cfp->me->original_id; | |
+ return cfp->me->def->original_id; | |
} | |
while (iseq) { | |
Index: gc.c | |
=================================================================== | |
--- gc.c (revision 24683) | |
+++ gc.c (working copy) | |
@@ -1378,11 +1378,14 @@ 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: | |
@@ -1418,5 +1421,5 @@ 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: iseq.c | |
=================================================================== | |
--- iseq.c (revision 24683) | |
+++ iseq.c (working copy) | |
@@ -108,4 +108,5 @@ iseq_mark(void *ptr) | |
RUBY_MARK_UNLESS_NULL(iseq->ic_entries[i].ic_class); | |
RUBY_MARK_UNLESS_NULL(iseq->ic_entries[i].ic_value); | |
+ if (iseq->ic_entries[i].ic_vmstat != GET_VM_STATE_VERSION()) continue; | |
if (iseq->ic_entries[i].ic_method) { | |
rb_gc_mark_method_entry(iseq->ic_entries[i].ic_method); | |
Index: method.h | |
=================================================================== | |
--- method.h (revision 24683) | |
+++ method.h (working copy) | |
@@ -50,10 +50,7 @@ typedef struct rb_method_cfunc_struct { | |
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 */ | |
@@ -67,12 +64,22 @@ typedef struct rb_method_entry_struct { | |
} 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: proc.c | |
=================================================================== | |
--- proc.c (revision 24683) | |
+++ proc.c (working copy) | |
@@ -17,5 +17,5 @@ struct METHOD { | |
VALUE rclass; | |
ID id; | |
- rb_method_entry_t *me; | |
+ rb_method_entry_t me; | |
}; | |
@@ -844,5 +844,16 @@ bm_mark(void *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--; | |
} | |
@@ -856,5 +867,5 @@ static const rb_data_type_t method_data_ | |
"method", | |
bm_mark, | |
- RUBY_TYPED_DEFAULT_FREE, | |
+ bm_free, | |
bm_memsize, | |
}; | |
@@ -874,16 +885,18 @@ mnew(VALUE klass, VALUE obj, ID id, VALU | |
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; | |
} | |
@@ -905,5 +918,6 @@ mnew(VALUE klass, VALUE obj, ID id, VALU | |
data->rclass = rclass; | |
data->id = rid; | |
- data->me = me; | |
+ data->me = *me; | |
+ if (def) def->alias_count++; | |
OBJ_INFECT(method, klass); | |
@@ -960,5 +974,5 @@ method_eq(VALUE method, VALUE other) | |
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) { | |
@@ -985,5 +999,5 @@ method_hash(VALUE method) | |
hash = (long)m->rclass; | |
hash ^= (long)m->recv; | |
- hash ^= (long)m->me; | |
+ hash ^= (long)m->me.def; | |
return INT2FIX(hash); | |
@@ -1011,4 +1025,5 @@ method_unbind(VALUE obj) | |
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); | |
@@ -1062,5 +1077,5 @@ method_owner(VALUE obj) | |
TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data); | |
- return data->me->klass; | |
+ return data->me.klass; | |
} | |
@@ -1224,5 +1239,5 @@ rb_mod_define_method(int argc, VALUE *ar | |
} | |
} | |
- 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)) { | |
@@ -1295,4 +1310,5 @@ method_clone(VALUE self) | |
CLONESETUP(clone, self); | |
*data = *orig; | |
+ if (data->me.def) data->me.def->alias_count++; | |
return clone; | |
@@ -1337,5 +1353,5 @@ rb_method_call(int argc, VALUE *argv, VA | |
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(); | |
@@ -1457,4 +1473,5 @@ umethod_bind(VALUE method, VALUE recv) | |
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); | |
@@ -1466,9 +1483,11 @@ 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; | |
@@ -1478,13 +1497,13 @@ rb_method_entry_arity(const rb_method_en | |
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; | |
- if (iseq->arg_rest == -1 && iseq->arg_opts == 0) { | |
- return iseq->argc; | |
- } | |
- else { | |
- return -(iseq->argc + 1 + iseq->arg_post_len); | |
- } | |
+ rb_iseq_t *iseq = def->body.iseq; | |
+ if (iseq->arg_rest == -1 && iseq->arg_opts == 0) { | |
+ return iseq->argc; | |
+ } | |
+ else { | |
+ return -(iseq->argc + 1 + iseq->arg_post_len); | |
+ } | |
} | |
case VM_METHOD_TYPE_UNDEF: | |
@@ -1492,13 +1511,13 @@ rb_method_entry_arity(const rb_method_en | |
return 0; | |
case VM_METHOD_TYPE_OPTIMIZED: { | |
- switch (me->body.optimize_type) { | |
- case OPTIMIZED_METHOD_TYPE_SEND: | |
- return -1; | |
- default: | |
- break; | |
- } | |
+ switch (def->body.optimize_type) { | |
+ case OPTIMIZED_METHOD_TYPE_SEND: | |
+ return -1; | |
+ default: | |
+ break; | |
+ } | |
} | |
} | |
- 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); | |
} | |
@@ -1549,5 +1568,5 @@ method_arity(VALUE method) | |
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); | |
- return rb_method_entry_arity(data->me); | |
+ return rb_method_entry_arity(&data->me); | |
} | |
@@ -1569,14 +1588,14 @@ 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; | |
@@ -1639,9 +1658,9 @@ method_inspect(VALUE method) | |
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) { | |
@@ -1659,13 +1678,13 @@ method_inspect(VALUE method) | |
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)"); | |
} | |
Index: vm.c | |
=================================================================== | |
--- vm.c (revision 24683) | |
+++ vm.c (working copy) | |
@@ -736,5 +736,5 @@ vm_backtrace_each(rb_thread_t *th, int l | |
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); | |
@@ -938,5 +938,5 @@ rb_vm_check_redefinition_opt_method(cons | |
{ | |
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; | |
@@ -949,6 +949,6 @@ add_opt_method(VALUE klass, ID mid, VALU | |
{ | |
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); | |
} | |
@@ -1339,5 +1339,5 @@ rb_thread_method_id_and_class(rb_thread_ | |
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; | |
@@ -1383,8 +1383,8 @@ rb_thread_current_status(const rb_thread | |
} | |
} | |
- 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)); | |
} | |
Index: vm_core.h | |
=================================================================== | |
--- vm_core.h (revision 24683) | |
+++ vm_core.h (working copy) | |
@@ -530,4 +530,10 @@ typedef struct { | |
typedef struct iseq_inline_cache_entry *IC; | |
+extern VALUE ruby_vm_global_state_version; | |
+extern VALUE ruby_vm_const_missing_count; | |
+ | |
+#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version) | |
+#define INC_VM_STATE_VERSION() \ | |
+ (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff) | |
void rb_vm_change_state(void); | |
Index: vm_dump.c | |
=================================================================== | |
--- vm_dump.c (revision 24683) | |
+++ vm_dump.c (working copy) | |
@@ -114,6 +114,6 @@ control_frame_dump(rb_thread_t *th, rb_c | |
} | |
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_eval.c | |
=================================================================== | |
--- vm_eval.c (revision 24683) | |
+++ vm_eval.c (working copy) | |
@@ -34,8 +34,10 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
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; | |
@@ -44,5 +46,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
again: | |
- switch (me->type) { | |
+ switch (def->type) { | |
case VM_METHOD_TYPE_ISEQ: { | |
rb_control_frame_t *reg_cfp; | |
@@ -72,5 +74,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
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) { | |
@@ -86,5 +88,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
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; | |
} | |
@@ -93,5 +95,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
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; | |
} | |
@@ -106,8 +108,9 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
} | |
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); | |
@@ -120,5 +123,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
} | |
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; | |
@@ -127,5 +130,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA | |
} | |
default: | |
- rb_bug("vm_call0: unsupported method type (%d)", me->type); | |
+ rb_bug("vm_call0: unsupported method type (%d)", def->type); | |
val = Qundef; | |
} | |
@@ -157,5 +160,5 @@ vm_call_super(rb_thread_t *th, int argc, | |
klass = vm_search_normal_superclass(cfp->me->klass, recv); | |
} | |
- id = cfp->me->original_id; | |
+ id = cfp->me->def->original_id; | |
} | |
else { | |
@@ -213,12 +216,12 @@ rb_call0(VALUE recv, ID mid, int argc, c | |
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); | |
+ } | |
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; | |
} | |
@@ -231,5 +234,5 @@ rb_call0(VALUE recv, ID mid, int argc, c | |
} | |
- oid = me->original_id; | |
+ oid = me->def->original_id; | |
noex = me->flag; | |
Index: vm_insnhelper.c | |
=================================================================== | |
--- vm_insnhelper.c (revision 24683) | |
+++ vm_insnhelper.c (working copy) | |
@@ -362,4 +362,5 @@ vm_call_cfunc(rb_thread_t *th, rb_contro | |
VALUE val = 0; | |
int state = 0; | |
+ const rb_method_definition_t *def = me->def; | |
VALUE klass = me->klass; | |
ID id = me->called_id; | |
@@ -368,7 +369,5 @@ vm_call_cfunc(rb_thread_t *th, rb_contro | |
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(); | |
@@ -385,5 +384,5 @@ vm_call_cfunc(rb_thread_t *th, rb_contro | |
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) { | |
@@ -411,5 +410,5 @@ vm_call_bmethod(rb_thread_t *th, VALUE r | |
(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; | |
@@ -444,5 +443,5 @@ vm_setup_method(rb_thread_t *th, rb_cont | |
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); | |
@@ -503,5 +502,5 @@ vm_call_method(rb_thread_t *th, rb_contr | |
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); | |
@@ -517,5 +516,5 @@ vm_call_method(rb_thread_t *th, rb_contr | |
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; | |
@@ -525,5 +524,5 @@ vm_call_method(rb_thread_t *th, rb_contr | |
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; | |
@@ -548,5 +547,5 @@ vm_call_method(rb_thread_t *th, rb_contr | |
} | |
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; | |
@@ -584,10 +583,10 @@ vm_call_method(rb_thread_t *th, rb_contr | |
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; | |
} | |
@@ -1310,5 +1309,5 @@ vm_search_superclass(rb_control_frame_t | |
} | |
- id = lcfp->me->original_id; | |
+ id = lcfp->me->def->original_id; | |
klass = vm_search_normal_superclass(lcfp->me->klass, recv); | |
} | |
@@ -1532,6 +1531,6 @@ 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; | |
} | |
Index: vm_insnhelper.h | |
=================================================================== | |
--- vm_insnhelper.h (revision 24683) | |
+++ vm_insnhelper.h (working copy) | |
@@ -59,10 +59,4 @@ enum { | |
extern char ruby_vm_redefined_flag[BOP_LAST_]; | |
-extern VALUE ruby_vm_global_state_version; | |
-extern VALUE ruby_vm_const_missing_count; | |
- | |
-#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version) | |
-#define INC_VM_STATE_VERSION() \ | |
- (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff) | |
Index: vm_method.c | |
=================================================================== | |
--- vm_method.c (revision 24684) | |
+++ vm_method.c (working copy) | |
@@ -127,6 +127,21 @@ rb_add_method_cfunc(VALUE klass, ID mid, | |
} | |
-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; | |
@@ -157,40 +172,4 @@ rb_add_method(VALUE klass, ID mid, rb_me | |
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); | |
@@ -199,16 +178,26 @@ rb_add_method(VALUE klass, ID mid, rb_me | |
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) { | |
@@ -236,4 +225,50 @@ rb_add_method(VALUE klass, ID mid, rb_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)) | |
@@ -258,6 +293,6 @@ rb_get_alloc_func(VALUE klass) | |
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 { | |
@@ -300,5 +335,5 @@ rb_get_method_entry(VALUE klass, ID id) | |
ent->klass = klass; | |
- if (!me || me->type == VM_METHOD_TYPE_UNDEF) { | |
+ if (UNDEFINED_METHOD_ENTRY_P(me)) { | |
ent->mid = id; | |
ent->me = 0; | |
@@ -347,5 +382,5 @@ rb_remove_method_id(VALUE klass, ID mid) | |
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; | |
} | |
@@ -361,4 +396,5 @@ rb_remove_method_id(VALUE klass, ID mid) | |
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)) { | |
@@ -426,5 +462,5 @@ rb_export_method(VALUE klass, ID name, I | |
} | |
- if (!me || me->type == VM_METHOD_TYPE_UNDEF) { | |
+ if (UNDEFINED_METHOD_ENTRY_P(me)) { | |
rb_print_undef(klass, name, 0); | |
} | |
@@ -451,5 +487,5 @@ rb_method_boundp(VALUE klass, ID id, int | |
return Qfalse; | |
} | |
- if (me->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { | |
+ if (!me->def || me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { | |
return Qfalse; | |
} | |
@@ -521,5 +557,5 @@ rb_undef(VALUE klass, ID id) | |
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; | |
@@ -747,53 +783,26 @@ rb_mod_protected_method_defined(VALUE mo | |
} | |
-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: | |
@@ -801,7 +810,7 @@ rb_method_entry_eq(const rb_method_entry | |
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; | |
} | |
@@ -811,5 +820,5 @@ 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; | |
@@ -821,9 +830,7 @@ rb_alias(VALUE klass, ID name, ID def) | |
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); | |
} | |
@@ -833,7 +840,5 @@ rb_alias(VALUE klass, ID name, ID def) | |
} | |
- 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; | |
@@ -1099,8 +1104,8 @@ rb_mod_modfunc(int argc, VALUE *argv, VA | |
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 */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment