Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -52,10 +52,11 @@ /* A few macros to reduce #ifdefs */ #ifdef OF_OLD_GNU_RUNTIME # define class_getInstanceSize class_get_instance_size # define class_getName class_get_class_name # define class_getSuperclass class_get_super_class +# define sel_registerName sel_get_uid #endif struct pre_ivar { void **memchunks; size_t memchunks_size; @@ -71,10 +72,13 @@ static struct { Class isa; } alloc_failed_exception; static Class autoreleasepool = Nil; + +static SEL cxx_construct = NULL; +static SEL cxx_destruct = NULL; size_t of_pagesize; #ifdef NEED_OBJC_SYNC_INIT extern BOOL objc_sync_init(); @@ -117,10 +121,19 @@ #endif #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) objc_setEnumerationMutationHandler(enumeration_mutation_handler); #endif + + cxx_construct = sel_registerName(".cxx_construct"); + cxx_destruct = sel_registerName(".cxx_destruct"); + + if (cxx_construct == NULL || cxx_destruct == NULL) { + fputs("Runtime error: Failed to register selector " + ".cxx_construct and/or .cxx_destruct!\n", stderr); + abort(); + } #if defined(_WIN32) SYSTEM_INFO si; GetSystemInfo(&si); of_pagesize = si.dwPageSize; @@ -138,10 +151,12 @@ + alloc { OFObject *instance; size_t isize = class_getInstanceSize(self); + Class class; + void (*last)(id, SEL) = NULL; if ((instance = malloc(isize + PRE_IVAR_ALIGN)) == NULL) { alloc_failed_exception.isa = [OFAllocFailedException class]; @throw (OFAllocFailedException*)&alloc_failed_exception; } @@ -158,10 +173,23 @@ #endif instance = (OFObject*)((char*)instance + PRE_IVAR_ALIGN); memset(instance, 0, isize); instance->isa = self; + + for (class = self; class != Nil; class = class_getSuperclass(class)) { + void (*construct)(id, SEL); + + if ([class instancesRespondToSelector: cxx_construct]) { + if ((construct = (void(*)(id, SEL))[class + instanceMethodForSelector: cxx_construct]) != last) + construct(instance, cxx_construct); + + last = construct; + } else + break; + } return instance; } + (Class)class @@ -712,12 +740,28 @@ return self; } - (void)dealloc { - void **iter = PRE_IVAR->memchunks + PRE_IVAR->memchunks_size; + Class class; + void (*last)(id, SEL) = NULL; + void **iter; + + for (class = isa; class != Nil; class = class_getSuperclass(class)) { + void (*destruct)(id, SEL); + + if ([class instancesRespondToSelector: cxx_destruct]) { + if ((destruct = (void(*)(id, SEL))[class + instanceMethodForSelector: cxx_destruct]) != last) + destruct(self, cxx_destruct); + + last = destruct; + } else + break; + } + iter = PRE_IVAR->memchunks + PRE_IVAR->memchunks_size; while (iter-- > PRE_IVAR->memchunks) free(*iter); if (PRE_IVAR->memchunks != NULL) free(PRE_IVAR->memchunks);