diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-07-15 14:59:41 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-07-15 14:59:41 +0000 |
commit | c330876d7c5065f89234becc5125426d0d136bdc (patch) | |
tree | d7a65121d7250d0137a2c75d7b7d454737815e7d /vm_method.c | |
parent | d3cbda6e8dc5732f64b06cacb4c137f01ebe0461 (diff) |
* method.h, vm_core.h: add rb_method_entry_t. Remove nodes around
method management. This change affect some VM control stack structure.
* vm.c, vm_insnhelper.c, vm_method.c, vm_eval.c: ditto. and make some
refactoring.
* insns.def, class.c, eval.c, proc.c, vm_dump.c : ditto.
* vm_core.h, compile.c (iseq_specialized_instruction): remove
VM_CALL_SEND_BIT. use another optimization tech for Kernel#send.
* node.h: remove unused node types.
* ext/objspace/objspace.c (count_nodes): ditto.
* gc.c: add mark/free functions for method entry.
* include/ruby/intern.h: remove decl of
rb_define_notimplement_method_id(). nobody can use it
because noex is not opend.
* iseq.c (iseq_mark): fix to check ic_method is available.
* iseq.c (rb_iseq_disasm): fix to use rb_method_get_iseq().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24128 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_method.c')
-rw-r--r-- | vm_method.c | 535 |
1 files changed, 276 insertions, 259 deletions
diff --git a/vm_method.c b/vm_method.c index 292146dab9..e84d4ccba6 100644 --- a/vm_method.c +++ b/vm_method.c @@ -6,7 +6,7 @@ #define CACHE_MASK 0x7ff #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) -static void rb_vm_check_redefinition_opt_method(const NODE *node); +static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); static ID object_id; static ID removed, singleton_removed, undefined, singleton_undefined; @@ -14,18 +14,14 @@ static ID added, singleton_added; struct cache_entry { /* method hash table. */ ID mid; /* method's id */ - ID mid0; /* method's original id */ VALUE klass; /* receiver's class */ - VALUE oklass; /* original's class */ - NODE *method; + rb_method_entry_t *me; }; static struct cache_entry cache[CACHE_SIZE]; #define ruby_running (GET_VM()->running) /* int ruby_running = 0; */ -static NODE *notimplement_body = 0; - void rb_clear_cache(void) { @@ -38,7 +34,7 @@ rb_clear_cache(void) ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - ent->mid = 0; + ent->me = ent->mid = 0; ent++; } } @@ -55,8 +51,8 @@ rb_clear_cache_for_undef(VALUE klass, ID id) ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - if (ent->oklass == klass && ent->mid == id) { - ent->mid = 0; + if ((ent->me && ent->me->klass == klass) && ent->mid == id) { + ent->me = ent->mid = 0; } ent++; } @@ -75,7 +71,7 @@ rb_clear_cache_by_id(ID id) end = ent + CACHE_SIZE; while (ent < end) { if (ent->mid == id) { - ent->mid = 0; + ent->me = ent->mid = 0; } ent++; } @@ -93,17 +89,43 @@ rb_clear_cache_by_class(VALUE klass) ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - if (ent->klass == klass || ent->oklass == klass) { - ent->mid = 0; + if (ent->klass == klass || (ent->me && ent->me->klass == klass)) { + ent->me = ent->mid = 0; } ent++; } } +VALUE rb_f_notimplement(int argc, VALUE *argv, VALUE obj) +{ + rb_notimplement(); +} + +static void rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex) +{ + rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex); +} + void -rb_add_method(VALUE klass, ID mid, NODE * node, int noex) +rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex) { - NODE *body; + if (func != rb_f_notimplement) { + rb_method_cfunc_t opt = { + func, argc, + }; + rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex); + } + else { + rb_define_notimplement_method_id(klass, mid, noex); + } +} + +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; + st_table *mtbl; + st_data_t data; if (NIL_P(klass)) { klass = rb_cObject; @@ -113,15 +135,16 @@ rb_add_method(VALUE klass, ID mid, NODE * node, int noex) rb_raise(rb_eSecurityError, "Insecure: can't define method"); } if (!FL_TEST(klass, FL_SINGLETON) && - node && nd_type(node) != NODE_ZSUPER && + type != VM_METHOD_TYPE_NOTIMPLEMENTED && + type != VM_METHOD_TYPE_ZSUPER && (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { noex = NOEX_PRIVATE | noex; } - else if (FL_TEST(klass, FL_SINGLETON) && node - && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) { - rb_warn - ("defining %s.allocate is deprecated; use rb_define_alloc_func()", - rb_class2name(rb_iv_get(klass, "__attached__"))); + else if (FL_TEST(klass, FL_SINGLETON) && + type == VM_METHOD_TYPE_CFUNC && + mid == rb_intern("allocate")) { + rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()", + rb_class2name(rb_iv_get(klass, "__attached__"))); mid = ID_ALLOCATOR; } if (OBJ_FROZEN(klass)) { @@ -129,189 +152,178 @@ rb_add_method(VALUE klass, ID mid, NODE * node, int noex) } rb_clear_cache_by_id(mid); - /* - * NODE_METHOD (NEW_METHOD(body, klass, vis)): - * nd_file : original id // RBASIC()->klass (TODO: dirty hack) - * nd_body : method body // (2) // mark - * nd_clss : klass // (1) // mark - * nd_noex : visibility // (3) - * - * NODE_FBODY (NEW_FBODY(method, alias)): - * nd_body : method (NODE_METHOD) // (2) // mark - * nd_oid : original id // (1) - * nd_cnt : alias count // (3) - */ - if (node) { - NODE *method = NEW_NODE_LONGLIFE(NODE_METHOD, - rb_gc_write_barrier(klass), - rb_gc_write_barrier((VALUE)node), - NOEX_WITH_SAFE(noex)); - method->nd_file = (void *)mid; - body = NEW_NODE_LONGLIFE(NODE_FBODY, mid, method, 0); - } - else { - body = 0; - } - - { - /* check re-definition */ - st_data_t data; - NODE *old_node; - - if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) { - old_node = (NODE *)data; - if (old_node) { - if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(old_node); - } - if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) { - rb_warning("method redefined; discarding old %s", rb_id2name(mid)); - } - } - } - if (klass == rb_cObject && node && mid == idInitialize) { - rb_warn("redefining Object#initialize may cause infinite loop"); + 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_vm_check_redefinition_opt_method(old_me); + + if (RTEST(ruby_verbose) && + old_me->alias_count == 0 && + old_me->type != VM_METHOD_TYPE_UNDEF) { + rb_warning("method redefined; discarding old %s", rb_id2name(mid)); } - if (mid == object_id || mid == id__send__) { - if (node && nd_type(node) == RUBY_VM_METHOD_NODE) { - rb_warn("redefining `%s' may cause serious problems", - rb_id2name(mid)); - } + // TODO: free old_me + } + + /* check mid */ + if (klass == rb_cObject && mid == idInitialize) { + rb_warn("redefining Object#initialize may cause infinite loop"); + } + /* check mid */ + if (mid == object_id || mid == id__send__) { + if (type == VM_METHOD_TYPE_ISEQ) { + rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid)); } } - st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body); + st_insert(mtbl, mid, (st_data_t) me); - if (node && mid != ID_ALLOCATOR && ruby_running) { + if (mid != ID_ALLOCATOR && ruby_running) { if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, - ID2SYM(mid)); + rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid)); } else { rb_funcall(klass, added, 1, ID2SYM(mid)); } } + + return me; } void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) { Check_Type(klass, T_CLASS); - rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, - NEW_NODE_LONGLIFE(NODE_CFUNC, func, 0, 0), - NOEX_PRIVATE); + rb_add_method_cfunc(rb_singleton_class(klass), ID_ALLOCATOR, + func, 0, NOEX_PRIVATE); } void rb_undef_alloc_func(VALUE klass) { Check_Type(klass, T_CLASS); - rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); + rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF); } rb_alloc_func_t rb_get_alloc_func(VALUE klass) { - NODE *n; + rb_method_entry_t *me; Check_Type(klass, T_CLASS); - n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR); - if (!n) return 0; - if (nd_type(n) != NODE_METHOD) return 0; - n = n->nd_body; - if (nd_type(n) != NODE_CFUNC) return 0; - return (rb_alloc_func_t)n->nd_cfnc; + 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; + } + else { + return 0; + } } -static NODE * -search_method(VALUE klass, ID id, VALUE *klassp) +static rb_method_entry_t* +search_method(VALUE klass, ID id) { st_data_t body; - if (!klass) { return 0; } while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { klass = RCLASS_SUPER(klass); - if (!klass) + if (!klass) { return 0; + } } - if (klassp) { - *klassp = klass; - } - - return (NODE *)body; + return (rb_method_entry_t *)body; } /* - * search method body (NODE_METHOD) - * with : klass and id - * without : method cache + * search method entry without method cache. * - * if you need method node with method cache, use - * rb_method_node() + * if you need method entry with method cache, use + * rb_method_entry() */ -NODE * -rb_get_method_body(VALUE klass, ID id, ID *idp) +rb_method_entry_t * +rb_get_method_entry(VALUE klass, ID id) { - NODE *volatile fbody, *body; - NODE *method; - - if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) { - /* store empty info in cache */ - struct cache_entry *ent; - ent = cache + EXPR1(klass, id); - ent->klass = klass; - ent->mid = ent->mid0 = id; - ent->method = 0; - ent->oklass = 0; - return 0; - } - - method = fbody->nd_body; + rb_method_entry_t *me = search_method(klass, id); if (ruby_running) { - /* store in cache */ struct cache_entry *ent; ent = cache + EXPR1(klass, id); ent->klass = klass; - ent->mid = id; - ent->mid0 = fbody->nd_oid; - ent->method = body = method; - ent->oklass = method->nd_clss; - } - else { - body = method; - } - if (idp) { - *idp = fbody->nd_oid; + if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + ent->mid = id; + ent->me = 0; + me = 0; + } + else { + ent->mid = id; + ent->me = me; + } } - return body; + return me; } -NODE * -rb_method_node(VALUE klass, ID id) +rb_method_entry_t * +rb_method_entry(VALUE klass, ID id) { struct cache_entry *ent; ent = cache + EXPR1(klass, id); if (ent->mid == id && ent->klass == klass) { - if (ent->method) return ent->method; - return 0; + return ent->me; } - return rb_get_method_body(klass, id, 0); + return rb_get_method_entry(klass, id); } static void remove_method(VALUE klass, ID mid) { st_data_t data; - NODE *body = 0; + rb_method_entry_t *me = 0; if (klass == rb_cObject) { rb_secure(4); @@ -324,26 +336,26 @@ remove_method(VALUE klass, ID mid) if (mid == object_id || mid == id__send__ || mid == idInitialize) { rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); } + if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) { - body = (NODE *)data; - if (!body || !body->nd_body) body = 0; + me = (rb_method_entry_t *)data; + if (!me || me->type == VM_METHOD_TYPE_UNDEF) { + me = 0; + } else { st_delete(RCLASS_M_TBL(klass), &mid, &data); } } - if (!body) { + if (!me) { rb_name_error(mid, "method `%s' not defined in %s", rb_id2name(mid), rb_class2name(klass)); } - if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(body); - } - + rb_vm_check_redefinition_opt_method(me); rb_clear_cache_for_undef(klass, mid); + if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, - ID2SYM(mid)); + rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid)); } else { rb_funcall(klass, removed, 1, ID2SYM(mid)); @@ -393,49 +405,45 @@ rb_enable_super(VALUE klass, const char *name) static void rb_export_method(VALUE klass, ID name, ID noex) { - NODE *fbody; - VALUE origin; + rb_method_entry_t *me; if (klass == rb_cObject) { rb_secure(4); } - fbody = search_method(klass, name, &origin); - if (!fbody && TYPE(klass) == T_MODULE) { - fbody = search_method(rb_cObject, name, &origin); + + me = search_method(klass, name); + if (!me && TYPE(klass) == T_MODULE) { + me = search_method(rb_cObject, name); } - if (!fbody || !fbody->nd_body) { + + if (!me || me->type == VM_METHOD_TYPE_UNDEF) { rb_print_undef(klass, name, 0); } - if (fbody->nd_body->nd_noex != noex) { - if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(fbody); - } - if (klass == origin) { - fbody->nd_body->nd_noex = noex; + + if (me->flag != noex) { + rb_vm_check_redefinition_opt_method(me); + + if (klass == me->klass) { + me->flag = noex; } else { - rb_add_method(klass, name, NEW_ZSUPER(), noex); + rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); } } } int -rb_notimplement_body_p(NODE *method) -{ - return method == notimplement_body ? Qtrue : Qfalse; -} - -int rb_method_boundp(VALUE klass, ID id, int ex) { - NODE *method; + rb_method_entry_t *me = rb_method_entry(klass, id); - if ((method = rb_method_node(klass, id)) != 0) { - if (ex && (method->nd_noex & NOEX_PRIVATE)) { + if (me != 0) { + if (ex && (me->flag & NOEX_PRIVATE)) { return Qfalse; } - if (rb_notimplement_body_p(method->nd_body)) + if (me->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { return Qfalse; + } return Qtrue; } return Qfalse; @@ -447,7 +455,7 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex) const char *name; ID attriv; VALUE aname; - int noex; + rb_method_flag_t noex; if (!ex) { noex = NOEX_PUBLIC; @@ -478,32 +486,32 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex) rb_enc_copy(aname, rb_id2str(id)); attriv = rb_intern_str(aname); if (read) { - rb_add_method(klass, id, NEW_IVAR(attriv), noex); + rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex); } if (write) { - rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex); + rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex); } } void rb_undef(VALUE klass, ID id) { - VALUE origin; - NODE *body; + rb_method_entry_t *me; if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { - rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", - rb_id2name(id)); + rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == id__send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); } - body = search_method(klass, id, &origin); - if (!body || !body->nd_body) { + + me = search_method(klass, id); + + if (!me || me->type == VM_METHOD_TYPE_UNDEF) { const char *s0 = " class"; VALUE c = klass; @@ -524,11 +532,10 @@ rb_undef(VALUE klass, ID id) rb_id2name(id), s0, rb_class2name(c)); } - rb_add_method(klass, id, 0, NOEX_PUBLIC); + rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), - singleton_undefined, 1, ID2SYM(id)); + rb_funcall(rb_iv_get(klass, "__attached__"), singleton_undefined, 1, ID2SYM(id)); } else { rb_funcall(klass, undefined, 1, ID2SYM(id)); @@ -622,6 +629,18 @@ rb_mod_method_defined(VALUE mod, VALUE mid) #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f)) +static VALUE +check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex) +{ + const rb_method_entry_t *me; + me = rb_method_entry(mod, mid); + if (me) { + if (VISI_CHECK(me->flag, noex)) + return Qtrue; + } + return Qfalse; +} + /* * call-seq: * mod.public_method_defined?(symbol) => true or false @@ -651,15 +670,7 @@ rb_mod_method_defined(VALUE mod, VALUE mid) static VALUE rb_mod_public_method_defined(VALUE mod, VALUE mid) { - ID id = rb_to_id(mid); - NODE *method; - - method = rb_method_node(mod, id); - if (method) { - if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC)) - return Qtrue; - } - return Qfalse; + return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC); } /* @@ -691,15 +702,7 @@ rb_mod_public_method_defined(VALUE mod, VALUE mid) static VALUE rb_mod_private_method_defined(VALUE mod, VALUE mid) { - ID id = rb_to_id(mid); - NODE *method; - - method = rb_method_node(mod, id); - if (method) { - if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE)) - return Qtrue; - } - return Qfalse; + return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE); } /* @@ -731,70 +734,100 @@ rb_mod_private_method_defined(VALUE mod, VALUE mid) static VALUE rb_mod_protected_method_defined(VALUE mod, VALUE mid) { - ID id = rb_to_id(mid); - NODE *method; + return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED); +} - method = rb_method_node(mod, id); - if (method) { - if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED)) - return Qtrue; +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; + 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) { + return 0; + } + switch (m1->type) { + case VM_METHOD_TYPE_ISEQ: + return m1->body.iseq == m2->body.iseq; + case VM_METHOD_TYPE_CFUNC: + return + m1->body.cfunc.func == m2->body.cfunc.func && + m1->body.cfunc.argc == m2->body.cfunc.argc; + case VM_METHOD_TYPE_ATTRSET: + case VM_METHOD_TYPE_IVAR: + return m1->body.attr_id == m2->body.attr_id; + case VM_METHOD_TYPE_BMETHOD: + return m1->body.proc == m2->body.proc; + case VM_METHOD_TYPE_ZSUPER: + case VM_METHOD_TYPE_NOTIMPLEMENTED: + case VM_METHOD_TYPE_UNDEF: + return 1; + default: + rb_bug("rb_add_method: unsupported method type (%d)\n", m1->type); + return 0; } - return Qfalse; } void rb_alias(VALUE klass, ID name, ID def) { - NODE *orig_fbody, *node, *method; + rb_method_entry_t *orig_me, *me; VALUE singleton = 0; - st_data_t data; rb_frozen_class_p(klass); if (klass == rb_cObject) { rb_secure(4); } - orig_fbody = search_method(klass, def, 0); - if (!orig_fbody || !orig_fbody->nd_body) { + + orig_me = search_method(klass, def); + + if (!orig_me || orig_me->type == VM_METHOD_TYPE_UNDEF) { if (TYPE(klass) == T_MODULE) { - orig_fbody = search_method(rb_cObject, def, 0); + orig_me = search_method(rb_cObject, def); + + if (!orig_me || !orig_me->type == VM_METHOD_TYPE_UNDEF) { + rb_print_undef(klass, def, 0); + } } } - if (!orig_fbody || !orig_fbody->nd_body) { - rb_print_undef(klass, def, 0); - } if (FL_TEST(klass, FL_SINGLETON)) { singleton = rb_iv_get(klass, "__attached__"); } - orig_fbody->nd_cnt++; - - if (st_lookup(RCLASS_M_TBL(klass), name, &data)) { - node = (NODE *)data; - if (node) { - if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) { - rb_warning("discarding old %s", rb_id2name(name)); - } - if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(node); - } - } - } + orig_me->alias_count++; + me = rb_add_method(klass, name, orig_me->type, me_opts(orig_me), orig_me->flag); + me->original_id = def; - st_insert(RCLASS_M_TBL(klass), name, - (st_data_t) NEW_NODE_LONGLIFE( - NODE_FBODY, - def, - method = NEW_NODE_LONGLIFE(NODE_METHOD, - rb_gc_write_barrier((VALUE)orig_fbody->nd_body->nd_clss), - rb_gc_write_barrier((VALUE)orig_fbody->nd_body->nd_body), - NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), - 0)); - method->nd_file = (void *)def; + if (!ruby_running) return; rb_clear_cache_by_id(name); - if (!ruby_running) return; - if (singleton) { rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); } @@ -832,18 +865,6 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) return mod; } -VALUE -rb_f_notimplement(int argc, VALUE *argv, VALUE obj) -{ - rb_notimplement(); -} - -void -rb_define_notimplement_method_id(VALUE mod, ID id, int noex) -{ - rb_add_method(mod, id, notimplement_body, noex); -} - static void secure_visibility(VALUE self) { @@ -1042,7 +1063,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) { int i; ID id; - NODE *fbody; + const rb_method_entry_t *me; if (TYPE(module) != T_MODULE) { rb_raise(rb_eTypeError, "module_function must be called for modules"); @@ -1061,22 +1082,21 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) id = rb_to_id(argv[i]); for (;;) { - fbody = search_method(m, id, &m); - if (fbody == 0) { - fbody = search_method(rb_cObject, id, &m); + me = search_method(m, id); + if (me == 0) { + me = search_method(rb_cObject, id); } - if (fbody == 0 || fbody->nd_body == 0) { + if (me == 0 || me->type == VM_METHOD_TYPE_UNDEF) { rb_print_undef(module, id, 0); } - if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) { - break; /* normal case: need not to follow 'super' link */ + if (me->type != VM_METHOD_TYPE_ZSUPER) { + break; /* normal case: need not to follow 'super' link */ } m = RCLASS_SUPER(m); if (!m) break; } - rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body, - NOEX_PUBLIC); + rb_add_method_me(rb_singleton_class(module), id, me, NOEX_PUBLIC); } return module; } @@ -1084,8 +1104,8 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) int rb_method_basic_definition_p(VALUE klass, ID id) { - NODE *node = rb_method_node(klass, id); - if (node && (node->nd_noex & NOEX_BASIC)) + const rb_method_entry_t *me = rb_method_entry(klass, id); + if (me && (me->flag & NOEX_BASIC)) return 1; return 0; } @@ -1174,8 +1194,5 @@ Init_eval_method(void) singleton_removed = rb_intern("singleton_method_removed"); undefined = rb_intern("method_undefined"); singleton_undefined = rb_intern("singleton_method_undefined"); - - notimplement_body = NEW_CFUNC(rb_f_notimplement, -1); - rb_gc_register_mark_object((VALUE)notimplement_body); } |