diff --git a/objc/runtime.h b/objc/runtime.h index 7f23595..5480aed 100644 --- a/objc/runtime.h +++ b/objc/runtime.h @@ -199,6 +199,9 @@ IMP method_setImplementation(Method method, IMP imp); Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes); +OBJC_NONPORTABLE +Class objc_allocateMetaClass(Class superclass, size_t extraBytes); + void objc_disposeClassPair(Class cls); id objc_getClass(const char *name); diff --git a/runtime.c b/runtime.c index e014f82..4ce41bb 100644 --- a/runtime.c +++ b/runtime.c @@ -771,6 +771,22 @@ Class objc_allocateClassPair(Class superclass, const char *name, size_t extraByt return newClass; } +Class objc_allocateMetaClass(Class superclass, size_t extraBytes) +{ + Class metaClass = calloc(1, sizeof(struct objc_class) + extraBytes); + + // Initialize the metaclass + metaClass->class_pointer = superclass->class_pointer->class_pointer; + metaClass->super_class = superclass->class_pointer; + metaClass->name = strdup(superclass->name); + metaClass->info = _CLS_META | _CLS_RUNTIME | _CLS_NEW_ABI; + metaClass->dtable = __objc_uninstalled_dtable; + metaClass->instance_size = sizeof(struct objc_class); + + return metaClass; +} + + void *object_getIndexedIvars(id obj) { if (class_isMetaClass(obj->isa)) diff --git a/sync.m b/sync.m index 07e8890..39d3c65 100644 --- a/sync.m +++ b/sync.m @@ -6,7 +6,6 @@ int snprintf(char *restrict s, size_t n, const char *restrict format, ...); - @interface Fake + (void)dealloc; @end @@ -49,16 +48,27 @@ static inline Class findLockClass(id obj) static inline Class initLockObject(id obj) { - char nameBuffer[40]; - snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++); - Class lockClass = objc_allocateClassPair(obj->isa, nameBuffer, - sizeof(mutex_t)); + Class lockClass; + if (class_isMetaClass(obj->isa)) + { + lockClass = objc_allocateMetaClass(obj, sizeof(mutex_t)); + } + else + { + char nameBuffer[40]; + snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++); + lockClass = objc_allocateClassPair(obj->isa, nameBuffer, + sizeof(mutex_t)); + } const char *types = method_getTypeEncoding(class_getInstanceMethod(obj->isa, @selector(dealloc))); class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, types); - objc_registerClassPair(lockClass); + if (!class_isMetaClass(obj->isa)) + { + objc_registerClassPair(lockClass); + } mutex_t *lock = object_getIndexedIvars(lockClass); INIT_LOCK(*lock); @@ -100,6 +110,7 @@ void objc_sync_enter(id obj) mutex_t *lock = object_getIndexedIvars(lockClass); LOCK(lock); } + void objc_sync_exit(id obj) { Class lockClass = findLockClass(obj);