Method class_getInstanceMethod(Class aClass, SEL aSelector) { CHECK_ARG(aClass); CHECK_ARG(aSelector); // If the class has a dtable installed, then we can use the fast path if (classHasInstalledDtable(aClass)) { // 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) { slot = objc_get_slot(aClass, sel_registerName(sel_getName(aSelector))); if (NULL == slot) { return NULL; } } // Now find the typed variant of the selector, with the correct types. aSelector = slot->selector; // Then do the slow lookup to find the method. return class_getInstanceMethodNonrecursive(slot->owner, aSelector); } Method m = class_getInstanceMethodNonrecursive(aClass, aSelector); if (NULL != m) { return m; } return class_getInstanceMethod(class_getSuperclass(aClass), aSelector); }
/** * Checks whether the class implements memory management methods, and whether * they are safe to use with ARC. */ static void checkARCAccessors(Class cls) { static SEL retain, release, autorelease, isARC; if (NULL == retain) { retain = sel_registerName("retain"); release = sel_registerName("release"); autorelease = sel_registerName("autorelease"); isARC = sel_registerName("_ARCCompliantRetainRelease"); } struct objc_slot *slot = objc_get_slot(cls, retain); if ((NULL != slot) && !ownsMethod(slot->owner, isARC)) { objc_clear_class_flag(cls, objc_class_flag_fast_arc); return; } slot = objc_get_slot(cls, release); if ((NULL != slot) && !ownsMethod(slot->owner, isARC)) { objc_clear_class_flag(cls, objc_class_flag_fast_arc); return; } slot = objc_get_slot(cls, autorelease); if ((NULL != slot) && !ownsMethod(slot->owner, isARC)) { objc_clear_class_flag(cls, objc_class_flag_fast_arc); return; } objc_set_class_flag(cls, objc_class_flag_fast_arc); }
static inline BOOL _objc_check_class_for_custom_arr_method(Class cls, SEL sel){ struct objc_slot *slot = objc_get_slot(cls, sel); if (NULL != slot && slot->owner == cls){ cls->flags.has_custom_arr = YES; return YES; } return NO; }
/* * Returns YES if the class implements a method for the specified selector, NO * otherwise. */ static BOOL ownsMethod(Class cls, SEL sel) { struct objc_slot *slot = objc_get_slot(cls, sel); if ((NULL != slot) && (slot->owner == cls)) { return YES; } return NO; }
static void call_cxx_construct_for_class(Class cls, id obj) { static SEL cxx_construct; if (NULL == cxx_construct) { cxx_construct = sel_registerName(".cxx_construct"); } struct objc_slot *slot = objc_get_slot(cls, cxx_construct); if (NULL != slot) { cls = slot->owner->super_class; if (Nil != cls) { call_cxx_construct_for_class(cls, obj); } slot->method(obj, cxx_construct); } }
/** * Calls C++ destructors in the correct order. */ PRIVATE void call_cxx_destruct(id obj) { static SEL cxx_destruct; if (NULL == cxx_destruct) { cxx_destruct = sel_registerName(".cxx_destruct"); } // Don't call object_getClass(), because we want to get hidden classes too Class cls = classForObject(obj); while (cls) { struct objc_slot *slot = objc_get_slot(cls, cxx_destruct); cls = Nil; if (NULL != slot) { cls = slot->owner->super_class; slot->method(obj, cxx_destruct); } } }