void objc_update_dtable(Class cls) { struct objc_method_list* ml; struct objc_category** cats; unsigned int i; if (!(cls->info & OBJC_CLASS_INFO_DTABLE)) return; if (cls->dtable == empty_dtable) cls->dtable = objc_sparsearray_new(); if (cls->superclass != Nil) objc_sparsearray_copy(cls->dtable, cls->superclass->dtable); for (ml = cls->methodlist; ml != NULL; ml = ml->next) for (i = 0; i < ml->count; i++) objc_sparsearray_set(cls->dtable, (uint32_t)ml->methods[i].sel.uid, ml->methods[i].imp); if ((cats = objc_categories_for_class(cls)) != NULL) { for (i = 0; cats[i] != NULL; i++) { unsigned int j; ml = (cls->info & OBJC_CLASS_INFO_CLASS ? cats[i]->instance_methods : cats[i]->class_methods); for (; ml != NULL; ml = ml->next) for (j = 0; j < ml->count; j++) objc_sparsearray_set(cls->dtable, (uint32_t)ml->methods[j].sel.uid, ml->methods[j].imp); } } if (cls->subclass_list != NULL) for (i = 0; cls->subclass_list[i] != NULL; i++) objc_update_dtable(cls->subclass_list[i]); }
const char* objc_get_type_encoding(Class cls, SEL sel) { struct objc_method_list* ml; struct objc_category** cats; unsigned int i; objc_global_mutex_lock(); for (ml = cls->methodlist; ml != NULL; ml = ml->next) { for (i = 0; i < ml->count; i++) { if (ml->methods[i].sel.uid == sel->uid) { const char* ret = ml->methods[i].sel.types; objc_global_mutex_unlock(); return ret; } } } if ((cats = objc_categories_for_class(cls)) != NULL) { for (; *cats != NULL; cats++) { for (ml = (*cats)->instance_methods; ml != NULL; ml = ml->next) { for (i = 0; i < ml->count; i++) { if (ml->methods[i].sel.uid == sel->uid) { const char* ret = ml->methods[i].sel.types; objc_global_mutex_unlock(); return ret; } } } } } objc_global_mutex_unlock(); return NULL; }
// INVARIANT: This must happen under lock. IMP _class_lookupMethodImplementation(Class cls, SEL sel, struct objc_method **outMethod) { struct objc_method *method = NULL; struct objc_method_list *ml; struct objc_category **cats; unsigned int i; for (ml = cls->methodlist; ml != NULL; ml = ml->next) { for (i = 0; i < ml->count; i++) { if (ml->methods[i].sel.uid == sel->uid) { method = &ml->methods[i]; goto out; } } } if ((cats = objc_categories_for_class(cls)) != NULL) { for (; *cats != NULL; cats++) { if (cls->info & OBJC_CLASS_INFO_METACLASS) ml = (*cats)->class_methods; else ml = (*cats)->instance_methods; for (; ml != NULL; ml = ml->next) { for (i = 0; i < ml->count; i++) { if (ml->methods[i].sel.uid == sel->uid) { method = &ml->methods[i]; goto out; } } } } } out: if(method) { if(outMethod) { *outMethod = method; } return method->imp; } return (IMP)nil; }