diff --git a/associate.m b/associate.m index 15796d1..2289dca 100644 --- a/associate.m +++ b/associate.m @@ -1,6 +1,7 @@ #include #include #include +#include #include "objc/runtime.h" #include "objc/objc-arc.h" #include "nsobject.h" @@ -200,9 +201,11 @@ static Class allocateHiddenClass(Class superclass) // Set up the new class newClass->isa = superclass->isa; - // Set the superclass pointer to the name. The runtime will fix this when - // the class links are resolved. newClass->name = superclass->name; + // Uncomment this for debugging: it makes it easier to track which hidden + // class is which + // static int count; + //asprintf(&newClass->name, "%s%d", superclass->name, count++); newClass->info = objc_class_flag_resolved | objc_class_flag_class | objc_class_flag_user_created | objc_class_flag_new_abi | objc_class_flag_hidden_class | @@ -210,10 +213,9 @@ static Class allocateHiddenClass(Class superclass) newClass->super_class = superclass; newClass->dtable = uninstalled_dtable; newClass->instance_size = superclass->instance_size; - if (objc_test_class_flag(superclass, objc_class_flag_meta)) - { - newClass->info |= objc_class_flag_meta; - } + + newClass->sibling_class = superclass->subclass_list; + superclass->subclass_list = newClass; return newClass; } @@ -221,22 +223,16 @@ static Class allocateHiddenClass(Class superclass) static inline Class initHiddenClassForObject(id obj) { Class hiddenClass = allocateHiddenClass(obj->isa); - if (class_isMetaClass(obj->isa)) + assert(!class_isMetaClass(obj->isa)); + static SEL cxx_destruct; + if (NULL == cxx_destruct) { - obj->isa = hiddenClass; - } - else - { - static SEL cxx_destruct; - if (NULL == cxx_destruct) - { - cxx_destruct = sel_registerName(".cxx_destruct"); - } - const char *types = sizeof(void*) == 4 ? "v8@0:4" : "v16@0:8"; - class_addMethod(hiddenClass, cxx_destruct, - (IMP)deallocHiddenClass, types); - obj->isa = hiddenClass; + cxx_destruct = sel_registerName(".cxx_destruct"); } + const char *types = sizeof(void*) == 4 ? "v8@0:4" : "v16@0:8"; + class_addMethod(hiddenClass, cxx_destruct, + (IMP)deallocHiddenClass, types); + obj->isa = hiddenClass; return hiddenClass; } @@ -421,6 +417,9 @@ static char prototypeKey; id object_clone_np(id object) { if (isSmallObject(object)) { return object; } + // Make sure that the prototype has a hidden class, so that methods added + // to it will appear in the clone. + referenceListForObject(object, YES); id new = class_createInstance(object->isa, 0); Class hiddenClass = initHiddenClassForObject(new); struct reference_list *list = object_getIndexedIvars(hiddenClass);