Skip to content

Commit

Permalink
moved the removed_method code to the VM + fixed undef_method callbacks
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2960 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Nov 5, 2009
1 parent 768fcbb commit e732379
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 41 deletions.
4 changes: 4 additions & 0 deletions id.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ Init_id(void)
selBackquote = sel_registerName("`:");
selMethodAdded = sel_registerName("method_added:");
selSingletonMethodAdded = sel_registerName("singleton_method_added:");
selMethodRemoved = sel_registerName("method_removed:");
selSingletonMethodRemoved = sel_registerName("singleton_method_removed:");
selMethodUndefined = sel_registerName("method_undefined:");
selSingletonMethodUndefined = sel_registerName("singleton_method_undefined:");
selIsEqual = sel_registerName("isEqual:");
selWrite = sel_registerName("write:");
selInherited = sel_registerName("inherited:");
Expand Down
4 changes: 4 additions & 0 deletions id.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ extern SEL selDup;
extern SEL selBackquote;
extern SEL selMethodAdded;
extern SEL selSingletonMethodAdded;
extern SEL selMethodRemoved;
extern SEL selSingletonMethodRemoved;
extern SEL selMethodUndefined;
extern SEL selSingletonMethodUndefined;
extern SEL selIsEqual;
extern SEL selWrite;
extern SEL selInherited;
Expand Down
60 changes: 54 additions & 6 deletions vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2311,16 +2311,14 @@ RoxorCore::undef_method(Class klass, SEL sel)
ruby_methods.erase(iter);
#endif

#if 0
// TODO call undefined
VALUE sym = ID2SYM(rb_intern(sel_getName(sel)));
if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"),
singleton_undefined, 1, ID2SYM(id));
VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
rb_vm_call(sk, selSingletonMethodUndefined, 1, &sym, false);
}
else {
rb_funcall(klass, undefined, 1, ID2SYM(id));
rb_vm_call((VALUE)klass, selMethodUndefined, 1, &sym, false);
}
#endif
}

extern "C"
Expand Down Expand Up @@ -2352,6 +2350,56 @@ rb_vm_undef_method(Class klass, ID name, bool must_exist)
}
}

void
RoxorCore::remove_method(Class klass, SEL sel)
{
#if ROXOR_VM_DEBUG
printf("remove %c[%s %s]\n",
class_isMetaClass(klass) ? '+' : '-',
class_getName(klass),
sel_getName(sel));
#endif

Method m = class_getInstanceMethod(klass, sel);
assert(m != NULL);
method_setImplementation(m, (IMP)rb_vm_removed_imp);
invalidate_respond_to_cache();

VALUE sym = ID2SYM(rb_intern(sel_getName(sel)));
if (RCLASS_SINGLETON(klass)) {
VALUE sk = rb_iv_get((VALUE)klass, "__attached__");
rb_vm_call(sk, selSingletonMethodRemoved, 1, &sym, false);
}
else {
rb_vm_call((VALUE)klass, selMethodRemoved, 1, &sym, false);
}
}

extern "C"
void
rb_vm_remove_method(Class klass, ID name)
{
rb_vm_method_node_t *node = NULL;

if (!rb_vm_lookup_method2((Class)klass, name, NULL, NULL, &node)) {
rb_raise(rb_eNameError, "undefined method `%s' for %s `%s'",
rb_id2name(name),
TYPE(klass) == T_MODULE ? "module" : "class",
rb_class2name((VALUE)klass));
}
if (node == NULL) {
rb_raise(rb_eRuntimeError,
"cannot remove method `%s' because it is a native method",
rb_id2name(name));
}
if (node->klass != klass) {
rb_raise(rb_eNameError, "method `%s' not defined in %s",
rb_id2name(name), rb_class2name((VALUE)klass));
}

GET_CORE()->remove_method(klass, node->sel);
}

extern "C"
VALUE
rb_vm_masgn_get_elem_before_splat(VALUE ary, int offset)
Expand Down
2 changes: 2 additions & 0 deletions vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ void *rb_vm_removed_imp(void *rcv, SEL sel);
|| imp == (IMP)rb_vm_removed_imp)
void rb_vm_define_attr(Class klass, const char *name, bool read, bool write);
void rb_vm_undef_method(Class klass, ID name, bool must_exist);
void rb_vm_remove_method(Class klass, ID name);
void rb_vm_alias(VALUE klass, ID name, ID def);
void rb_vm_copy_methods(Class from_class, Class to_class);
VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args, bool super);
Expand Down Expand Up @@ -744,6 +745,7 @@ class RoxorCore {
rb_vm_method_node_t *retype_method(Class klass,
rb_vm_method_node_t *node, const char *types);
void undef_method(Class klass, SEL sel);
void remove_method(Class klass, SEL sel);
bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel);
void copy_methods(Class from_class, Class to_class);
Expand Down
39 changes: 4 additions & 35 deletions vm_method.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,43 +120,14 @@ remove_method(VALUE klass, ID mid)
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't remove method");
}
if (OBJ_FROZEN(klass))
if (OBJ_FROZEN(klass)) {
rb_error_frozen("class/module");
}
if (mid == object_id || mid == __send__ || mid == idInitialize) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
SEL sel;
Method m;

sel = sel_registerName(rb_id2name(mid));
m = class_getInstanceMethod((Class)klass, sel);
if (m == NULL) {
char buf[100];
size_t len = strlen((char *)sel);
if (((char *)sel)[len - 1] != ':') {
snprintf(buf, sizeof buf, "%s:", (char *)sel);
sel = sel_registerName(buf);
m = class_getInstanceMethod((Class)klass, sel);
}
}
if (m == NULL
|| class_getInstanceMethod((Class)RCLASS_SUPER(klass), sel) == m) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
}
if (!rb_vm_is_ruby_method(m)) {
rb_warn("removing pure Objective-C method `%s' may cause serious " \
"problem", rb_id2name(mid));
}
method_setImplementation(m, (IMP)rb_vm_removed_imp);

if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
ID2SYM(mid));
}
else {
rb_funcall(klass, removed, 1, ID2SYM(mid));
}
rb_vm_remove_method((Class)klass, mid);
}

void
Expand All @@ -176,9 +147,7 @@ rb_remove_method(VALUE klass, const char *name)
static VALUE
rb_mod_remove_method(VALUE mod, SEL sel, int argc, VALUE *argv)
{
int i;

for (i = 0; i < argc; i++) {
for (int i = 0; i < argc; i++) {
remove_method(mod, rb_to_id(argv[i]));
}
return mod;
Expand Down

0 comments on commit e732379

Please sign in to comment.