From 0964d63ba96ac823f1c69981984c1f615248ce98 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Fri, 23 Mar 2018 10:22:31 +0000 Subject: [PATCH] Update for the compiler / linker setting up superclass pointers. In the legact ABI, superclass pointers are initially set to strings containing the superclass name and the runtime fixes them up. In the new ABI, the compiler sets up the linkage directly. --- NSBlocks.m | 5 +++-- class_table.c | 33 +++++++++++++++++++++------------ legacy.c | 2 +- runtime.c | 8 +++----- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/NSBlocks.m b/NSBlocks.m index 32870da..2235069 100644 --- a/NSBlocks.m +++ b/NSBlocks.m @@ -1,5 +1,6 @@ #import "objc/runtime.h" #import "class.h" +#import "loader.h" #import "lock.h" #import "objc/blocks_runtime.h" #import "dtable.h" @@ -27,13 +28,13 @@ static void createNSBlockSubclass(Class superclass, Class newClass, // Set up the new class newClass->isa = metaClass; - newClass->super_class = (Class)superclass->name; + newClass->super_class = superclass; newClass->name = name; newClass->info = objc_class_flag_class; newClass->dtable = uninstalled_dtable; LOCK_RUNTIME_FOR_SCOPE(); - class_table_insert(newClass); + objc_load_class(newClass); } diff --git a/class_table.c b/class_table.c index e829a7e..f49276a 100644 --- a/class_table.c +++ b/class_table.c @@ -155,8 +155,7 @@ PRIVATE BOOL objc_resolve_class(Class cls) // We can only resolve the class if its superclass is resolved. if (cls->super_class) { - Class super = (Class)objc_getClass((char*)cls->super_class); - if (Nil == super) { return NO; } + Class super = cls->super_class; if (!objc_test_class_flag(super, objc_class_flag_resolved)) { @@ -166,6 +165,24 @@ PRIVATE BOOL objc_resolve_class(Class cls) } } } + else + { + struct legacy_gnustep_objc_class *ocls = objc_legacy_class_for_class(cls); + if (ocls != NULL) + { + const char *super_name = (const char*)ocls->super_class; + if (super_name) + { + Class super = (Class)objc_getClass(super_name); + if (super == Nil) + { + return NO; + } + cls->super_class = super; + return objc_resolve_class(cls); + } + } + } // Remove the class from the unresolved class list @@ -203,14 +220,13 @@ PRIVATE BOOL objc_resolve_class(Class cls) else { // Resolve the superclass if it isn't already resolved - Class super = (Class)objc_getClass((char*)cls->super_class); + Class super = cls->super_class; if (!objc_test_class_flag(super, objc_class_flag_resolved)) { objc_resolve_class(super); } superMeta = super->isa; // Set the superclass pointer for the class and the superclass - cls->super_class = super; do { metaMeta = super->isa; @@ -402,13 +418,6 @@ PRIVATE void objc_load_class(struct objc_class *class) return; } - // The compiler initialises the super class pointer to the name of the - // superclass, not the superclass pointer. - // Note: With the new ABI, the class pointer is public. We could, - // therefore, directly reference the superclass from the compiler and make - // the linker resolve it. This should be done in the GCC-incompatible ABI. - const char *superclassName = (char*)class->super_class; - // Work around a bug in some versions of GCC that don't initialize the // class structure correctly. class->subclass_list = NULL; @@ -422,7 +431,7 @@ PRIVATE void objc_load_class(struct objc_class *class) // If this is a root class, make the class into the metaclass's superclass. // This means that all instance methods will be available to the class. - if (NULL == superclassName) + if (NULL == class->super_class) { class->isa->super_class = class; } diff --git a/legacy.c b/legacy.c index 64d3668..6d8c22a 100644 --- a/legacy.c +++ b/legacy.c @@ -108,7 +108,7 @@ PRIVATE Class objc_upgrade_class(struct legacy_gnustep_objc_class *oldClass) { Class cls = calloc(sizeof(struct objc_class), 1); cls->isa = oldClass->isa; - cls->super_class = (struct objc_class*)oldClass->super_class; + // super_class is left nil and we upgrade it later. cls->name = oldClass->name; cls->version = oldClass->version; cls->info = oldClass->info; diff --git a/runtime.c b/runtime.c index ac153ae..0138906 100644 --- a/runtime.c +++ b/runtime.c @@ -199,7 +199,7 @@ BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) methods->methods[0].types = strdup(types); methods->methods[0].imp = imp; - if (objc_test_class_flag(cls, objc_class_flag_resolved)) + if (classHasDtable(cls)) { add_method_list_to_class(cls, methods); } @@ -712,7 +712,7 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt // in objc_resolve_class(). // If the superclass is not yet resolved, then we need to look it up // via the class table. - metaClass->isa = (Class)superclass->isa->isa->name; + metaClass->isa = superclass->isa; metaClass->super_class = superclass->isa; } metaClass->name = strdup(name); @@ -723,9 +723,7 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt // Set up the new class newClass->isa = metaClass; - // Set the superclass pointer to the name. The runtime will fix this when - // the class links are resolved. - newClass->super_class = (Nil == superclass) ? Nil : (Class)(superclass->name); + newClass->super_class = superclass; newClass->name = strdup(name); newClass->info = objc_class_flag_class | objc_class_flag_user_created |