+ 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;
+ }