diff --git a/runtime.c b/runtime.c index 0f203beb..f0149024 100644 --- a/runtime.c +++ b/runtime.c @@ -19,6 +19,7 @@ #include Class objc_next_class(void*); +struct objc_slot *objc_get_slot(Class cls, SEL selector); /** * Looks up the instance method in a specific class, without recursing into @@ -257,18 +258,15 @@ id class_createInstance(Class cls, size_t extraBytes) Method class_getInstanceMethod(Class aClass, SEL aSelector) { - Method method = class_getInstanceMethodNonrecursive(aClass, aSelector); - if (method == NULL) - { - // TODO: Check if this should be NULL or aClass - Class superclass = class_getSuperclass(aClass); - if (superclass == NULL) - { - return NULL; - } - return class_getInstanceMethod(superclass, aSelector); - } - return method; + // Do a dtable lookup to find out which class the method comes from. + struct objc_slot *slot = objc_get_slot(aClass, aSelector); + if (NULL == slot) { return NULL; } + + // Now find the typed variant of the selector, with the correct types. + aSelector = sel_registerTypedName_np(sel_getName(aSelector), slot->types); + + // Then do the slow lookup to find the method. + return class_getInstanceMethodNonrecursive(slot->owner, aSelector); } Method class_getClassMethod(Class aClass, SEL aSelector) @@ -359,10 +357,11 @@ BOOL class_isMetaClass(Class cls) IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) { - Method method = class_getInstanceMethodNonrecursive(cls, name); + SEL sel = sel_registerTypedName_np(sel_getName(name), types); + Method method = class_getInstanceMethodNonrecursive(cls, sel); if (method == NULL) { - class_addMethod(cls, name, imp, types); + class_addMethod(cls, sel, imp, types); return NULL; } IMP old = (IMP)method->imp; diff --git a/selector_table.c b/selector_table.c index 807035cd..70c25923 100644 --- a/selector_table.c +++ b/selector_table.c @@ -344,7 +344,7 @@ const char *sel_getType_np(SEL aSel) } -unsigned sel_copyTypes(const char *selName, const char **types, unsigned count) +unsigned sel_copyTypes_np(const char *selName, const char **types, unsigned count) { SEL untyped = selector_lookup(selName, 0); if (untyped == NULL) { return 0; } @@ -373,6 +373,35 @@ unsigned sel_copyTypes(const char *selName, const char **types, unsigned count) return found; } +unsigned sel_copyTypedSelectors_np(const char *selName, SEL *const sels, unsigned count) +{ + SEL untyped = selector_lookup(selName, 0); + if (untyped == NULL) { return 0; } + + struct sel_type_list *l = + SparseArrayLookup(selector_list, (uint32_t)(uintptr_t)untyped->name); + // Skip the head, which just contains the name, not the types. + l = l->next; + + if (count == 0) + { + while (NULL != l) + { + count++; + l = l->next; + } + return count; + } + + unsigned found = 0; + while (NULL != l && foundvalue); + l = l->next; + } + return found; +} + void objc_register_selectors_from_list(struct objc_method_list *l) { for (int i=0 ; icount ; i++)