Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -85,13 +85,10 @@ static struct { Class isa; } alloc_failed_exception; -static SEL cxx_construct = NULL; -static SEL cxx_destruct = NULL; - size_t of_pagesize; size_t of_num_cpus; #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) static void @@ -204,11 +201,16 @@ #endif instance = (OFObject*)((char*)instance + PRE_IVAR_ALIGN); memset(instance, 0, instanceSize); - object_setClass(instance, class); + + if (!objc_constructInstance(class, instance)) { + free((char*)instance - PRE_IVAR_ALIGN); + @throw [OFInitializationFailedException + exceptionWithClass: class]; + } if OF_UNLIKELY (extra != NULL) *extra = (char*)instance + instanceSize + extraAlignment; return instance; @@ -240,19 +242,10 @@ #ifdef HAVE_OBJC_ENUMERATIONMUTATION 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; of_num_cpus = si.dwNumberOfProcessors; @@ -509,27 +502,10 @@ return NO; } - init { - Class class; - void (*last)(id, SEL) = NULL; - - for (class = object_getClass(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(self, cxx_construct); - - last = construct; - } else - break; - } - return self; } - (Class)class { @@ -825,27 +801,13 @@ return NO; } - (void)dealloc { - Class class; - void (*last)(id, SEL) = NULL; struct pre_mem *iter; - for (class = object_getClass(self); 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; - } + objc_destructInstance(self); iter = PRE_IVAR->firstMem; while (iter != NULL) { struct pre_mem *next = iter->next; Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -28,10 +28,13 @@ static struct objc_hashtable *classes = NULL; static Class *load_queue = NULL; static size_t load_queue_cnt = 0; static struct objc_sparsearray *empty_dtable = NULL; +static SEL cxx_construct = NULL; +static SEL cxx_destruct = NULL; + static void register_class(struct objc_abi_class *cls) { if (classes == NULL) classes = objc_hashtable_new(2); @@ -291,10 +294,15 @@ void objc_register_all_classes(struct objc_abi_symtab *symtab) { uint_fast32_t i; + if (cxx_construct == NULL) + cxx_construct = sel_registerName(".cxx_construct"); + if (cxx_destruct == NULL) + cxx_destruct = sel_registerName(".cxx_destruct"); + for (i = 0; i < symtab->cls_def_cnt; i++) { struct objc_abi_class *cls = (struct objc_abi_class*)symtab->defs[i]; register_class(cls); @@ -531,10 +539,64 @@ objc_global_mutex_unlock(); return (IMP)nil; } + +id +objc_constructInstance(Class cls, void *bytes) +{ + id obj = (id)bytes; + BOOL (*last)(id, SEL) = NULL; + + if (cls == Nil || bytes == NULL) + return nil; + + object_setClass(obj, cls); + + /* FIXME: Constructors of superclasses should be called first */ + for (; cls != Nil; cls = class_getSuperclass(cls)) { + BOOL (*ctor)(id, SEL); + + if (class_respondsToSelector(cls, cxx_construct)) { + if ((ctor = (BOOL(*)(id, SEL)) + class_getMethodImplementation(cls, + cxx_construct)) != last) + if (!ctor(obj, cxx_construct)) + return nil; + + last = ctor; + } else + break; + } + + return obj; +} + +void* +objc_destructInstance(id obj) +{ + Class cls; + void (*last)(id, SEL) = NULL; + + for (cls = object_getClass(obj); cls != Nil; + cls = class_getSuperclass(cls)) { + void (*dtor)(id, SEL); + + if (class_respondsToSelector(cls, cxx_destruct)) { + if ((dtor = (void(*)(id, SEL)) + class_getMethodImplementation(cls, + cxx_destruct)) != last) + dtor(obj, cxx_destruct); + + last = dtor; + } else + break; + } + + return obj; +} static void free_class(Class rcls) { struct objc_abi_class *cls = (struct objc_abi_class*)rcls; Index: src/runtime/runtime.h ================================================================== --- src/runtime/runtime.h +++ src/runtime/runtime.h @@ -189,10 +189,12 @@ extern void objc_thread_remove(void); extern void objc_exit(void); extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler( objc_uncaught_exception_handler); extern IMP (*objc_forward_handler)(id, SEL); +extern id objc_constructInstance(Class, void*); +extern void* objc_destructInstance(id); extern id objc_autorelease(id); extern void* objc_autoreleasePoolPush(void); extern void objc_autoreleasePoolPop(void*); extern id _objc_rootAutorelease(id);