From ca2c7d1d9de0c8625d6c5f2e8dff17ce67b0e2ea Mon Sep 17 00:00:00 2001 From: theraven Date: Wed, 23 Feb 2011 12:00:11 +0000 Subject: [PATCH] Stop treating NSObject as magic and do what OS X does with regard to root objects and metaclasses. --- class_table.c | 63 +++++++++++++++++++++++------------------------ constant_string.h | 7 ++++++ loader.c | 1 - magic_objects.h | 7 ------ statics_loader.c | 4 +-- 5 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 constant_string.h delete mode 100644 magic_objects.h diff --git a/class_table.c b/class_table.c index f1e71c8..b422789 100644 --- a/class_table.c +++ b/class_table.c @@ -1,4 +1,3 @@ -#include "magic_objects.h" #include "objc/runtime.h" #include "objc/hooks.h" #include "objc/developer.h" @@ -161,21 +160,6 @@ BOOL objc_resolve_class(Class cls) } - // Give up if we can't resolve the root class yet... - static Class root_class = Nil; - if (Nil == root_class) - { - root_class = (Class)objc_getClass(ROOT_OBJECT_CLASS_NAME); - if (Nil == root_class) { return NO; } - - if (cls != root_class && !objc_test_class_flag(root_class, objc_class_flag_resolved)) - { - objc_resolve_class(root_class); - } - assert(root_class); - } - - // Remove the class from the unresolved class list if (Nil == cls->unresolved_class_prev) { @@ -194,17 +178,24 @@ BOOL objc_resolve_class(Class cls) cls->unresolved_class_prev = Nil; cls->unresolved_class_next = Nil; - // Resolve the superclass pointer + // The superclass for the metaclass. This is the metaclass for the + // superclass if one exists, otherwise it is the root class itself + Class superMeta = Nil; + // The metaclass for the metaclass. This is always the root class's + // metaclass. + Class metaMeta = Nil; - // If this class has no superclass, use [NS]Object - Class super = root_class; - Class superMeta = root_class; - Class meta = cls->isa; + // Resolve the superclass pointer - if (NULL != cls->super_class) + if (NULL == cls->super_class) + { + superMeta = cls; + metaMeta = cls->isa; + } + else { // Resolve the superclass if it isn't already resolved - super = (Class)objc_getClass((char*)cls->super_class); + Class super = (Class)objc_getClass((char*)cls->super_class); if (!objc_test_class_flag(super, objc_class_flag_resolved)) { objc_resolve_class(super); @@ -212,18 +203,26 @@ BOOL objc_resolve_class(Class cls) superMeta = super->isa; // Set the superclass pointer for the class and the superclass cls->super_class = super; + do + { + metaMeta = super->isa; + super = super->super_class; + } while (Nil != super); } + Class meta = cls->isa; - // Don't make the root class a subclass of itself - if (cls != super) + // Make the root class the superclass of the metaclass (e.g. NSObject is + // the superclass of all metaclasses in classes that inherit from NSObject) + meta->super_class = superMeta; + meta->isa = metaMeta; + + // Don't register root classes as children of anything + if (Nil != cls->super_class) { // Set up the class links - cls->sibling_class = super->subclass_list; - super->subclass_list = cls; + cls->sibling_class = cls->super_class->subclass_list; + cls->super_class->subclass_list = cls; } - // Make the root class the superclass of the metaclass (e.g. NSObject is - // the superclass of all metaclasses) - meta->super_class = superMeta; // Set up the metaclass links meta->sibling_class = superMeta->subclass_list; superMeta->subclass_list = meta; @@ -231,8 +230,8 @@ BOOL objc_resolve_class(Class cls) // Mark this class (and its metaclass) as resolved objc_set_class_flag(cls, objc_class_flag_resolved); objc_set_class_flag(cls->isa, objc_class_flag_resolved); - cls->isa->isa = (Nil == cls->isa->isa) ? root_class->isa : - ((Class)objc_getClass((char*)cls->isa->isa))->isa; + + // Fix up the ivar offsets objc_compute_ivar_offsets(cls); // Send the +load message, if required diff --git a/constant_string.h b/constant_string.h new file mode 100644 index 0000000..781a491 --- /dev/null +++ b/constant_string.h @@ -0,0 +1,7 @@ +#ifndef CONSTANT_STRING_CLASS +# ifdef GNUSTEP +# define CONSTANT_STRING_CLASS "NSConstantString" +# else +# define CONSTANT_STRING_CLASS "NXConstantString" +# endif +#endif diff --git a/loader.c b/loader.c index 0349c10..56fd3b4 100644 --- a/loader.c +++ b/loader.c @@ -3,7 +3,6 @@ #include "objc/runtime.h" #include "lock.h" #include "loader.h" -#include "magic_objects.h" /** * Runtime lock. This is exposed in diff --git a/magic_objects.h b/magic_objects.h deleted file mode 100644 index f29afb0..0000000 --- a/magic_objects.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifdef GNUSTEP -#define ROOT_OBJECT_CLASS_NAME "NSObject" -#define CONSTANT_STRING_CLASS "NSConstantString" -#else -#define ROOT_OBJECT_CLASS_NAME "Object" -#define CONSTANT_STRING_CLASS "NXConstantString" -#endif diff --git a/statics_loader.c b/statics_loader.c index 068f7ad..627d4a5 100644 --- a/statics_loader.c +++ b/statics_loader.c @@ -2,7 +2,7 @@ #include #include "objc/runtime.h" #include "module.h" -#include "magic_objects.h" +#include "constant_string.h" #define BUFFER_TYPE struct objc_static_instance_list #include "buffer.h" @@ -21,7 +21,7 @@ static BOOL try_init_statics(struct objc_static_instance_list *statics) // NXConstantString instances. This is a mess. We hack around this by // silently assuming that the user meant NSConstantString when they said // NXConstantString if NSConstantString is set as the constant string class - // in magic_objects.h + // in string_class.h or by an external -D flag. if (strcmp(class_name, "NXConstantString") == 0) { class_name = CONSTANT_STRING_CLASS;