Index: src/runtime/category.m ================================================================== --- src/runtime/category.m +++ src/runtime/category.m @@ -114,11 +114,11 @@ return (struct objc_category**)objc_hashtable_get(categories, cls->name); } void -objc_free_all_categories(void) +objc_unregister_all_categories(void) { uint32_t i; if (categories == NULL) return; Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -312,11 +312,11 @@ return; if ((superclass = ((struct objc_abi_class*)cls)->superclass) != NULL) { Class super = objc_classname_to_class(superclass, false); - if (super == nil) + if (super == Nil) return; setup_class(super); if (!(super->info & OBJC_CLASS_INFO_SETUP)) @@ -655,11 +655,11 @@ objc_update_dtable(cls); objc_global_mutex_unlock(); - return (IMP)nil; + return NULL; } Class object_getClass(id obj_) { @@ -684,12 +684,12 @@ object_getClassName(id obj) { return object_getClass(obj)->name; } -void -objc_free_class(Class rcls) +static void +unregister_class(Class rcls) { struct objc_abi_class *cls = (struct objc_abi_class*)rcls; if (rcls->subclass_list != NULL) { free(rcls->subclass_list); @@ -704,10 +704,17 @@ if (rcls->superclass != Nil) cls->superclass = rcls->superclass->name; objc_hashtable_set(classes, cls->name, NULL); } + +void +objc_unregister_class(Class cls) +{ + unregister_class(cls); + unregister_class(cls->isa); +} static void free_sparsearray(struct sparsearray *sa, size_t depth) { uint_fast16_t i; @@ -720,11 +727,11 @@ free(sa); } void -objc_free_all_classes(void) +objc_unregister_all_classes(void) { uint_fast32_t i; if (classes == NULL) return; @@ -734,12 +741,11 @@ Class cls = (Class)classes->data[i]->obj; if (cls == Nil || (uintptr_t)cls & 1) continue; - objc_free_class(cls); - objc_free_class(cls->isa); + objc_unregister_class(cls); } } if (empty_dtable != NULL) { objc_sparsearray_free(empty_dtable); Index: src/runtime/init.m ================================================================== --- src/runtime/init.m +++ src/runtime/init.m @@ -35,13 +35,14 @@ void objc_exit(void) { objc_global_mutex_lock(); - objc_free_all_categories(); - objc_free_all_classes(); - objc_free_all_selectors(); + objc_unregister_all_categories(); + objc_unregister_all_classes(); + objc_unregister_all_selectors(); + objc_forget_pending_static_instances(); objc_sparsearray_cleanup(); objc_global_mutex_unlock(); objc_global_mutex_free(); } Index: src/runtime/runtime-private.h ================================================================== --- src/runtime/runtime-private.h +++ src/runtime/runtime-private.h @@ -120,34 +120,35 @@ }; #endif extern void objc_register_all_categories(struct objc_abi_symtab*); extern struct objc_category** objc_categories_for_class(Class); -extern void objc_free_all_categories(void); +extern void objc_unregister_all_categories(void); extern void objc_initialize_class(Class); extern void objc_update_dtable(Class); extern void objc_register_all_classes(struct objc_abi_symtab*); extern Class objc_classname_to_class(const char*, bool); -extern void objc_free_class(Class); -extern void objc_free_all_classes(void); +extern void objc_unregister_class(Class); +extern void objc_unregister_all_classes(void); extern uint32_t objc_hash_string(const char*); extern struct objc_hashtable* objc_hashtable_new(uint32_t); extern void objc_hashtable_set(struct objc_hashtable*, const char*, const void*); extern void* objc_hashtable_get(struct objc_hashtable*, const char*); extern void objc_hashtable_free(struct objc_hashtable *h); extern void objc_register_selector(struct objc_abi_selector*); extern void objc_register_all_selectors(struct objc_abi_symtab*); -extern void objc_free_all_selectors(void); +extern void objc_unregister_all_selectors(void); extern struct objc_sparsearray* objc_sparsearray_new(void); extern void objc_sparsearray_copy(struct objc_sparsearray*, struct objc_sparsearray*); extern void objc_sparsearray_set(struct objc_sparsearray*, uint32_t, const void*); extern void objc_sparsearray_free(struct objc_sparsearray*); extern void objc_sparsearray_cleanup(void); extern void objc_init_static_instances(struct objc_abi_symtab*); +extern void objc_forget_pending_static_instances(void); extern void __objc_exec_class(struct objc_abi_module*); #ifdef OF_HAVE_THREADS extern void objc_global_mutex_lock(void); extern void objc_global_mutex_unlock(void); extern void objc_global_mutex_free(void); Index: src/runtime/runtime.h ================================================================== --- src/runtime/runtime.h +++ src/runtime/runtime.h @@ -14,10 +14,11 @@ * file. */ #ifndef __OBJFW_RUNTIME_H__ #define __OBJFW_RUNTIME_H__ + #include #include #ifndef __has_feature # define __has_feature(x) 0 Index: src/runtime/selector.m ================================================================== --- src/runtime/selector.m +++ src/runtime/selector.m @@ -126,11 +126,11 @@ { return (sel1->uid == sel2->uid); } void -objc_free_all_selectors(void) +objc_unregister_all_selectors(void) { objc_hashtable_free(selectors); objc_sparsearray_free(selector_names); if (free_list != NULL) { Index: src/runtime/static-instances.m ================================================================== --- src/runtime/static-instances.m +++ src/runtime/static-instances.m @@ -89,5 +89,13 @@ static_instances[static_instances_cnt++] = *si; } } } + +void +objc_forget_pending_static_instances() +{ + free(static_instances); + static_instances = NULL; + static_instances_cnt = 0; +} Index: tests/plugin/TestPlugin.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -22,15 +22,11 @@ # import "runtime-private.h" static void __attribute__((destructor)) unload(void) { - Class class = objc_getClass("TestPlugin"); - Class metaclass = object_getClass(class); - - objc_free_class(class); - objc_free_class(metaclass); + objc_unregister_class(objc_getClass("TestPlugin")); } #endif @implementation TestPlugin - (int)test: (int)num