]> git.saurik.com Git - apple/objc4.git/blobdiff - runtime/objc-runtime-old.mm
objc4-723.tar.gz
[apple/objc4.git] / runtime / objc-runtime-old.mm
index bf5d5c5b0090b6bcfcaf4b7ccbdf4d6776436cc1..7c95bd70feae8ee1841dd7c261b2f28b9f5f7e82 100644 (file)
@@ -175,18 +175,18 @@ static int _objc_defaultClassHandler(const char *clsName);
 static inline NXMapTable *pendingClassRefsMapTable(void);
 static inline NXMapTable *pendingSubclassesMapTable(void);
 static void pendClassInstallation(Class cls, const char *superName);
-static void pendClassReference(Class *ref, const char *className, BOOL isMeta);
+static void pendClassReference(Class *ref, const char *className, bool isMeta);
 static void resolve_references_to_class(Class cls);
 static void resolve_subclasses_of_class(Class cls);
 static void really_connect_class(Class cls, Class supercls);
-static BOOL connect_class(Class cls);
-static void  map_method_descs (struct objc_method_description_list * methods, BOOL copy);
+static bool connect_class(Class cls);
+static void  map_method_descs (struct objc_method_description_list * methods, bool copy);
 static void _objcTweakMethodListPointerForClass(Class cls);
 static inline void _objc_add_category(Class cls, old_category *category, int version);
-static BOOL _objc_add_category_flush_caches(Class cls, old_category *category, int version);
+static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version);
 static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat);
 static void resolve_categories_for_class(Class cls);
-static BOOL _objc_register_category(old_category *cat, int version);
+static bool _objc_register_category(old_category *cat, int version);
 
 
 // Function called when a class is loaded from an image
@@ -243,7 +243,7 @@ void objc_dump_class_hash(void)
     count = 0;
     state = NXInitHashState (table);
     while (NXNextHashState (table, &state, (void **) &data))
-        printf ("class %d: %s\n", ++count, data->getName());
+        printf ("class %d: %s\n", ++count, data->nameForLogging());
 }
 
 
@@ -264,10 +264,7 @@ void _objc_init_class_hash(void)
     // about 520 classes.  Larger apps (like IB or WOB) have more like
     // 800 classes.  Some customers have massive quantities of classes.
     // Foundation-only programs aren't likely to notice the ~6K loss.
-    class_hash = NXCreateHashTableFromZone (classHashPrototype,
-                                            16,
-                                            nil,
-                                            _objc_internal_zone ());
+    class_hash = NXCreateHashTable(classHashPrototype, 16, nil);
     _objc_debug_class_hash = class_hash;
 }
 
@@ -281,16 +278,12 @@ int objc_getClassList(Class *buffer, int bufferLen)
     Class cls;
     int cnt, num;
 
-    mutex_lock(&classLock);
-    if (!class_hash) {
-        mutex_unlock(&classLock);
-        return 0;
-    }
+    mutex_locker_t lock(classLock);
+    if (!class_hash) return 0;
+
     num = NXCountHashTable(class_hash);
-    if (nil == buffer) {
-        mutex_unlock(&classLock);
-        return num;
-    }
+    if (nil == buffer) return num;
+
     cnt = 0;
     state = NXInitHashState(class_hash);
     while (cnt < bufferLen  &&  
@@ -298,7 +291,7 @@ int objc_getClassList(Class *buffer, int bufferLen)
     {
         buffer[cnt++] = cls;
     }
-    mutex_unlock(&classLock);
+
     return num;
 }
 
@@ -319,7 +312,7 @@ objc_copyClassList(unsigned int *outCount)
     Class *result;
     unsigned int count;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
     result = nil;
     count = class_hash ? NXCountHashTable(class_hash) : 0;
 
@@ -333,7 +326,6 @@ objc_copyClassList(unsigned int *outCount)
         }
         result[count] = nil;
     }
-    mutex_unlock(&classLock);
         
     if (outCount) *outCount = count;
     return result;
@@ -354,11 +346,10 @@ objc_copyProtocolList(unsigned int *outCount)
     NXMapState state;
     Protocol **result;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     count = NXCountMapTable(protocol_map);
     if (count == 0) {
-        mutex_unlock(&classLock);
         if (outCount) *outCount = 0;
         return nil;
     }
@@ -376,8 +367,6 @@ objc_copyProtocolList(unsigned int *outCount)
     result[i++] = nil;
     assert(i == count+1);
 
-    mutex_unlock(&classLock);
-
     if (outCount) *outCount = count;
     return result;
 }
@@ -408,7 +397,7 @@ static uintptr_t classHash(void *info, Class data)
         return 0;
 
     // Call through to real hash function
-    return _objc_strhash (data->getName());
+    return _objc_strhash (data->mangledName());
 }
 
 /***********************************************************************
@@ -419,7 +408,7 @@ static uintptr_t classHash(void *info, Class data)
 static int classIsEqual(void *info, Class name, Class cls)
 {
     // Standard string comparison
-    return strcmp(name->getName(), cls->getName()) == 0;
+    return strcmp(name->mangledName(), cls->mangledName()) == 0;
 }
 
 
@@ -443,11 +432,9 @@ static void setOriginalClassForFutureClass(Class futureClass,
 {
     if (!future_class_to_original_class_map) {
         future_class_to_original_class_map =
-            NXCreateMapTableFromZone (NXPtrValueMapPrototype, FUTURE_COUNT, 
-                                      _objc_internal_zone ());
+            NXCreateMapTable(NXPtrValueMapPrototype, FUTURE_COUNT);
         original_class_to_future_class_map =
-            NXCreateMapTableFromZone (NXPtrValueMapPrototype, FUTURE_COUNT, 
-                                      _objc_internal_zone ());
+            NXCreateMapTable(NXPtrValueMapPrototype, FUTURE_COUNT);
     }
 
     NXMapInsert (future_class_to_original_class_map,
@@ -493,11 +480,10 @@ static void makeFutureClass(Class cls, const char *name)
     // CF requests about 20 future classes, plus HIToolbox has one.
     if (!future_class_hash) {
         future_class_hash = 
-            NXCreateHashTableFromZone(classHashPrototype, FUTURE_COUNT, 
-                                      nil, _objc_internal_zone());
+            NXCreateHashTable(classHashPrototype, FUTURE_COUNT, nil);
     }
 
-    cls->name = _strdup_internal(name);
+    cls->name = strdup(name);
     NXHashInsert(future_class_hash, cls);
 
     if (PrintFuture) {
@@ -533,38 +519,42 @@ Class _objc_allocateFutureClass(const char *name)
 
 
 /***********************************************************************
-* objc_setFutureClass.  
-* Like objc_getFutureClass, but uses the provided memory block. 
-* If the class already exists, a posing-like substitution is performed.
-* Not thread safe.
+* objc_getFutureClass.  Return the id of the named class.
+* If the class does not exist, return an uninitialized class 
+* structure that will be used for the class when and if it 
+* does get loaded.
+* Not thread safe. 
 **********************************************************************/
-void objc_setFutureClass(Class cls, const char *name)
+Class objc_getFutureClass(const char *name)
 {
-    Class oldcls;
-    Class newcls = cls;  // Not a real class!
-
-    if ((oldcls = look_up_class(name, NO/*unconnected*/, NO/*classhandler*/))) {
-        setOriginalClassForFutureClass(newcls, oldcls);
-        // fixme hack
-        memcpy(newcls, oldcls, sizeof(struct objc_class));
-        newcls->info &= ~CLS_EXT;
+    Class cls;
 
-        mutex_lock(&classLock);
-        NXHashRemove(class_hash, oldcls);
-        objc_removeRegisteredClass(oldcls);
-        change_class_references(newcls, oldcls, nil, YES);
-        NXHashInsert(class_hash, newcls);
-        objc_addRegisteredClass(newcls);
-        mutex_unlock(&classLock);
-    } else {
-        makeFutureClass(newcls, name);
+    // YES unconnected, NO class handler
+    // (unconnected is OK because it will someday be the real class)
+    cls = look_up_class(name, YES, NO);
+    if (cls) {
+        if (PrintFuture) {
+            _objc_inform("FUTURE: found %p already in use for %s", 
+                         (void*)cls, name);
+        }
+        return cls;
     }
+    
+    // No class or future class with that name yet. Make one.
+    // fixme not thread-safe with respect to 
+    // simultaneous library load or getFutureClass.
+    return _objc_allocateFutureClass(name);
 }
 
 
 BOOL _class_isFutureClass(Class cls)
 {
-    return cls  &&  future_class_hash  &&  NXHashGet(future_class_hash, cls);
+    return cls  &&  cls->isFuture();
+}
+
+bool objc_class::isFuture() 
+{
+    return future_class_hash  &&  NXHashGet(future_class_hash, this);
 }
 
 
@@ -611,12 +601,9 @@ void _objc_setClassLoader(BOOL (*newClassLoader)(const char *))
 **********************************************************************/
 Protocol *objc_getProtocol(const char *name)
 {
-    Protocol *result;
+    mutex_locker_t lock(classLock);
     if (!protocol_map) return nil;
-    mutex_lock(&classLock);
-    result = (Protocol *)NXMapGet(protocol_map, name);
-    mutex_unlock(&classLock);
-    return result;
+    return (Protocol *)NXMapGet(protocol_map, name);
 }
 
 
@@ -631,9 +618,10 @@ Protocol *objc_getProtocol(const char *name)
 * 3. classLoader callback
 * 4. classHandler callback (optional)
 **********************************************************************/
-Class look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
+Class look_up_class(const char *aClassName, bool includeUnconnected, 
+                    bool includeClassHandler)
 {
-    BOOL includeClassLoader = YES; // class loader cannot be skipped
+    bool includeClassLoader = YES; // class loader cannot be skipped
     Class result = nil;
     struct objc_class query;
 
@@ -643,16 +631,14 @@ Class look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includ
 
     if (!result  &&  class_hash) {
         // Check ordinary classes
-        mutex_lock (&classLock);
+        mutex_locker_t lock(classLock);
         result = (Class)NXHashGet(class_hash, &query);
-        mutex_unlock (&classLock);
     }
 
     if (!result  &&  includeUnconnected  &&  unconnected_class_hash) {
         // Check not-yet-connected classes
-        mutex_lock(&classLock);
+        mutex_locker_t lock(classLock);
         result = (Class)NXHashGet(unconnected_class_hash, &query);
-        mutex_unlock(&classLock);
     }
 
     if (!result  &&  includeClassLoader  &&  _objc_classLoader) {
@@ -686,11 +672,8 @@ Class look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includ
 **********************************************************************/
 bool objc_class::isConnected()
 {
-    bool result;
-    mutex_lock(&classLock);
-    result = NXHashMember(class_hash, this);
-    mutex_unlock(&classLock);
-    return result;
+    mutex_locker_t lock(classLock);
+    return NXHashMember(class_hash, this);
 }
 
 
@@ -702,9 +685,7 @@ static inline NXMapTable *pendingClassRefsMapTable(void)
 {
     // Allocate table if needed
     if (!pendingClassRefsMap) {
-        pendingClassRefsMap = 
-            NXCreateMapTableFromZone(NXStrValueMapPrototype, 
-                                     10, _objc_internal_zone ());
+        pendingClassRefsMap = NXCreateMapTable(NXStrValueMapPrototype, 10);
     }
     
     // Return table pointer
@@ -720,9 +701,7 @@ static inline NXMapTable *pendingSubclassesMapTable(void)
 {
     // Allocate table if needed
     if (!pendingSubclassesMap) {
-        pendingSubclassesMap = 
-            NXCreateMapTableFromZone(NXStrValueMapPrototype, 
-                                     10, _objc_internal_zone ());
+        pendingSubclassesMap = NXCreateMapTable(NXStrValueMapPrototype, 10);
     }
     
     // Return table pointer
@@ -752,7 +731,7 @@ static void pendClassInstallation(Class cls, const char *superName)
     }
     
     // Create entry referring to this class
-    pending = (PendingSubclass *)_malloc_internal(sizeof(PendingSubclass));
+    pending = (PendingSubclass *)malloc(sizeof(PendingSubclass));
     pending->subclass = cls;
     
     // Link new entry into head of list of entries for this class
@@ -767,7 +746,7 @@ static void pendClassInstallation(Class cls, const char *superName)
 * pendClassReference
 * Fix up a class ref when the class with the given name becomes connected.
 **********************************************************************/
-static void pendClassReference(Class *ref, const char *className, BOOL isMeta)
+static void pendClassReference(Class *ref, const char *className, bool isMeta)
 {
     NXMapTable *table;
     PendingClassRef *pending;
@@ -776,7 +755,7 @@ static void pendClassReference(Class *ref, const char *className, BOOL isMeta)
     table = pendingClassRefsMapTable ();
     
     // Create entry containing the class reference
-    pending = (PendingClassRef *)_malloc_internal(sizeof(PendingClassRef));
+    pending = (PendingClassRef *)malloc(sizeof(PendingClassRef));
     pending->ref = ref;
     if (isMeta) {
         pending->ref = (Class *)((uintptr_t)pending->ref | 1);
@@ -817,12 +796,12 @@ static void resolve_references_to_class(Class cls)
     while (pending) {
         PendingClassRef *next = pending->next;
         if (pending->ref) {
-            BOOL isMeta = ((uintptr_t)pending->ref & 1) ? YES : NO;
+            bool isMeta = (uintptr_t)pending->ref & 1;
             Class *ref = 
                 (Class *)((uintptr_t)pending->ref & ~(uintptr_t)1);
             *ref = isMeta ? cls->ISA() : cls;
         }
-        _free_internal(pending);
+        free(pending);
         pending = next;
     }
 
@@ -861,7 +840,7 @@ static void resolve_subclasses_of_class(Class cls)
     while (pending) {
         PendingSubclass *next = pending->next;
         if (pending->subclass) connect_class(pending->subclass);
-        _free_internal(pending);
+        free(pending);
         pending = next;
     }
 }
@@ -882,88 +861,26 @@ static void really_connect_class(Class cls,
     // Connect superclass pointers.
     set_superclass(cls, supercls, YES);
 
-    // Update GC layouts
-    // For paranoia, this is a conservative update: 
-    // only non-strong -> strong and weak -> strong are corrected.
-    if (UseGC  &&  supercls  &&  
-        (cls->info & CLS_EXT)  &&  (supercls->info & CLS_EXT)) 
+    // Done!
+    cls->info |= CLS_CONNECTED;
+
     {
-        BOOL layoutChanged;
-        layout_bitmap ivarBitmap = 
-            layout_bitmap_create(cls->ivar_layout, 
-                                 cls->instance_size, 
-                                 cls->instance_size, NO);
-
-        layout_bitmap superBitmap = 
-            layout_bitmap_create(supercls->ivar_layout, 
-                                 supercls->instance_size, 
-                                 supercls->instance_size, NO);
-
-        // non-strong -> strong: bits set in super should be set in sub
-        layoutChanged = layout_bitmap_or(ivarBitmap, superBitmap, cls->name);
-        layout_bitmap_free(superBitmap);
+        mutex_locker_t lock(classLock);
         
-        if (layoutChanged) {
-            layout_bitmap weakBitmap = {};
-            BOOL weakLayoutChanged = NO;
-
-            if (cls->ext  &&  cls->ext->weak_ivar_layout) {
-                // weak -> strong: strong bits should be cleared in weak layout
-                // This is a subset of non-strong -> strong
-                weakBitmap = 
-                    layout_bitmap_create(cls->ext->weak_ivar_layout, 
-                                         cls->instance_size, 
-                                         cls->instance_size, YES);
-
-                weakLayoutChanged = 
-                    layout_bitmap_clear(weakBitmap, ivarBitmap, cls->name);
-            } else {
-                // no existing weak ivars, so no weak -> strong changes
-            }
-
-            // Rebuild layout strings. 
-            if (PrintIvars) {
-                _objc_inform("IVARS: gc layout changed "
-                             "for class %s (super %s)",
-                             cls->name, supercls->name);
-                if (weakLayoutChanged) {
-                    _objc_inform("IVARS: gc weak layout changed "
-                                 "for class %s (super %s)",
-                                 cls->name, supercls->name);
-                }
-            }
-            cls->ivar_layout = layout_string_create(ivarBitmap);
-            if (weakLayoutChanged) {
-                cls->ext->weak_ivar_layout = layout_string_create(weakBitmap);
-            }
-
-            layout_bitmap_free(weakBitmap);
+        // Update hash tables. 
+        NXHashRemove(unconnected_class_hash, cls);
+        oldCls = (Class)NXHashInsert(class_hash, cls);
+        
+        // Delete unconnected_class_hash if it is now empty.
+        if (NXCountHashTable(unconnected_class_hash) == 0) {
+            NXFreeHashTable(unconnected_class_hash);
+            unconnected_class_hash = nil;
         }
         
-        layout_bitmap_free(ivarBitmap);
-    }
-
-    // Done!
-    cls->info |= CLS_CONNECTED;
-
-    mutex_lock(&classLock);
-
-    // Update hash tables. 
-    NXHashRemove(unconnected_class_hash, cls);
-    oldCls = (Class)NXHashInsert(class_hash, cls);
-    objc_addRegisteredClass(cls);
-
-    // Delete unconnected_class_hash if it is now empty.
-    if (NXCountHashTable(unconnected_class_hash) == 0) {
-        NXFreeHashTable(unconnected_class_hash);
-        unconnected_class_hash = nil;
-    }
-
-    // No duplicate classes allowed. 
-    // Duplicates should have been rejected by _objc_read_classes_from_image.
-    assert(!oldCls);
-
-    mutex_unlock(&classLock);
+        // No duplicate classes allowed. 
+        // Duplicates should have been rejected by _objc_read_classes_from_image
+        assert(!oldCls);
+    }        
  
     // Fix up pended class refs to this class, if any
     resolve_references_to_class(cls);
@@ -971,16 +888,6 @@ static void really_connect_class(Class cls,
     // Connect newly-connectable subclasses
     resolve_subclasses_of_class(cls);
 
-    // GC debugging: make sure all classes with -dealloc also have -finalize
-    if (DebugFinalizers) {
-        extern IMP findIMPInClass(Class cls, SEL sel);
-        if (findIMPInClass(cls, sel_getUid("dealloc"))  &&  
-            ! findIMPInClass(cls, sel_getUid("finalize")))
-        {
-            _objc_inform("GC: class '%s' implements -dealloc but not -finalize", cls->name);
-        }
-    }
-
     // Debugging: if this class has ivars, make sure this class's ivars don't 
     // overlap with its super's. This catches some broken fragile base classes.
     // Do not use super->instance_size vs. self->ivar[0] to check this. 
@@ -1023,7 +930,7 @@ static void really_connect_class(Class cls,
 * Returns FALSE if cls could not be connected for some reason 
 *   (missing superclass or still-unconnected superclass)
 **********************************************************************/
-static BOOL connect_class(Class cls)
+static bool connect_class(Class cls)
 {
     if (cls->isConnected()) {
         // This class is already connected to its superclass.
@@ -1095,18 +1002,17 @@ static BOOL connect_class(Class cls)
 *   installation. 
 * Returns YES if some method caches now need to be flushed.
 **********************************************************************/
-static BOOL _objc_read_categories_from_image (header_info *  hi)
+static bool _objc_read_categories_from_image (header_info *  hi)
 {
     Module             mods;
     size_t     midx;
-    BOOL needFlush = NO;
+    bool needFlush = NO;
 
-    if (_objcHeaderIsReplacement(hi)) {
+    if (hi->info()->isReplacement()) {
         // Ignore any categories in this image
         return NO;
     }
 
-
     // Major loop - process all modules in the header
     mods = hi->mod_ptr;
 
@@ -1154,7 +1060,7 @@ static void _objc_read_classes_from_image(header_info *hi)
     Module             mods;
     int                isBundle = headerIsBundle(hi);
 
-    if (_objcHeaderIsReplacement(hi)) {
+    if (hi->info()->isReplacement()) {
         // Ignore any classes in this image
         return;
     }
@@ -1163,11 +1069,12 @@ static void _objc_read_classes_from_image(header_info *hi)
     // If other Objective-C libraries are found, immediately resize 
     // class_hash, assuming that Foundation and AppKit are about 
     // to add lots of classes.
-    mutex_lock(&classLock);
-    if (hi->mhdr != libobjc_header && _NXHashCapacity(class_hash) < 1024) {
-        _NXHashRehashToCapacity(class_hash, 1024);
+    {
+        mutex_locker_t lock(classLock);
+        if (hi->mhdr() != libobjc_header && _NXHashCapacity(class_hash) < 1024) {
+            _NXHashRehashToCapacity(class_hash, 1024);
+        }
     }
-    mutex_unlock(&classLock);
 
     // Major loop - process all modules in the image
     mods = hi->mod_ptr;
@@ -1181,7 +1088,7 @@ static void _objc_read_classes_from_image(header_info *hi)
         for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
         {
             Class newCls, oldCls;
-            BOOL rejected;
+            bool rejected;
 
             // Locate the class description pointer
             newCls = (Class)mods[midx].symtab->defs[index];
@@ -1218,48 +1125,47 @@ static void _objc_read_classes_from_image(header_info *hi)
             if (_class_hasLoadMethod(newCls)) {
                 newCls->ISA()->info |= CLS_HAS_LOAD_METHOD;
             }
-            
-            // Install into unconnected_class_hash.
-            mutex_lock(&classLock);
 
-            if (future_class_hash) {
-                Class futureCls = (Class)
-                    NXHashRemove(future_class_hash, newCls);
-                if (futureCls) {
-                    // Another class structure for this class was already 
-                    // prepared by objc_getFutureClass(). Use it instead.
-                    _free_internal((char *)futureCls->name);
-                    memcpy(futureCls, newCls, sizeof(objc_class));
-                    setOriginalClassForFutureClass(futureCls, newCls);
-                    newCls = futureCls;
-
-                    if (NXCountHashTable(future_class_hash) == 0) {
-                        NXFreeHashTable(future_class_hash);
-                        future_class_hash = nil;
+            // Install into unconnected_class_hash.
+            {
+                mutex_locker_t lock(classLock);
+
+                if (future_class_hash) {
+                    Class futureCls = (Class)
+                        NXHashRemove(future_class_hash, newCls);
+                    if (futureCls) {
+                        // Another class structure for this class was already 
+                        // prepared by objc_getFutureClass(). Use it instead.
+                        free((char *)futureCls->name);
+                        memcpy(futureCls, newCls, sizeof(objc_class));
+                        setOriginalClassForFutureClass(futureCls, newCls);
+                        newCls = futureCls;
+                        
+                        if (NXCountHashTable(future_class_hash) == 0) {
+                            NXFreeHashTable(future_class_hash);
+                            future_class_hash = nil;
+                        }
                     }
                 }
+                
+                if (!unconnected_class_hash) {
+                    unconnected_class_hash = 
+                        NXCreateHashTable(classHashPrototype, 128, nil);
+                }
+                
+                if ((oldCls = (Class)NXHashGet(class_hash, newCls))  ||  
+                    (oldCls = (Class)NXHashGet(unconnected_class_hash, newCls)))
+                {
+                    // Another class with this name exists. Complain and reject.
+                    inform_duplicate(newCls->name, oldCls, newCls);
+                    rejected = YES;
+                }
+                else {
+                    NXHashInsert(unconnected_class_hash, newCls); 
+                    rejected = NO;
+                }
             }
 
-            if (!unconnected_class_hash) {
-                unconnected_class_hash = 
-                    NXCreateHashTableFromZone(classHashPrototype, 128, 
-                                              nil, _objc_internal_zone());
-            }
-
-            if ((oldCls = (Class)NXHashGet(class_hash, newCls))  ||  
-                (oldCls = (Class)NXHashGet(unconnected_class_hash, newCls)))
-            {
-                // Another class with this name exists. Complain and reject.
-                inform_duplicate(newCls->name, oldCls, newCls);
-                rejected = YES;
-            }
-            else {
-                NXHashInsert(unconnected_class_hash, newCls); 
-                rejected = NO;
-            }
-
-            mutex_unlock(&classLock);
-
             if (!rejected) {
                 // Attach pended categories for this class, if any
                 resolve_categories_for_class(newCls);
@@ -1279,7 +1185,7 @@ static void _objc_connect_classes_from_image(header_info *hi)
     unsigned int index;
     unsigned int midx;
     Module mods;
-    BOOL replacement = _objcHeaderIsReplacement(hi);
+    bool replacement = hi->info()->isReplacement();
 
     // Major loop - process all modules in the image
     mods = hi->mod_ptr;
@@ -1294,7 +1200,7 @@ static void _objc_connect_classes_from_image(header_info *hi)
         {
             Class cls = (Class)mods[midx].symtab->defs[index];
             if (! replacement) {
-                BOOL connected;
+                bool connected;
                 Class futureCls = getFutureClassForOriginalClass(cls);
                 if (futureCls) {
                     // objc_getFutureClass() requested a different class 
@@ -1335,7 +1241,7 @@ static void _objc_connect_classes_from_image(header_info *hi)
 * not yet exist, the reference is added to a list of pending references
 * to be fixed up at a later date.
 **********************************************************************/
-static void fix_class_ref(Class *ref, const char *name, BOOL isMeta)
+static void fix_class_ref(Class *ref, const char *name, bool isMeta)
 {
     Class cls;
 
@@ -1425,7 +1331,7 @@ static void _objc_remove_pending_class_refs_in_image(header_info *hi)
 * can still be used after the bundle's data segment is unmapped.
 * Returns YES if dst was written to, NO if it was unchanged.
 **********************************************************************/
-static inline void map_selrefs(SEL *sels, size_t count, BOOL copy)
+static inline void map_selrefs(SEL *sels, size_t count, bool copy)
 {
     size_t index;
 
@@ -1459,7 +1365,7 @@ static inline void map_selrefs(SEL *sels, size_t count, BOOL copy)
 * for registering selectors from unloadable bundles, so the selector 
 * can still be used after the bundle's data segment is unmapped.
 **********************************************************************/
-static void  map_method_descs (struct objc_method_description_list * methods, BOOL copy)
+static void  map_method_descs (struct objc_method_description_list * methods, bool copy)
 {
     int index;
 
@@ -1528,8 +1434,8 @@ lookup_method(struct objc_method_description_list *mlist, SEL aSel)
 **********************************************************************/
 struct objc_method_description *
 lookup_protocol_method(old_protocol *proto, SEL aSel, 
-                       BOOL isRequiredMethod, BOOL isInstanceMethod, 
-                       BOOL recursive)
+                       bool isRequiredMethod, bool isInstanceMethod, 
+                       bool recursive)
 {
     struct objc_method_description *m = nil;
     old_protocol_ext *ext;
@@ -1648,8 +1554,9 @@ protocol_copyMethodDescriptionList(Protocol *p,
 }
 
 
-objc_property_t protocol_getProperty(Protocol *p, const char *name, 
-                              BOOL isRequiredProperty, BOOL isInstanceProperty)
+objc_property_t 
+protocol_getProperty(Protocol *p, const char *name, 
+                     BOOL isRequiredProperty, BOOL isInstanceProperty)
 {
     old_protocol *proto = oldprotocol(p);
     old_protocol_ext *ext;
@@ -1657,14 +1564,18 @@ objc_property_t protocol_getProperty(Protocol *p, const char *name,
 
     if (!proto  ||  !name) return nil;
     
-    if (!isRequiredProperty  ||  !isInstanceProperty) {
-        // Only required instance properties are currently supported
+    if (!isRequiredProperty) {
+        // Only required properties are currently supported
         return nil;
     }
 
     if ((ext = ext_for_protocol(proto))) {
         old_property_list *plist;
-        if ((plist = ext->instance_properties)) {
+        if (isInstanceProperty) plist = ext->instance_properties;
+        else if (ext->hasClassPropertiesField()) plist = ext->class_properties;
+        else plist = nil;
+
+        if (plist) {
             uint32_t i;
             for (i = 0; i < plist->count; i++) {
                 old_property *prop = property_list_nth(plist, i);
@@ -1689,24 +1600,35 @@ objc_property_t protocol_getProperty(Protocol *p, const char *name,
 }
 
 
-objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *outCount)
+objc_property_t *
+protocol_copyPropertyList2(Protocol *p, unsigned int *outCount,
+                           BOOL isRequiredProperty, BOOL isInstanceProperty)
 {
     old_property **result = nil;
     old_protocol_ext *ext;
     old_property_list *plist;
     
     old_protocol *proto = oldprotocol(p);
-    if (! (ext = ext_for_protocol(proto))) {
+    if (! (ext = ext_for_protocol(proto))  ||  !isRequiredProperty) {
+        // Only required properties are currently supported.
         if (outCount) *outCount = 0;
         return nil;
     }
 
-    plist = ext->instance_properties;
+    if (isInstanceProperty) plist = ext->instance_properties;
+    else if (ext->hasClassPropertiesField()) plist = ext->class_properties;
+    else plist = nil;
+
     result = copyPropertyList(plist, outCount);
     
     return (objc_property_t *)result;
 }
 
+objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *outCount)
+{
+    return protocol_copyPropertyList2(p, outCount, YES, YES);
+}
+
 
 /***********************************************************************
 * protocol_copyProtocolList
@@ -1862,29 +1784,25 @@ Protocol *
 objc_allocateProtocol(const char *name)
 {
     Class cls = objc_getClass("__IncompleteProtocol");
+    assert(cls);
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
-    if (NXMapGet(protocol_map, name)) {
-        mutex_unlock(&classLock);
-        return nil;
-    }
+    if (NXMapGet(protocol_map, name)) return nil;
 
     old_protocol *result = (old_protocol *)
-        _calloc_internal(1, sizeof(old_protocol) 
+        calloc(1, sizeof(old_protocol) 
                          + sizeof(old_protocol_ext));
     old_protocol_ext *ext = (old_protocol_ext *)(result+1);
     
     result->isa = cls;
-    result->protocol_name = _strdup_internal(name);
+    result->protocol_name = strdup(name);
     ext->size = sizeof(old_protocol_ext);
 
     // fixme reserve name without installing
 
     NXMapInsert(protocol_ext_map, result, result+1);
 
-    mutex_unlock(&classLock);
-
     return (Protocol *)result;
 }
 
@@ -1902,26 +1820,22 @@ void objc_registerProtocol(Protocol *proto_gen)
     Class oldcls = objc_getClass("__IncompleteProtocol");
     Class cls = objc_getClass("Protocol");
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     if (proto->isa == cls) {
         _objc_inform("objc_registerProtocol: protocol '%s' was already "
                      "registered!", proto->protocol_name);
-        mutex_unlock(&classLock);
         return;
     }
     if (proto->isa != oldcls) {
         _objc_inform("objc_registerProtocol: protocol '%s' was not allocated "
                      "with objc_allocateProtocol!", proto->protocol_name);
-        mutex_unlock(&classLock);
         return;
     }
 
     proto->isa = cls;
 
     NXMapKeyCopyingInsert(protocol_map, proto->protocol_name, proto);
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -1943,18 +1857,16 @@ protocol_addProtocol(Protocol *proto_gen, Protocol *addition_gen)
     if (!proto_gen) return;
     if (!addition_gen) return;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     if (proto->isa != cls) {
         _objc_inform("protocol_addProtocol: modified protocol '%s' is not "
                      "under construction!", proto->protocol_name);
-        mutex_unlock(&classLock);
         return;
     }
     if (addition->isa == cls) {
         _objc_inform("protocol_addProtocol: added protocol '%s' is still "
                      "under construction!", addition->protocol_name);
-        mutex_unlock(&classLock);
         return;        
     }
     
@@ -1963,16 +1875,14 @@ protocol_addProtocol(Protocol *proto_gen, Protocol *addition_gen)
         size_t size = sizeof(old_protocol_list) 
             + protolist->count * sizeof(protolist->list[0]);
         protolist = (old_protocol_list *)
-            _realloc_internal(protolist, size);
+            realloc(protolist, size);
     } else {
         protolist = (old_protocol_list *)
-            _calloc_internal(1, sizeof(old_protocol_list));
+            calloc(1, sizeof(old_protocol_list));
     }
 
     protolist->list[protolist->count++] = addition;
     proto->protocol_list = protolist;
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -1986,17 +1896,17 @@ _protocol_addMethod(struct objc_method_description_list **list, SEL name, const
 {
     if (!*list) {
         *list = (struct objc_method_description_list *)
-            _calloc_internal(sizeof(struct objc_method_description_list), 1);
+            calloc(sizeof(struct objc_method_description_list), 1);
     } else {
         size_t size = sizeof(struct objc_method_description_list) 
             + (*list)->count * sizeof(struct objc_method_description);
         *list = (struct objc_method_description_list *)
-            _realloc_internal(*list, size);
+            realloc(*list, size);
     }
 
     struct objc_method_description *desc = &(*list)->list[(*list)->count++];
     desc->name = name;
-    desc->types = _strdup_internal(types ?: "");
+    desc->types = strdup(types ?: "");
 }
 
 void 
@@ -2009,12 +1919,11 @@ protocol_addMethodDescription(Protocol *proto_gen, SEL name, const char *types,
 
     if (!proto_gen) return;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     if (proto->isa != cls) {
         _objc_inform("protocol_addMethodDescription: protocol '%s' is not "
                      "under construction!", proto->protocol_name);
-        mutex_unlock(&classLock);
         return;
     }
 
@@ -2029,8 +1938,6 @@ protocol_addMethodDescription(Protocol *proto_gen, SEL name, const char *types,
         old_protocol_ext *ext = (old_protocol_ext *)(proto+1);
         _protocol_addMethod(&ext->optional_class_methods, name, types);
     }
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -2046,16 +1953,16 @@ _protocol_addProperty(old_property_list **plist, const char *name,
 {
     if (!*plist) {
         *plist = (old_property_list *)
-            _calloc_internal(sizeof(old_property_list), 1);
+            calloc(sizeof(old_property_list), 1);
         (*plist)->entsize = sizeof(old_property);
     } else {
         *plist = (old_property_list *)
-            _realloc_internal(*plist, sizeof(old_property_list) 
+            realloc(*plist, sizeof(old_property_list) 
                               + (*plist)->count * (*plist)->entsize);
     }
 
     old_property *prop = property_list_nth(*plist, (*plist)->count++);
-    prop->name = _strdup_internal(name);
+    prop->name = strdup(name);
     prop->attributes = copyPropertyAttributeString(attrs, count);
 }
 
@@ -2072,12 +1979,11 @@ protocol_addProperty(Protocol *proto_gen, const char *name,
     if (!proto) return;
     if (!name) return;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
     
     if (proto->isa != cls) {
         _objc_inform("protocol_addProperty: protocol '%s' is not "
                      "under construction!", proto->protocol_name);
-        mutex_unlock(&classLock);
         return;
     }
 
@@ -2086,15 +1992,15 @@ protocol_addProperty(Protocol *proto_gen, const char *name,
     if (isRequiredProperty  &&  isInstanceProperty) {
         _protocol_addProperty(&ext->instance_properties, name, attrs, count);
     }
-    //else if (isRequiredProperty  &&  !isInstanceProperty) {
-    //    _protocol_addProperty(&ext->class_properties, name, attrs, count);
-    //} else if (!isRequiredProperty  &&  isInstanceProperty) {
+    else if (isRequiredProperty  &&  !isInstanceProperty) {
+        _protocol_addProperty(&ext->class_properties, name, attrs, count);
+    }
+    // else if (!isRequiredProperty  &&  isInstanceProperty) {
     //    _protocol_addProperty(&ext->optional_instance_properties, name, attrs, count);
-    //} else /*  !isRequiredProperty  &&  !isInstanceProperty) */ {
+    //} 
+    // else /*  !isRequiredProperty  &&  !isInstanceProperty) */ {
     //    _protocol_addProperty(&ext->optional_class_properties, name, attrs, count);
     //}
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -2103,7 +2009,7 @@ protocol_addProperty(Protocol *proto_gen, const char *name,
 * specified image, selectorize the method names and add to the protocol hash.
 **********************************************************************/
 
-static BOOL versionIsExt(uintptr_t version, const char *names, size_t size)
+static bool versionIsExt(uintptr_t version, const char *names, size_t size)
 {
     // CodeWarrior used isa field for string "Protocol" 
     //   from section __OBJC,__class_names.  rdar://4951638
@@ -2111,7 +2017,7 @@ static BOOL versionIsExt(uintptr_t version, const char *names, size_t size)
     //   the only version number used on Mac OS X was 2.
     // gcc (10.5 and later) uses isa field for ext pointer
 
-    if (version < PAGE_SIZE) {
+    if (version < 4096 /* not PAGE_SIZE */) {
         return NO;
     }
 
@@ -2123,7 +2029,7 @@ static BOOL versionIsExt(uintptr_t version, const char *names, size_t size)
 }
 
 static void fix_protocol(old_protocol *proto, Class protocolClass, 
-                         BOOL isBundle, const char *names, size_t names_size)
+                         bool isBundle, const char *names, size_t names_size)
 {
     uintptr_t version;
     if (!proto) return;
@@ -2173,18 +2079,16 @@ static void _objc_fixup_protocol_objects_for_image (header_info * hi)
     const char *names;
     size_t names_size;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     // Allocate the protocol registry if necessary.
     if (!protocol_map) {
         protocol_map = 
-            NXCreateMapTableFromZone(NXStrValueMapPrototype, 32, 
-                                     _objc_internal_zone());
+            NXCreateMapTable(NXStrValueMapPrototype, 32);
     }
     if (!protocol_ext_map) {
         protocol_ext_map = 
-            NXCreateMapTableFromZone(NXPtrValueMapPrototype, 32, 
-                                     _objc_internal_zone());        
+            NXCreateMapTable(NXPtrValueMapPrototype, 32);
     }
 
     protos = _getObjcProtocols(hi, &count);
@@ -2192,8 +2096,6 @@ static void _objc_fixup_protocol_objects_for_image (header_info * hi)
     for (i = 0; i < count; i++) {
         fix_protocol(protos[i], protocolClass, isBundle, names, names_size);
     }
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -2206,25 +2108,27 @@ static void _objc_fixup_selector_refs   (const header_info *hi)
     size_t count;
     SEL *sels;
 
+    bool preoptimized = hi->isPreoptimized();
+
     if (PrintPreopt) {
-        if (sel_preoptimizationValid(hi)) {
+        if (preoptimized) {
             _objc_inform("PREOPTIMIZATION: honoring preoptimized selectors in %s", 
-                         hi->fname);
+                         hi->fname());
         }
-        else if (_objcHeaderOptimizedByDyld(hi)) {
+        else if (hi->info()->optimizedByDyld()) {
             _objc_inform("PREOPTIMIZATION: IGNORING preoptimized selectors in %s", 
-                         hi->fname);
+                         hi->fname());
         }
     }
 
-    if (sel_preoptimizationValid(hi)) return;
+    if (preoptimized) return;
     
     sels = _getObjcSelectorRefs (hi, &count);
 
     map_selrefs(sels, count, headerIsBundle(hi));
 }
 
-static inline BOOL _is_threaded() {
+static inline bool _is_threaded() {
 #if TARGET_OS_WIN32
     return YES;
 #else
@@ -2240,11 +2144,10 @@ static inline BOOL _is_threaded() {
 *   dyld_priv.h says even for 64-bit.
 **********************************************************************/
 void 
-unmap_image(const struct mach_header *mh, intptr_t vmaddr_slide)
+unmap_image(const char *path __unused, const struct mach_header *mh)
 {
-    recursive_mutex_lock(&loadMethodLock);
+    recursive_mutex_locker_t lock(loadMethodLock);
     unmap_image_nolock(mh);
-    recursive_mutex_unlock(&loadMethodLock);
 }
 
 
@@ -2253,46 +2156,33 @@ unmap_image(const struct mach_header *mh, intptr_t vmaddr_slide)
 * Process the given images which are being mapped in by dyld.
 * Calls ABI-agnostic code after taking ABI-specific locks.
 **********************************************************************/
-const char *
-map_images(enum dyld_image_states state, uint32_t infoCount,
-           const struct dyld_image_info infoList[])
+void
+map_images(unsigned count, const char * const paths[],
+           const struct mach_header * const mhdrs[])
 {
-    const char *err;
-
-    recursive_mutex_lock(&loadMethodLock);
-    err = map_images_nolock(state, infoCount, infoList);
-    recursive_mutex_unlock(&loadMethodLock);
-
-    return err;
+    recursive_mutex_locker_t lock(loadMethodLock);
+    map_images_nolock(count, paths, mhdrs);
 }
 
 
 /***********************************************************************
 * load_images
 * Process +load in the given images which are being mapped in by dyld.
-* Calls ABI-agnostic code after taking ABI-specific locks.
 *
 * Locking: acquires classLock and loadMethodLock
 **********************************************************************/
-const char *
-load_images(enum dyld_image_states state, uint32_t infoCount,
-           const struct dyld_image_info infoList[])
-{
-    BOOL found;
+extern void prepare_load_methods(const headerType *mhdr);
 
-    recursive_mutex_lock(&loadMethodLock);
+void
+load_images(const char *path __unused, const struct mach_header *mh)
+{
+    recursive_mutex_locker_t lock(loadMethodLock);
 
     // Discover +load methods
-    found = load_images_nolock(state, infoCount, infoList);
+    prepare_load_methods((const headerType *)mh);
 
     // Call +load methods (without classLock - re-entrant)
-    if (found) {
-        call_load_methods();
-    }
-
-    recursive_mutex_unlock(&loadMethodLock);
-
-    return nil;
+    call_load_methods();
 }
 #endif
 
@@ -2301,10 +2191,10 @@ load_images(enum dyld_image_states state, uint32_t infoCount,
 * _read_images
 * Perform metadata processing for hCount images starting with firstNewHeader
 **********************************************************************/
-void _read_images(header_info **hList, uint32_t hCount)
+void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClass)
 {
     uint32_t i;
-    BOOL categoriesLoaded = NO;
+    bool categoriesLoaded = NO;
 
     if (!class_hash) _objc_init_class_hash();
 
@@ -2319,7 +2209,7 @@ void _read_images(header_info **hList, uint32_t hCount)
     // But not if any other threads are running - they might
     // call a category method before the fixups below are complete.
      if (!_is_threaded()) {
-        BOOL needFlush = NO;
+        bool needFlush = NO;
         for (i = 0; i < hCount; i++) {
             needFlush |= _objc_read_categories_from_image(hList[i]);
         }
@@ -2343,7 +2233,7 @@ void _read_images(header_info **hList, uint32_t hCount)
     // But not if this is the only thread - it's more 
     // efficient to attach categories earlier if safe.
     if (!categoriesLoaded) {
-        BOOL needFlush = NO;
+        bool needFlush = NO;
         for (i = 0; i < hCount; i++) {
             needFlush |= _objc_read_categories_from_image(hList[i]);
         }
@@ -2369,13 +2259,18 @@ static void schedule_class_load(Class cls)
     cls->info |= CLS_LOADED;
 }
 
-void prepare_load_methods(header_info *hi)
+void prepare_load_methods(const headerType *mhdr)
 {
     Module mods;
     unsigned int midx;
-    
 
-    if (_objcHeaderIsReplacement(hi)) {
+    header_info *hi;
+    for (hi = FirstHeader; hi; hi = hi->getNext()) {
+        if (mhdr == hi->mhdr()) break;
+    }
+    if (!hi) return;
+
+    if (hi->info()->isReplacement()) {
         // Ignore any classes in this image
         return;
     }
@@ -2463,8 +2358,8 @@ static void rependClassReferences(Class *refs, size_t count,
     // Process each class ref
     for (i = 0; i < count; i++) {
         if ((uintptr_t)(refs[i]) >= start  &&  (uintptr_t)(refs[i]) < end) {
-            pendClassReference(&refs[i], refs[i]->name, 
-                               (refs[i]->info & CLS_META) ? YES : NO);
+            pendClassReference(&refs[i], refs[i]->name,
+                               refs[i]->info & CLS_META);
             refs[i] = nil;
         }
     }
@@ -2596,7 +2491,7 @@ static void _objc_remove_classes_in_image(header_info *hi)
     unsigned int       midx;
     Module             mods;
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
     
     // Major loop - process all modules in the image
     mods = hi->mod_ptr;
@@ -2636,7 +2531,6 @@ static void _objc_remove_classes_in_image(header_info *hi)
             
             // Remove from class_hash
             NXHashRemove(class_hash, cls);
-            objc_removeRegisteredClass(cls);
 
             // Free heap memory pointed to by the class
             unload_class(cls->ISA());
@@ -2651,10 +2545,10 @@ static void _objc_remove_classes_in_image(header_info *hi)
     // Get the location of the dying image's __OBJC segment
     uintptr_t seg;
     unsigned long seg_size;
-    seg = (uintptr_t)getsegmentdata(hi->mhdr, "__OBJC", &seg_size);
+    seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
 
     header_info *other_hi;
-    for (other_hi = FirstHeader; other_hi != nil; other_hi = other_hi->next) {
+    for (other_hi = FirstHeader; other_hi != nil; other_hi = other_hi->getNext()) {
         Class *other_refs;
         size_t count;
         if (other_hi == hi) continue;  // skip the image being unloaded
@@ -2663,8 +2557,6 @@ static void _objc_remove_classes_in_image(header_info *hi)
         other_refs = _getObjcClassRefs(other_hi, &count);
         rependClassReferences(other_refs, count, seg, seg+seg_size);
     }
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -2729,12 +2621,12 @@ static void unload_paranoia(header_info *hi)
     // Get the location of the dying image's __OBJC segment
     uintptr_t seg;
     unsigned long seg_size;
-    seg = (uintptr_t)getsegmentdata(hi->mhdr, "__OBJC", &seg_size);
+    seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
 
     _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]", 
-                 hi->fname, (void *)seg, (void*)(seg+seg_size));
+                 hi->fname(), (void *)seg, (void*)(seg+seg_size));
 
-    mutex_lock(&classLock);
+    mutex_locker_t lock(classLock);
 
     // Make sure the image contains no categories on surviving classes.
     {
@@ -2791,8 +2683,6 @@ static void unload_paranoia(header_info *hi)
             }
         }
     }
-
-    mutex_unlock(&classLock);
 }
 
 
@@ -2803,7 +2693,7 @@ static void unload_paranoia(header_info *hi)
 **********************************************************************/
 void _unload_image(header_info *hi)
 {
-    recursive_mutex_assert_locked(&loadMethodLock);
+    loadMethodLock.assertLocked();
 
     // Cleanup:
     // Remove image's classes from the class list and free auxiliary data.
@@ -2812,7 +2702,8 @@ void _unload_image(header_info *hi)
     _objc_remove_classes_in_image(hi);
     _objc_remove_categories_in_image(hi);
     _objc_remove_pending_class_refs_in_image(hi);
-    
+    if (hi->proto_refs) try_free(hi->proto_refs);
+
     // Perform various debugging checks if requested.
     if (DebugUnload) unload_paranoia(hi);
 }
@@ -2829,7 +2720,7 @@ void              objc_addClass           (Class cls)
     OBJC_WARN_DEPRECATED;
 
     // Synchronize access to hash table
-    mutex_lock (&classLock);
+    mutex_locker_t lock(classLock);
 
     // Make sure both the class and the metaclass have caches!
     // Clear all bits of the info fields except CLS_CLASS and CLS_META.
@@ -2854,16 +2745,12 @@ void            objc_addClass           (Class cls)
 
     // Add the class to the table
     (void) NXHashInsert (class_hash, cls);
-    objc_addRegisteredClass(cls);
 
     // Superclass is no longer a leaf for cache flushing
     if (cls->superclass && (cls->superclass->info & CLS_LEAF)) {
         cls->superclass->clearInfo(CLS_LEAF);
         cls->superclass->ISA()->clearInfo(CLS_LEAF);
     }
-
-    // Desynchronize
-    mutex_unlock (&classLock);
 }
 
 /***********************************************************************
@@ -2887,7 +2774,7 @@ static void _objcTweakMethodListPointerForClass(Class cls)
 
     // Allocate and zero a method list array
     mallocSize   = sizeof(old_method_list *) * initialEntries;
-    ptr             = (old_method_list **) _calloc_internal(1, mallocSize);
+    ptr             = (old_method_list **) calloc(1, mallocSize);
 
     // Insert the existing list into the array
     ptr[initialEntries - 1] = END_OF_METHODS_LIST;
@@ -2957,7 +2844,6 @@ void _objc_insertMethods(Class cls, old_method_list *mlist, old_category *cat)
         newSize  = oldSize + sizeof(old_method_list *); // only increase by 1
 
         // Grow the method list array by one.
-        // This block may be from user code; don't use _realloc_internal
         *list = (old_method_list **)realloc(*list, newSize);
 
         // Zero out addition part of new array
@@ -3060,12 +2946,24 @@ static inline void _objc_add_category(Class cls, old_category *category, int ver
         }
     }
 
-    // Augment properties
+    // Augment instance properties
     if (version >= 7  &&  category->instance_properties) {
         if (cls->ISA()->version >= 6) {
             _class_addProperties(cls, category->instance_properties);
         } else {
-            _objc_inform ("unable to add properties from category %s...\n", category->category_name);
+            _objc_inform ("unable to add instance properties from category %s...\n", category->category_name);
+            _objc_inform ("class `%s' must be recompiled\n", category->class_name);
+        }
+    }
+
+    // Augment class properties
+    if (version >= 7  &&  category->hasClassPropertiesField()  &&  
+        category->class_properties) 
+    {
+        if (cls->ISA()->version >= 6) {
+            _class_addProperties(cls->ISA(), category->class_properties);
+        } else {
+            _objc_inform ("unable to add class properties from category %s...\n", category->category_name);
             _objc_inform ("class `%s' must be recompiled\n", category->class_name);
         }
     }
@@ -3076,14 +2974,15 @@ static inline void _objc_add_category(Class cls, old_category *category, int ver
 * methods into the class it augments, and flush the class' method cache.
 * Return YES if some method caches now need to be flushed.
 **********************************************************************/
-static BOOL _objc_add_category_flush_caches(Class cls, old_category *category, int version)
+static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version)
 {
-    BOOL needFlush = NO;
+    bool needFlush = NO;
 
     // Install the category's methods into its intended class
-    mutex_lock(&methodListLock);
-    _objc_add_category (cls, category, version);
-    mutex_unlock(&methodListLock);
+    {
+        mutex_locker_t lock(methodListLock);
+        _objc_add_category (cls, category, version);
+    }
 
     // Queue for cache flushing so category's methods can get called
     if (category->instance_methods) {
@@ -3162,7 +3061,7 @@ static void resolve_categories_for_class(Class cls)
 
         // Delink and reclaim this registration
         next = pending->next;
-        _free_internal(pending);
+        free(pending);
         pending = next;
     }
 }
@@ -3204,7 +3103,7 @@ void _objc_resolve_categories_for_class(Class cls)
 *   they were discovered.
 * Returns YES if some method caches now need to be flushed.
 **********************************************************************/
-static BOOL _objc_register_category(old_category *cat, int version)
+static bool _objc_register_category(old_category *cat, int version)
 {
     _objc_unresolved_category *        new_cat;
     _objc_unresolved_category *        old;
@@ -3234,9 +3133,7 @@ static BOOL _objc_register_category(old_category *cat, int version)
 
     // Create category lookup table if needed
     if (!category_hash)
-        category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
-                                                  128,
-                                                  _objc_internal_zone ());
+        category_hash = NXCreateMapTable(NXStrValueMapPrototype, 128);
 
     // Locate an existing list of categories, if any, for the class.
     old = (_objc_unresolved_category *)
@@ -3246,7 +3143,7 @@ static BOOL _objc_register_category(old_category *cat, int version)
     // The category list is built backwards, and is reversed again 
     // by resolve_categories_for_class().
     new_cat = (_objc_unresolved_category *)
-        _malloc_internal(sizeof(_objc_unresolved_category));
+        malloc(sizeof(_objc_unresolved_category));
     new_cat->next    = old;
     new_cat->cat     = cat;
     new_cat->version = version;
@@ -3322,16 +3219,14 @@ Class gdb_object_getClass(id obj)
 /***********************************************************************
 * Lock management
 **********************************************************************/
-rwlock_t selLock = {};
-mutex_t classLock = MUTEX_INITIALIZER;
-mutex_t methodListLock = MUTEX_INITIALIZER;
-mutex_t cacheUpdateLock = MUTEX_INITIALIZER;
-recursive_mutex_t loadMethodLock = RECURSIVE_MUTEX_INITIALIZER;
+rwlock_t selLock;
+mutex_t classLock;
+mutex_t methodListLock;
+mutex_t cacheUpdateLock;
+recursive_mutex_t loadMethodLock;
 
 void lock_init(void)
 {
-    rwlock_init(&selLock);
-    recursive_mutex_init(&loadMethodLock);
 }