]> git.saurik.com Git - apple/objc4.git/blobdiff - runtime/objc-runtime-old.h
objc4-818.2.tar.gz
[apple/objc4.git] / runtime / objc-runtime-old.h
index fe319e6e29a90a07898e458100c29b12a12f8e17..14672106da8ca9ef8ba8c9b76689c0bcfa1d571f 100644 (file)
 #define _OBJC_RUNTIME_OLD_H
 
 #include "objc-private.h"
-#include "objc-file-old.h"
 
+#define CLS_CLASS              0x1
+#define CLS_META               0x2
+#define CLS_INITIALIZED                0x4
+#define CLS_POSING             0x8
+#define CLS_MAPPED             0x10
+#define CLS_FLUSH_CACHE                0x20
+#define CLS_GROW_CACHE         0x40
+#define CLS_NEED_BIND          0x80
+#define CLS_METHOD_ARRAY        0x100
+// the JavaBridge constructs classes with these markers
+#define CLS_JAVA_HYBRID                0x200
+#define CLS_JAVA_CLASS         0x400
+// thread-safe +initialize
+#define CLS_INITIALIZING       0x800
+// bundle unloading
+#define CLS_FROM_BUNDLE                0x1000
+// C++ ivar support
+#define CLS_HAS_CXX_STRUCTORS  0x2000
+// Lazy method list arrays
+#define CLS_NO_METHOD_ARRAY    0x4000
+// +load implementation
+#define CLS_HAS_LOAD_METHOD     0x8000
+// objc_allocateClassPair API
+#define CLS_CONSTRUCTING        0x10000
+// visibility=hidden
+#define CLS_HIDDEN              0x20000
+// available for use; was CLS_FINALIZE_ON_MAIN_THREAD
+#define CLS_40000               0x40000
+// Lazy property list arrays
+#define CLS_NO_PROPERTY_ARRAY  0x80000
+// +load implementation
+#define CLS_CONNECTED           0x100000
+#define CLS_LOADED              0x200000
+// objc_allocateClassPair API
+#define CLS_CONSTRUCTED         0x400000
+// class is leaf for cache flushing
+#define CLS_LEAF                0x800000
+// class instances may have associative references
+#define CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS 0x1000000
+// available for use; was CLS_HAS_INSTANCE_SPECIFIC_LAYOUT
+#define CLS_2000000 0x2000000
+// class compiled with ARC
+#define CLS_IS_ARC              0x4000000
+// class is not ARC but has ARC-style weak ivar layout
+#define CLS_HAS_WEAK_WITHOUT_ARC 0x8000000
+
+
+// Terminator for array of method lists
+#define END_OF_METHODS_LIST ((struct old_method_list*)-1)
+
+#define ISCLASS(cls)           (((cls)->info & CLS_CLASS) != 0)
+#define ISMETA(cls)            (((cls)->info & CLS_META) != 0)
+#define GETMETA(cls)           (ISMETA(cls) ? (cls) : (cls)->ISA())
 
-struct old_class {
-    struct old_class *isa;
-    struct old_class *super_class;
-    const char *name;
-    long version;
-    long info;
-    long instance_size;
-    struct old_ivar_list *ivars;
-    struct old_method_list **methodLists;
-    Cache cache;
-    struct old_protocol_list *protocols;
-    // CLS_EXT only
-    const uint8_t *ivar_layout;
-    struct old_class_ext *ext;
-};
 
 struct old_class_ext {
     uint32_t size;
@@ -56,8 +93,15 @@ struct old_category {
     struct old_method_list *instance_methods;
     struct old_method_list *class_methods;
     struct old_protocol_list *protocols;
+    // Fields below this point are in version 7 or later only.
     uint32_t size;
     struct old_property_list *instance_properties;
+    // Check size for fields below this point.
+    struct old_property_list *class_properties;
+
+    bool hasClassPropertiesField() const { 
+        return size >= offsetof(old_category, class_properties) + sizeof(class_properties);
+    }
 };
 
 struct old_ivar {
@@ -86,7 +130,7 @@ struct old_method {
 };
 
 struct old_method_list {
-    struct old_method_list *obsolete;
+    void *obsolete;
 
     int method_count;
 #ifdef __LP64__
@@ -116,6 +160,11 @@ struct old_protocol_ext {
     struct objc_method_description_list *optional_class_methods;
     struct old_property_list *instance_properties;
     const char **extendedMethodTypes;
+    struct old_property_list *class_properties;
+
+    bool hasClassPropertiesField() const { 
+        return size >= offsetof(old_protocol_ext, class_properties) + sizeof(class_properties);
+    }
 };
 
 
@@ -131,86 +180,212 @@ struct old_property_list {
 };
 
 
-#define CLS_CLASS              0x1
-#define CLS_META               0x2
-#define CLS_INITIALIZED                0x4
-#define CLS_POSING             0x8
-#define CLS_MAPPED             0x10
-#define CLS_FLUSH_CACHE                0x20
-#define CLS_GROW_CACHE         0x40
-#define CLS_NEED_BIND          0x80
-#define CLS_METHOD_ARRAY        0x100
-// the JavaBridge constructs classes with these markers
-#define CLS_JAVA_HYBRID                0x200
-#define CLS_JAVA_CLASS         0x400
-// thread-safe +initialize
-#define CLS_INITIALIZING       0x800
-// bundle unloading
-#define CLS_FROM_BUNDLE                0x1000
-// C++ ivar support
-#define CLS_HAS_CXX_STRUCTORS  0x2000
-// Lazy method list arrays
-#define CLS_NO_METHOD_ARRAY    0x4000
-// +load implementation
-#define CLS_HAS_LOAD_METHOD     0x8000
-// objc_allocateClassPair API
-#define CLS_CONSTRUCTING        0x10000
-// visibility=hidden
-#define CLS_HIDDEN              0x20000
-// GC:  class has unsafe finalize method
-#define CLS_FINALIZE_ON_MAIN_THREAD 0x40000
-// Lazy property list arrays
-#define CLS_NO_PROPERTY_ARRAY  0x80000
-// +load implementation
-#define CLS_CONNECTED           0x100000
-#define CLS_LOADED              0x200000
-// objc_allocateClassPair API
-#define CLS_CONSTRUCTED         0x400000
-// class is leaf for cache flushing
-#define CLS_LEAF                0x800000
-// class instances may have associative references
-#define CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS 0x1000000
-// class has instance-specific GC layout
-#define CLS_HAS_INSTANCE_SPECIFIC_LAYOUT 0x2000000
+struct objc_class : objc_object {
+    Class superclass;
+    const char *name;
+    uint32_t version;
+    uint32_t info;
+    uint32_t instance_size;
+    struct old_ivar_list *ivars;
+    struct old_method_list **methodLists;
+    Cache cache;
+    struct old_protocol_list *protocols;
+    // CLS_EXT only
+    const uint8_t *ivar_layout;
+    struct old_class_ext *ext;
 
+    void setInfo(uint32_t set) {
+        OSAtomicOr32Barrier(set, (volatile uint32_t *)&info);
+    }
+
+    void clearInfo(uint32_t clear) {
+        OSAtomicXor32Barrier(clear, (volatile uint32_t *)&info);
+    }
+
+
+    // set and clear must not overlap
+    void changeInfo(uint32_t set, uint32_t clear) {
+        ASSERT((set & clear) == 0);
+
+        uint32_t oldf, newf;
+        do {
+            oldf = this->info;
+            newf = (oldf | set) & ~clear;
+        } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&info));
+    }
+
+    bool hasCxxCtor() {
+        // set_superclass propagates the flag from the superclass.
+        return info & CLS_HAS_CXX_STRUCTORS;
+    }
+
+    bool hasCxxDtor() {
+        return hasCxxCtor();  // one bit for both ctor and dtor
+    }
+
+    // Return YES if the class's ivars are managed by ARC, 
+    // or the class is MRC but has ARC-style weak ivars.
+    bool hasAutomaticIvars() {
+        return info & (CLS_IS_ARC | CLS_HAS_WEAK_WITHOUT_ARC);
+    }
+
+    // Return YES if the class's ivars are managed by ARC.
+    bool isARC() {
+        return info & CLS_IS_ARC;
+    }
+
+    bool hasCustomRR() {
+        return true;
+    }
+
+    bool hasCustomAWZ() {
+        return true;
+    }
+
+    bool forbidsAssociatedObjects() {
+        // Old runtime doesn't support forbidding associated objects.
+        return false;
+    }
+    
+    bool instancesHaveAssociatedObjects() {
+        return info & CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS;
+    }
+
+    void setInstancesHaveAssociatedObjects() {
+        setInfo(CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS);
+    }
+
+    bool shouldGrowCache() {
+        return info & CLS_GROW_CACHE;
+    }
+
+    void setShouldGrowCache(bool grow) {
+        if (grow) setInfo(CLS_GROW_CACHE);
+        else clearInfo(CLS_GROW_CACHE);
+    }
+
+    // +initialize bits are stored on the metaclass only
+    bool isInitializing() {
+        return getMeta()->info & CLS_INITIALIZING;
+    }
+
+    // +initialize bits are stored on the metaclass only
+    void setInitializing() {
+        getMeta()->setInfo(CLS_INITIALIZING);
+    }
+
+    // +initialize bits are stored on the metaclass only
+    bool isInitialized() {
+        return getMeta()->info & CLS_INITIALIZED;
+    }
+
+    // +initialize bits are stored on the metaclass only
+    void setInitialized() {
+        getMeta()->changeInfo(CLS_INITIALIZED, CLS_INITIALIZING);
+    }
+
+    bool isLoadable() {
+        // A class registered for +load is ready for +load to be called
+        // if it is connected.
+        return isConnected();
+    }
+
+    IMP getLoadMethod();
+
+    bool isFuture();
+
+    bool isConnected();
+
+    const char *mangledName() { return name; }
+    const char *demangledName() { return name; }
+    const char *nameForLogging() { return name; }
+    
+    bool isRootClass() {
+        return superclass == nil;
+    }
+
+    bool isRootMetaclass() {
+        return ISA() == (Class)this;
+    }
+
+    bool isMetaClass() {
+        return info & CLS_META;
+    }
+
+    // NOT identical to this->ISA() when this is a metaclass
+    Class getMeta() {
+        if (isMetaClass()) return (Class)this;
+        else return this->ISA();
+    }
+
+    // May be unaligned depending on class's ivars.
+    uint32_t unalignedInstanceStart() {
+        // This is not simply superclass->instance_size.
+        // superclass->instance_size is padded to its sizeof() boundary, 
+        // which may envelop one of this class's ivars. 
+        // That in turn would break ARC-style ivar layouts.
+        // Instead, we use the address of this class's first ivar when possible.
+        if (!superclass) return 0;
+        if (!ivars || ivars->ivar_count == 0) return superclass->instance_size;
+        return ivars->ivar_list[0].ivar_offset;
+    }
+
+    // Class's instance start rounded up to a pointer-size boundary.
+    // This is used for ARC layout bitmaps.
+    uint32_t alignedInstanceStart() {
+        return word_align(unalignedInstanceStart());
+    }
+
+
+    // May be unaligned depending on class's ivars.
+    uint32_t unalignedInstanceSize() {
+        return instance_size;
+    }
+
+    // Class's ivar size rounded up to a pointer-size boundary.
+    uint32_t alignedInstanceSize() {
+        return word_align(unalignedInstanceSize());
+    }
+
+    size_t instanceSize(size_t extraBytes) {
+        size_t size = alignedInstanceSize() + extraBytes;
+        // CF requires all objects be at least 16 bytes.
+        if (size < 16) size = 16;
+        return size;
+    }
 
-// Terminator for array of method lists
-#define END_OF_METHODS_LIST ((struct old_method_list*)-1)
+};
 
-#define ISCLASS(cls)           (((cls)->info & CLS_CLASS) != 0)
-#define ISMETA(cls)            (((cls)->info & CLS_META) != 0)
-#define GETMETA(cls)           (ISMETA(cls) ? (cls) : (cls)->isa)
 
+#include "hashtable2.h"
 
 __BEGIN_DECLS
 
-#define oldcls(cls) ((struct old_class *)cls)
 #define oldprotocol(proto) ((struct old_protocol *)proto)
 #define oldmethod(meth) ((struct old_method *)meth)
 #define oldcategory(cat) ((struct old_category *)cat)
 #define oldivar(ivar) ((struct old_ivar *)ivar)
 #define oldproperty(prop) ((struct old_property *)prop)
 
-extern void unload_class(struct old_class *cls);
+extern NXHashTable *class_hash;
+
+extern void unload_class(Class cls);
 
-extern Class objc_getOrigClass (const char *name);
 extern IMP lookupNamedMethodInMethodList(struct old_method_list *mlist, const char *meth_name);
-extern void _objc_insertMethods(struct old_class *cls, struct old_method_list *mlist, struct old_category *cat);
-extern void _objc_removeMethods(struct old_class *cls, struct old_method_list *mlist);
+extern void _objc_insertMethods(Class cls, struct old_method_list *mlist, struct old_category *cat);
+extern void _objc_removeMethods(Class cls, struct old_method_list *mlist);
 extern void _objc_flush_caches (Class cls);
-extern BOOL _class_addProperties(struct old_class *cls, struct old_property_list *additions);
-extern void change_class_references(struct old_class *imposter, struct old_class *original, struct old_class *copy, BOOL changeSuperRefs);
+extern bool _class_addProperties(Class cls, struct old_property_list *additions);
+extern bool _class_hasLoadMethod(Class cls);
+extern void change_class_references(Class imposter, Class original, Class copy, bool changeSuperRefs);
 extern void flush_marked_caches(void);
-extern void set_superclass(struct old_class *cls, struct old_class *supercls, BOOL cls_is_new);
+extern void set_superclass(Class cls, Class supercls, bool cls_is_new);
 extern void try_free(const void *p);
 
 extern struct old_property *property_list_nth(const struct old_property_list *plist, uint32_t i);
 extern struct old_property **copyPropertyList(struct old_property_list *plist, unsigned int *outCount);
 
-extern void _class_setInfo(Class cls, long set);
-extern void _class_clearInfo(Class cls, long clear);
-extern void _class_changeInfo(Class cls, long set, long clear);
-
+extern struct objc_method_description * lookup_protocol_method(struct old_protocol *proto, SEL aSel, bool isRequiredMethod, bool isInstanceMethod, bool recursive);
 
 // used by flush_caches outside objc-cache.m
 extern void _cache_flush(Class cls);