X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/cd5f04f5e921b81f893bb165605f65af4658baa2..refs/heads/master:/runtime/objc-runtime-old.h diff --git a/runtime/objc-runtime-old.h b/runtime/objc-runtime-old.h index fe319e6..1467210 100644 --- a/runtime/objc-runtime-old.h +++ b/runtime/objc-runtime-old.h @@ -25,24 +25,61 @@ #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);