diff --git a/NSBlocks.m b/NSBlocks.m index 17851bb..4571290 100644 --- a/NSBlocks.m +++ b/NSBlocks.m @@ -12,6 +12,7 @@ static struct objc_class _NSBlock; static struct objc_class _NSBlockMeta; void __objc_update_dispatch_table_for_class(Class); +void __objc_add_class_to_hash(Class); extern struct sarray *__objc_uninstalled_dtable; extern objc_mutex_t __objc_runtime_mutex; @@ -19,32 +20,20 @@ static void createNSBlockSubclass(Class superclass, Class newClass, Class metaClass, char *name) { // Initialize the metaclass - metaClass->class_pointer = superclass->class_pointer; - metaClass->super_class = superclass->class_pointer; + //metaClass->class_pointer = superclass->class_pointer; + //metaClass->super_class = superclass->class_pointer; metaClass->info = _CLS_META; metaClass->dtable = __objc_uninstalled_dtable; // Set up the new class newClass->class_pointer = metaClass; - newClass->super_class = superclass; + newClass->super_class = superclass->name; newClass->name = name; newClass->info = _CLS_CLASS; newClass->dtable = __objc_uninstalled_dtable; - // Initialize the dispatch table for the class and metaclass. - __objc_update_dispatch_table_for_class(metaClass); - __objc_update_dispatch_table_for_class(newClass); - CLS_SETINITIALIZED(metaClass); - CLS_SETINITIALIZED(newClass); - CLS_SETRESOLV(metaClass); - CLS_SETRESOLV(newClass); - // Add pointer from super class - objc_mutex_lock(__objc_runtime_mutex); - newClass->sibling_class = newClass->super_class->subclass_list; - newClass->super_class->subclass_list = newClass; - metaClass->sibling_class = metaClass->super_class->subclass_list; - metaClass->super_class->subclass_list = metaClass; - objc_mutex_unlock(__objc_runtime_mutex); + __objc_add_class_to_hash(newClass); + } #define NEW_CLASS(super, sub) \ diff --git a/class.c b/class.c index 5f892f4..e8fee53 100644 --- a/class.c +++ b/class.c @@ -224,87 +224,6 @@ objc_next_class (void **enum_state) return class; } -/* Resolve super/subclass links for all classes. The only thing we - can be sure of is that the class_pointer for class objects point to - the right meta class objects. */ -void -__objc_resolve_class_links (void) -{ - void *es = NULL; - Class object_class = objc_get_class (ROOT_OBJECT_CLASS_NAME); - Class class1; - - assert (object_class); - - LOCK(__objc_runtime_mutex); - - - /* Assign subclass links. */ - while ((class1 = class_table_next (&es))) - { - /* Make sure we have what we think we have. */ - assert (CLS_ISCLASS (class1)); - assert (CLS_ISMETA (class1->class_pointer)); - - /* The class_pointer of all meta classes point to Object's meta - class. */ - class1->class_pointer->class_pointer = object_class->class_pointer; - - if (! CLS_ISRESOLV (class1)) - { - CLS_SETRESOLV (class1); - CLS_SETRESOLV (class1->class_pointer); - - if (class1->super_class) - { - Class a_super_class - = objc_get_class ((char *) class1->super_class); - - assert (a_super_class); - - DEBUG_PRINTF ("making class connections for: %s\n", - class1->name); - - /* Assign subclass links for superclass. */ - class1->sibling_class = a_super_class->subclass_list; - a_super_class->subclass_list = class1; - - /* Assign subclass links for meta class of superclass. */ - if (a_super_class->class_pointer) - { - class1->class_pointer->sibling_class - = a_super_class->class_pointer->subclass_list; - a_super_class->class_pointer->subclass_list - = class1->class_pointer; - } - } - else /* A root class, make its meta object be a subclass of - Object. */ - { - class1->class_pointer->sibling_class - = object_class->subclass_list; - object_class->subclass_list = class1->class_pointer; - } - } - } - - /* Assign superclass links. */ - es = NULL; - while ((class1 = class_table_next (&es))) - { - Class sub_class; - for (sub_class = class1->subclass_list; sub_class; - sub_class = sub_class->sibling_class) - { - sub_class->super_class = class1; - if (CLS_ISCLASS (sub_class)) - sub_class->class_pointer->super_class = class1->class_pointer; - } - } - - UNLOCK(__objc_runtime_mutex); -} - Class class_pose_as (Class impostor, Class super_class) { diff --git a/class_table.c b/class_table.c index 902abb9..232c7b6 100644 --- a/class_table.c +++ b/class_table.c @@ -1,6 +1,8 @@ +#include "magic_objects.h" #include "objc/objc-api.h" #include "lock.h" #include +#include // Get the functions for string hashing #include "string_hash.h" @@ -26,8 +28,25 @@ static int class_hash(const Class class) static class_table_internal_table *class_table; + +#define unresolved_class_next subclass_list +#define unresolved_class_prev sibling_class +/** + * Linked list using the subclass_list pointer in unresolved classes. + */ +static Class unresolved_class_list; + void class_table_insert(Class class) { + if (!CLS_ISRESOLV(class)) + { + if (Nil != unresolved_class_list) + { + unresolved_class_list->unresolved_class_prev = class; + } + class->unresolved_class_next = unresolved_class_list; + unresolved_class_list = class; + } class_table_internal_insert(class_table, class); } @@ -36,8 +55,7 @@ Class class_table_get_safe(const char *class_name) return class_table_internal_table_get(class_table, class_name); } -Class -class_table_next (void **e) +Class class_table_next(void **e) { return class_table_internal_next(class_table, (struct class_table_internal_table_enumerator**)e); @@ -47,3 +65,75 @@ void __objc_init_class_tables(void) { class_table = class_table_internal_create(16); } + +static void objc_resolve_class(Class cls) +{ + // Skip this if the class is already resolved. + if (CLS_ISRESOLV(cls)) { return; } + // Remove the class from the unresolved class list + if (Nil == cls->unresolved_class_prev) + { + unresolved_class_list = cls->unresolved_class_next; + } + else + { + cls->unresolved_class_prev->unresolved_class_next = + cls->unresolved_class_next; + } + if (Nil != cls->unresolved_class_next) + { + cls->unresolved_class_next->unresolved_class_prev = + cls->unresolved_class_prev; + } + cls->unresolved_class_prev = Nil; + cls->unresolved_class_next = Nil; + + static Class root_class = Nil; + if (Nil == root_class) + { + root_class = objc_get_class(ROOT_OBJECT_CLASS_NAME); + if (!CLS_ISRESOLV(root_class)) + { + objc_resolve_class(root_class); + } + assert(root_class); + } + + // Resolve the superclass pointer + + // If this class has no superclass, use [NS]Object + Class super = root_class; + Class superMeta = root_class; + if (NULL != cls->super_class) + { + // Resolve the superclass if it isn't already resolved + super = objc_get_class((char*)cls->super_class); + if (!CLS_ISRESOLV(super)) + { + objc_resolve_class(super); + } + superMeta = super->class_pointer; + // Set the superclass pointer for the class and the superclass + cls->super_class = super; + cls->class_pointer->super_class = super->class_pointer; + } + // Set up the class links + cls->sibling_class = super->subclass_list; + super->subclass_list = cls; + // Set up the metaclass links + cls->class_pointer->sibling_class = superMeta->subclass_list; + superMeta->subclass_list = cls->class_pointer; + // Mark this class (and its metaclass) as resolved + CLS_SETRESOLV(cls); + CLS_SETRESOLV(cls->class_pointer); +} + +void __objc_resolve_class_links(void) +{ + LOCK(__objc_runtime_mutex); + Class class; + while ((class = unresolved_class_list)) + { + objc_resolve_class(class); + } +}