2 * Copyright (c) 2005-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #ifndef _OBJC_RUNTIME_NEW_H
25 #define _OBJC_RUNTIME_NEW_H
30 typedef uint32_t mask_t
; // x86_64 & arm64 asm are less efficient with 16-bits
32 typedef uint16_t mask_t
;
34 typedef uintptr_t cache_key_t
;
45 inline cache_key_t
key() const { return _key
; }
46 inline IMP
imp() const { return (IMP
)_imp
; }
47 inline void setKey(cache_key_t newKey
) { _key
= newKey
; }
48 inline void setImp(IMP newImp
) { _imp
= newImp
; }
50 void set(cache_key_t newKey
, IMP newImp
);
55 struct bucket_t
*_buckets
;
60 struct bucket_t
*buckets();
63 void incrementOccupied();
64 void setBucketsAndMask(struct bucket_t
*newBuckets
, mask_t newMask
);
70 static size_t bytesForCapacity(uint32_t cap
);
71 static struct bucket_t
* endMarker(struct bucket_t
*b
, uint32_t cap
);
74 void reallocate(mask_t oldCapacity
, mask_t newCapacity
);
75 struct bucket_t
* find(cache_key_t key
);
77 static void bad_cache(id receiver
, SEL sel
, Class isa
) __attribute__((noreturn
));
81 // classref_t is unremapped class_t*
82 typedef struct classref
* classref_t
;
89 struct SortBySELAddress
:
90 public std::binary_function
<const method_t
&,
91 const method_t
&, bool>
93 bool operator() (const method_t
& lhs
,
95 { return lhs
.name
< rhs
.name
; }
99 struct method_list_t
{
100 uint32_t entsize_NEVER_USE
; // high bits used for fixup markers
104 uint32_t getEntsize() const {
105 return entsize_NEVER_USE
& ~(uint32_t)3;
107 uint32_t getCount() const {
110 method_t
& getOrEnd(uint32_t i
) const {
112 return *(method_t
*)((uint8_t *)&first
+ i
*getEntsize());
114 method_t
& get(uint32_t i
) const {
119 // iterate methods, taking entsize into account
120 // fixme need a proper const_iterator
121 struct method_iterator
{
123 uint32_t index
; // keeping track of this saves a divide in operator-
126 typedef std::random_access_iterator_tag iterator_category
;
127 typedef method_t value_type
;
128 typedef ptrdiff_t difference_type
;
129 typedef method_t
* pointer
;
130 typedef method_t
& reference
;
132 method_iterator() { }
134 method_iterator(const method_list_t
& mlist
, uint32_t start
= 0)
135 : entsize(mlist
.getEntsize())
137 , method(&mlist
.getOrEnd(start
))
140 const method_iterator
& operator += (ptrdiff_t delta
) {
141 method
= (method_t
*)((uint8_t *)method
+ delta
*entsize
);
142 index
+= (int32_t)delta
;
145 const method_iterator
& operator -= (ptrdiff_t delta
) {
146 method
= (method_t
*)((uint8_t *)method
- delta
*entsize
);
147 index
-= (int32_t)delta
;
150 const method_iterator
operator + (ptrdiff_t delta
) const {
151 return method_iterator(*this) += delta
;
153 const method_iterator
operator - (ptrdiff_t delta
) const {
154 return method_iterator(*this) -= delta
;
157 method_iterator
& operator ++ () { *this += 1; return *this; }
158 method_iterator
& operator -- () { *this -= 1; return *this; }
159 method_iterator
operator ++ (int) {
160 method_iterator
result(*this); *this += 1; return result
;
162 method_iterator
operator -- (int) {
163 method_iterator
result(*this); *this -= 1; return result
;
166 ptrdiff_t operator - (const method_iterator
& rhs
) const {
167 return (ptrdiff_t)this->index
- (ptrdiff_t)rhs
.index
;
170 method_t
& operator * () const { return *method
; }
171 method_t
* operator -> () const { return method
; }
173 operator method_t
& () const { return *method
; }
175 bool operator == (const method_iterator
& rhs
) {
176 return this->method
== rhs
.method
;
178 bool operator != (const method_iterator
& rhs
) {
179 return this->method
!= rhs
.method
;
182 bool operator < (const method_iterator
& rhs
) {
183 return this->method
< rhs
.method
;
185 bool operator > (const method_iterator
& rhs
) {
186 return this->method
> rhs
.method
;
190 method_iterator
begin() const { return method_iterator(*this, 0); }
191 method_iterator
end() const { return method_iterator(*this, getCount()); }
197 // *offset was originally 64-bit on some x86_64 platforms.
198 // We read and write only 32 bits of it.
199 // Some metadata provides all 64 bits. This is harmless for unsigned
200 // little-endian values.
201 // Some code uses all 64 bits. class_addIvar() over-allocates the
202 // offset for their benefit.
207 // alignment is sometimes -1; use alignment() instead
208 uint32_t alignment_raw
;
211 uint32_t alignment() {
212 if (alignment_raw
== ~(uint32_t)0) return 1U << WORD_SHIFT
;
213 return 1 << alignment_raw
;
225 const char *attributes
;
228 struct property_list_t
{
234 typedef uintptr_t protocol_ref_t
; // protocol_t *, but unremapped
236 #define PROTOCOL_FIXED_UP (1<<31) // must never be set by compiler
238 struct protocol_t
: objc_object
{
239 const char *mangledName
;
240 struct protocol_list_t
*protocols
;
241 method_list_t
*instanceMethods
;
242 method_list_t
*classMethods
;
243 method_list_t
*optionalInstanceMethods
;
244 method_list_t
*optionalClassMethods
;
245 property_list_t
*instanceProperties
;
246 uint32_t size
; // sizeof(protocol_t)
248 const char **extendedMethodTypes
;
250 // Fields below this point are allocated at runtime
251 // and are not present on disk.
252 const char *_demangledName
;
254 const char *demangledName();
256 const char *nameForLogging() {
257 return demangledName();
260 bool isFixedUp() const {
261 return flags
& PROTOCOL_FIXED_UP
;
264 bool hasExtendedMethodTypesField() const {
265 return size
>= (offsetof(protocol_t
, extendedMethodTypes
)
266 + sizeof(extendedMethodTypes
));
268 bool hasExtendedMethodTypes() const {
269 return hasExtendedMethodTypesField() && extendedMethodTypes
;
273 struct protocol_list_t
{
274 // count is 64-bit by accident.
276 protocol_ref_t list
[0]; // variable-size
281 uint32_t instanceStart
;
282 uint32_t instanceSize
;
287 const uint8_t * ivarLayout
;
290 const method_list_t
* baseMethods
;
291 const protocol_list_t
* baseProtocols
;
292 const ivar_list_t
* ivars
;
294 const uint8_t * weakIvarLayout
;
295 const property_list_t
*baseProperties
;
302 const class_ro_t
*ro
;
305 method_list_t
**method_lists
; // RW_METHOD_ARRAY == 1
306 method_list_t
*method_list
; // RW_METHOD_ARRAY == 0
308 struct chained_property_list
*properties
;
309 const protocol_list_t
** protocols
;
312 Class nextSiblingClass
;
316 void setFlags(uint32_t set
)
318 OSAtomicOr32Barrier(set
, &flags
);
321 void clearFlags(uint32_t clear
)
323 OSAtomicXor32Barrier(clear
, &flags
);
326 // set and clear must not overlap
327 void changeFlags(uint32_t set
, uint32_t clear
)
329 assert((set
& clear
) == 0);
334 newf
= (oldf
| set
) & ~clear
;
335 } while (!OSAtomicCompareAndSwap32Barrier(oldf
, newf
, (volatile int32_t *)&flags
));
340 // class_data_bits_t is the class_t->data field (class_rw_t pointer plus flags)
341 // The extra bits are optimized for the retain/release and alloc/dealloc paths.
343 // Values for class_ro_t->flags
344 // These are emitted by the compiler and are part of the ABI.
345 // class is a metaclass
346 #define RO_META (1<<0)
347 // class is a root class
348 #define RO_ROOT (1<<1)
349 // class has .cxx_construct/destruct implementations
350 #define RO_HAS_CXX_STRUCTORS (1<<2)
351 // class has +load implementation
352 // #define RO_HAS_LOAD_METHOD (1<<3)
353 // class has visibility=hidden set
354 #define RO_HIDDEN (1<<4)
355 // class has attribute(objc_exception): OBJC_EHTYPE_$_ThisClass is non-weak
356 #define RO_EXCEPTION (1<<5)
357 // this bit is available for reassignment
358 // #define RO_REUSE_ME (1<<6)
359 // class compiled with -fobjc-arc (automatic retain/release)
360 #define RO_IS_ARR (1<<7)
361 // class has .cxx_destruct but no .cxx_construct (with RO_HAS_CXX_STRUCTORS)
362 #define RO_HAS_CXX_DTOR_ONLY (1<<8)
364 // class is in an unloadable bundle - must never be set by compiler
365 #define RO_FROM_BUNDLE (1<<29)
366 // class is unrealized future class - must never be set by compiler
367 #define RO_FUTURE (1<<30)
368 // class is realized - must never be set by compiler
369 #define RO_REALIZED (1<<31)
371 // Values for class_rw_t->flags
372 // These are not emitted by the compiler and are never used in class_ro_t.
373 // Their presence should be considered in future ABI versions.
374 // class_t->data is class_rw_t, not class_ro_t
375 #define RW_REALIZED (1<<31)
376 // class is unresolved future class
377 #define RW_FUTURE (1<<30)
378 // class is initialized
379 #define RW_INITIALIZED (1<<29)
380 // class is initializing
381 #define RW_INITIALIZING (1<<28)
382 // class_rw_t->ro is heap copy of class_ro_t
383 #define RW_COPIED_RO (1<<27)
384 // class allocated but not yet registered
385 #define RW_CONSTRUCTING (1<<26)
386 // class allocated and registered
387 #define RW_CONSTRUCTED (1<<25)
388 // GC: class has unsafe finalize method
389 #define RW_FINALIZE_ON_MAIN_THREAD (1<<24)
390 // class +load has been called
391 #define RW_LOADED (1<<23)
392 #if !SUPPORT_NONPOINTER_ISA
393 // class instances may have associative references
394 #define RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS (1<<22)
396 // class has instance-specific GC layout
397 #define RW_HAS_INSTANCE_SPECIFIC_LAYOUT (1 << 21)
398 // class's method list is an array of method lists
399 #define RW_METHOD_ARRAY (1<<20)
400 // class has started realizing but not yet completed it
401 #define RW_REALIZING (1<<19)
403 // NOTE: MORE RW_ FLAGS DEFINED BELOW
406 // Values for class_rw_t->flags or class_t->bits
407 // These flags are optimized for retain/release and alloc/dealloc
408 // 64-bit stores more of them in class_t->bits to reduce pointer indirection.
412 // class or superclass has .cxx_construct implementation
413 #define RW_HAS_CXX_CTOR (1<<18)
414 // class or superclass has .cxx_destruct implementation
415 #define RW_HAS_CXX_DTOR (1<<17)
416 // class or superclass has default alloc/allocWithZone: implementation
417 // Note this is is stored in the metaclass.
418 #define RW_HAS_DEFAULT_AWZ (1<<16)
419 // class's instances requires raw isa
420 // not tracked for 32-bit because it only applies to non-pointer isa
421 // #define RW_REQUIRES_RAW_ISA
423 // class is a Swift class
424 #define FAST_IS_SWIFT (1UL<<0)
425 // class or superclass has default retain/release/autorelease/retainCount/
426 // _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
427 #define FAST_HAS_DEFAULT_RR (1UL<<1)
429 #define FAST_DATA_MASK 0xfffffffcUL
432 // Leaks-compatible version that steals low bits only.
434 // class or superclass has .cxx_construct implementation
435 #define RW_HAS_CXX_CTOR (1<<18)
436 // class or superclass has .cxx_destruct implementation
437 #define RW_HAS_CXX_DTOR (1<<17)
438 // class or superclass has default alloc/allocWithZone: implementation
439 // Note this is is stored in the metaclass.
440 #define RW_HAS_DEFAULT_AWZ (1<<16)
442 // class is a Swift class
443 #define FAST_IS_SWIFT (1UL<<0)
444 // class or superclass has default retain/release/autorelease/retainCount/
445 // _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
446 #define FAST_HAS_DEFAULT_RR (1UL<<1)
447 // class's instances requires raw isa
448 #define FAST_REQUIRES_RAW_ISA (1UL<<2)
450 #define FAST_DATA_MASK 0x00007ffffffffff8UL
453 // Leaks-incompatible version that steals lots of bits.
455 // class is a Swift class
456 #define FAST_IS_SWIFT (1UL<<0)
457 // class's instances requires raw isa
458 #define FAST_REQUIRES_RAW_ISA (1UL<<1)
459 // class or superclass has .cxx_destruct implementation
460 // This bit is aligned with isa_t->hasCxxDtor to save an instruction.
461 #define FAST_HAS_CXX_DTOR (1UL<<2)
463 #define FAST_DATA_MASK 0x00007ffffffffff8UL
464 // class or superclass has .cxx_construct implementation
465 #define FAST_HAS_CXX_CTOR (1UL<<47)
466 // class or superclass has default alloc/allocWithZone: implementation
467 // Note this is is stored in the metaclass.
468 #define FAST_HAS_DEFAULT_AWZ (1UL<<48)
469 // class or superclass has default retain/release/autorelease/retainCount/
470 // _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
471 #define FAST_HAS_DEFAULT_RR (1UL<<49)
472 // summary bit for fast alloc path: !hasCxxCtor and
473 // !requiresRawIsa and instanceSize fits into shiftedSize
474 #define FAST_ALLOC (1UL<<50)
475 // instance size in units of 16 bytes
476 // or 0 if the instance size is too big in this field
477 // This field must be LAST
478 #define FAST_SHIFTED_SIZE_SHIFT 51
481 // FAST_HAS_CXX_CTOR is set
482 // FAST_REQUIRES_RAW_ISA is not set
483 // FAST_SHIFTED_SIZE is not zero
484 // FAST_ALLOC does NOT check FAST_HAS_DEFAULT_AWZ because that
485 // bit is stored on the metaclass.
486 #define FAST_ALLOC_MASK (FAST_HAS_CXX_CTOR | FAST_REQUIRES_RAW_ISA)
487 #define FAST_ALLOC_VALUE (0)
492 struct class_data_bits_t
{
494 // Values are the FAST_ flags above.
497 bool getBit(uintptr_t bit
)
503 static uintptr_t updateFastAlloc(uintptr_t oldBits
, uintptr_t change
)
505 if (change
& FAST_ALLOC_MASK
) {
506 if (((oldBits
& FAST_ALLOC_MASK
) == FAST_ALLOC_VALUE
) &&
507 ((oldBits
>> FAST_SHIFTED_SIZE_SHIFT
) != 0))
509 oldBits
|= FAST_ALLOC
;
511 oldBits
&= ~FAST_ALLOC
;
517 static uintptr_t updateFastAlloc(uintptr_t oldBits
, uintptr_t change
) {
522 void setBits(uintptr_t set
)
527 oldBits
= LoadExclusive(&bits
);
528 newBits
= updateFastAlloc(oldBits
| set
, set
);
529 } while (!StoreReleaseExclusive(&bits
, oldBits
, newBits
));
532 void clearBits(uintptr_t clear
)
537 oldBits
= LoadExclusive(&bits
);
538 newBits
= updateFastAlloc(oldBits
& ~clear
, clear
);
539 } while (!StoreReleaseExclusive(&bits
, oldBits
, newBits
));
545 return (class_rw_t
*)(bits
& FAST_DATA_MASK
);
547 void setData(class_rw_t
*newData
)
549 assert(!data() || (newData
->flags
& (RW_REALIZING
| RW_FUTURE
)));
550 // Set during realization or construction only. No locking needed.
551 bits
= (bits
& ~FAST_DATA_MASK
) | (uintptr_t)newData
;
554 bool hasDefaultRR() {
555 return getBit(FAST_HAS_DEFAULT_RR
);
557 void setHasDefaultRR() {
558 setBits(FAST_HAS_DEFAULT_RR
);
560 void setHasCustomRR() {
561 clearBits(FAST_HAS_DEFAULT_RR
);
564 #if FAST_HAS_DEFAULT_AWZ
565 bool hasDefaultAWZ() {
566 return getBit(FAST_HAS_DEFAULT_AWZ
);
568 void setHasDefaultAWZ() {
569 setBits(FAST_HAS_DEFAULT_AWZ
);
571 void setHasCustomAWZ() {
572 clearBits(FAST_HAS_DEFAULT_AWZ
);
575 bool hasDefaultAWZ() {
576 return data()->flags
& RW_HAS_DEFAULT_AWZ
;
578 void setHasDefaultAWZ() {
579 data()->setFlags(RW_HAS_DEFAULT_AWZ
);
581 void setHasCustomAWZ() {
582 data()->clearFlags(RW_HAS_DEFAULT_AWZ
);
586 #if FAST_HAS_CXX_CTOR
588 return getBit(FAST_HAS_CXX_CTOR
);
590 void setHasCxxCtor() {
591 setBits(FAST_HAS_CXX_CTOR
);
595 return data()->flags
& RW_HAS_CXX_CTOR
;
597 void setHasCxxCtor() {
598 data()->setFlags(RW_HAS_CXX_CTOR
);
602 #if FAST_HAS_CXX_DTOR
604 return getBit(FAST_HAS_CXX_DTOR
);
606 void setHasCxxDtor() {
607 setBits(FAST_HAS_CXX_DTOR
);
611 return data()->flags
& RW_HAS_CXX_DTOR
;
613 void setHasCxxDtor() {
614 data()->setFlags(RW_HAS_CXX_DTOR
);
618 #if FAST_REQUIRES_RAW_ISA
619 bool requiresRawIsa() {
620 return getBit(FAST_REQUIRES_RAW_ISA
);
622 void setRequiresRawIsa() {
623 setBits(FAST_REQUIRES_RAW_ISA
);
626 # if SUPPORT_NONPOINTER_ISA
629 bool requiresRawIsa() {
632 void setRequiresRawIsa() {
638 size_t fastInstanceSize()
640 assert(bits
& FAST_ALLOC
);
641 return (bits
>> FAST_SHIFTED_SIZE_SHIFT
) * 16;
643 void setFastInstanceSize(size_t newSize
)
645 // Set during realization or construction only. No locking needed.
646 assert(data()->flags
& RW_REALIZING
);
648 // Round up to 16-byte boundary, then divide to get 16-byte units
649 newSize
= ((newSize
+ 15) & ~15) / 16;
651 uintptr_t newBits
= newSize
<< FAST_SHIFTED_SIZE_SHIFT
;
652 if ((newBits
>> FAST_SHIFTED_SIZE_SHIFT
) == newSize
) {
653 int shift
= WORD_BITS
- FAST_SHIFTED_SIZE_SHIFT
;
654 uintptr_t oldBits
= (bits
<< shift
) >> shift
;
655 if ((oldBits
& FAST_ALLOC_MASK
) == FAST_ALLOC_VALUE
) {
656 newBits
|= FAST_ALLOC
;
658 bits
= oldBits
| newBits
;
662 bool canAllocFast() {
663 return bits
& FAST_ALLOC
;
666 size_t fastInstanceSize() {
669 void setFastInstanceSize(size_t) {
672 bool canAllocFast() {
678 return getBit(FAST_IS_SWIFT
);
682 setBits(FAST_IS_SWIFT
);
687 struct objc_class
: objc_object
{
690 cache_t cache
; // formerly cache pointer and vtable
691 class_data_bits_t bits
; // class_rw_t * plus custom rr/alloc flags
696 void setData(class_rw_t
*newData
) {
697 bits
.setData(newData
);
700 void setInfo(uint32_t set
) {
701 assert(isFuture() || isRealized());
702 data()->setFlags(set
);
705 void clearInfo(uint32_t clear
) {
706 assert(isFuture() || isRealized());
707 data()->clearFlags(clear
);
710 // set and clear must not overlap
711 void changeInfo(uint32_t set
, uint32_t clear
) {
712 assert(isFuture() || isRealized());
713 assert((set
& clear
) == 0);
714 data()->changeFlags(set
, clear
);
718 return ! bits
.hasDefaultRR();
720 void setHasDefaultRR() {
721 assert(isInitializing());
722 bits
.setHasDefaultRR();
724 void setHasCustomRR(bool inherited
= false);
725 void printCustomRR(bool inherited
);
727 bool hasCustomAWZ() {
728 return ! bits
.hasDefaultAWZ();
730 void setHasDefaultAWZ() {
731 assert(isInitializing());
732 bits
.setHasDefaultAWZ();
734 void setHasCustomAWZ(bool inherited
= false);
735 void printCustomAWZ(bool inherited
);
737 bool requiresRawIsa() {
738 return bits
.requiresRawIsa();
740 void setRequiresRawIsa(bool inherited
= false);
741 void printRequiresRawIsa(bool inherited
);
743 bool canAllocIndexed() {
744 return !requiresRawIsa();
746 bool canAllocFast() {
747 return bits
.canAllocFast();
752 // addSubclass() propagates this flag from the superclass.
753 assert(isRealized());
754 return bits
.hasCxxCtor();
756 void setHasCxxCtor() {
757 bits
.setHasCxxCtor();
761 // addSubclass() propagates this flag from the superclass.
762 assert(isRealized());
763 return bits
.hasCxxDtor();
765 void setHasCxxDtor() {
766 bits
.setHasCxxDtor();
771 return bits
.isSwift();
775 #if SUPPORT_NONPOINTER_ISA
776 // Tracked in non-pointer isas; not tracked otherwise
778 bool instancesHaveAssociatedObjects() {
779 // this may be an unrealized future class in the CF-bridged case
780 assert(isFuture() || isRealized());
781 return data()->flags
& RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS
;
784 void setInstancesHaveAssociatedObjects() {
785 // this may be an unrealized future class in the CF-bridged case
786 assert(isFuture() || isRealized());
787 setInfo(RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS
);
791 bool shouldGrowCache() {
795 void setShouldGrowCache(bool) {
796 // fixme good or bad for memory use?
799 bool shouldFinalizeOnMainThread() {
800 // finishInitializing() propagates this flag from the superclass.
801 assert(isRealized());
802 return data()->flags
& RW_FINALIZE_ON_MAIN_THREAD
;
805 void setShouldFinalizeOnMainThread() {
806 assert(isRealized());
807 setInfo(RW_FINALIZE_ON_MAIN_THREAD
);
810 bool isInitializing() {
811 return getMeta()->data()->flags
& RW_INITIALIZING
;
814 void setInitializing() {
815 assert(!isMetaClass());
816 ISA()->setInfo(RW_INITIALIZING
);
819 bool isInitialized() {
820 return getMeta()->data()->flags
& RW_INITIALIZED
;
823 void setInitialized();
826 assert(isRealized());
827 return true; // any class registered for +load is definitely loadable
832 // Locking: To prevent concurrent realization, hold runtimeLock.
834 return data()->flags
& RW_REALIZED
;
837 // Returns true if this is an unrealized future class.
838 // Locking: To prevent concurrent realization, hold runtimeLock.
840 return data()->flags
& RW_FUTURE
;
845 assert(isRealized());
846 return data()->ro
->flags
& RO_META
;
849 // NOT identical to this->ISA when this is a metaclass
851 if (isMetaClass()) return (Class
)this;
852 else return this->ISA();
856 return superclass
== nil
;
858 bool isRootMetaclass() {
859 return ISA() == (Class
)this;
862 const char *mangledName() {
863 // fixme can't assert locks here
866 if (isRealized() || isFuture()) {
867 return data()->ro
->name
;
869 return ((const class_ro_t
*)data())->name
;
873 const char *demangledName(bool realize
= false);
874 const char *nameForLogging();
876 // May be unaligned depending on class's ivars.
877 uint32_t unalignedInstanceSize() {
878 assert(isRealized());
879 return data()->ro
->instanceSize
;
882 // Class's ivar size rounded up to a pointer-size boundary.
883 uint32_t alignedInstanceSize() {
884 return word_align(unalignedInstanceSize());
887 size_t instanceSize(size_t extraBytes
) {
888 size_t size
= alignedInstanceSize() + extraBytes
;
889 // CF requires all objects be at least 16 bytes.
890 if (size
< 16) size
= 16;
894 void setInstanceSize(uint32_t newSize
) {
895 assert(isRealized());
896 if (newSize
!= data()->ro
->instanceSize
) {
897 assert(data()->flags
& RW_COPIED_RO
);
898 *const_cast<uint32_t *>(&data()->ro
->instanceSize
) = newSize
;
900 bits
.setFastInstanceSize(newSize
);
905 struct swift_class_t
: objc_class
{
907 uint32_t instanceAddressOffset
;
908 uint32_t instanceSize
;
909 uint16_t instanceAlignMask
;
913 uint32_t classAddressOffset
;
917 void *baseAddress() {
918 return (void *)((uint8_t *)this - classAddressOffset
);
926 struct method_list_t
*instanceMethods
;
927 struct method_list_t
*classMethods
;
928 struct protocol_list_t
*protocols
;
929 struct property_list_t
*instanceProperties
;
937 struct message_ref_t
{
943 extern Method
protocol_getMethod(protocol_t
*p
, SEL sel
, bool isRequiredMethod
, bool isInstanceMethod
, bool recursive
);
946 foreach_realized_class_and_subclass_2(Class top
, bool (^code
)(Class
))
948 // rwlock_assert_writing(&runtimeLock);
952 if (!code(cls
)) break;
954 if (cls
->data()->firstSubclass
) {
955 cls
= cls
->data()->firstSubclass
;
957 while (!cls
->data()->nextSiblingClass
&& cls
!= top
) {
958 cls
= cls
->superclass
;
960 if (cls
== top
) break;
961 cls
= cls
->data()->nextSiblingClass
;
967 foreach_realized_class_and_subclass(Class top
, void (^code
)(Class
))
969 foreach_realized_class_and_subclass_2(top
, ^bool(Class cls
) {
970 code(cls
); return true;