在 Swift 中,類對(duì)象的結(jié)構(gòu)是否和 Objective-C 一樣呢?
SwiftObject
在swift中,如果沒有明確聲明父類的類,則會(huì)隱式地繼承自 SwiftObject (支持與 Objective-C 混編的前提下,因?yàn)?SwiftObject 是一個(gè) Objective-C 類),隱式繼承來源于 swift 的 ABI/TypeLayout.rst 文檔。
關(guān)于 SwiftObject 的定義如下:
#if SWIFT_OBJC_INTEROP
#if __OBJC__
// Source code: "SwiftObject"
// Real class name: mangled "Swift._SwiftObject"
#define SwiftObject _TtCs12_SwiftObject
#if __has_attribute(objc_root_class)
__attribute__((__objc_root_class__))
#endif
SWIFT_RUNTIME_EXPORT @interface SwiftObject<NSObject> {
@private
Class isa;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
}
...
@end
namespace swift {
id getDescription(OpaqueValue *value, const Metadata *type);
}
#endif
#endif
namespace swift {
/// Get the NSObject metadata.
const Metadata *getNSObjectMetadata();
}
#endif
SwiftObject 的聲明是 SWIFT_OBJC_INTEROP 為 true 的情況下才有聲明的,而在蘋果平臺(tái)下,都是支持 swift 與 Objective-C 進(jìn)行混編的,因此 SWIFT_OBJC_INTEROP 為 1(true),SWIFT_OBJC_INTEROP 宏的定義可在 Config.h 中找到
/// Does the current Swift platform support "unbridged" interoperation
/// with Objective-C? If so, the implementations of various types must
/// implicitly handle Objective-C pointers.
///
/// Apple platforms support this by default.
#ifndef SWIFT_OBJC_INTEROP
#ifdef __APPLE__
#define SWIFT_OBJC_INTEROP 1
#else
#define SWIFT_OBJC_INTEROP 0
#endif
#endif
從 SwiftObject 的定義中可以看到
- 第一個(gè)成員變量和 Objective-C 一樣是
isa指針,暫時(shí)猜想和 Objective-C 中的isa指針功能一樣 - 第二個(gè)成員變量是一個(gè)
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS宏,其定義可在 HeapObject.h 和 RefCount.h 中找到,從命名上看是引用計(jì)數(shù)器
// RefCount.h
// This definition is a placeholder for importing into Swift.
// It provides size and alignment but cannot be manipulated safely there.
typedef struct {
__swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
} InlineRefCountsPlaceholder;
#if defined(__swift__)
typedef InlineRefCountsPlaceholder InlineRefCounts;
#else
// HeapObject.h
namespace swift {
struct InProcess;
template <typename Target> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;
#else
typedef struct HeapMetadata HeapMetadata;
typedef struct HeapObject HeapObject;
#endif
// The members of the HeapObject header that are not shared by a
// standard Objective-C instance
#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
InlineRefCounts refCounts
/// The Swift heap-object header.
/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
#ifndef __swift__
HeapObject() = default;
// Initialize a HeapObject header as appropriate for a newly-allocated object.
constexpr HeapObject(HeapMetadata const *newMetadata)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Initialized)
{ }
// Initialize a HeapObject header for an immortal object
constexpr HeapObject(HeapMetadata const *newMetadata,
InlineRefCounts::Immortal_t immortal)
: metadata(newMetadata)
, refCounts(InlineRefCounts::Immortal)
{ }
#ifndef NDEBUG
void dump() const LLVM_ATTRIBUTE_USED;
#endif
#endif // __swift__
};
在下文的所有測(cè)試代碼中,均使用自定義 Person 類
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func printData() {
print("name=\(name), age=\(age)")
}
}
驗(yàn)證父類
下面通過2種方式來驗(yàn)證在 swift 中,沒有明確聲明父類的類,會(huì)隱式繼承 SwiftObject 類
- Objective-C runtime
print(class_getSuperclass(Person.self))
打印結(jié)果為:
Optional(_TtCs12_SwiftObject)
- MachO文件

_$s11ClassStruct6PersonCN 這個(gè)結(jié)構(gòu)體可以理解為 Person 類的類對(duì)象,其 superclass 指針指向 _TtCs12_SwiftObject
_TtCs12_SwiftObject 是 SwiftObject 的真實(shí)類名,可在 SwiftObject.h 的文檔中找到相關(guān)的描述:
// Source code: "SwiftObject"
// Real class name: mangled "Swift._SwiftObject"
#define SwiftObject _TtCs12_SwiftObject
HeapObject
在 swift 中,基本上分配在堆上的對(duì)象都是一個(gè) HeapObject。其定義可在 HeapObject.h 中找到:
// The members of the HeapObject header that are not shared by a
// standard Objective-C instance
#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
InlineRefCounts refCounts
/// The Swift heap-object header.
/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
...
};
metadata 是指向類結(jié)構(gòu) HeapMetadata 的指針,refCounts 所包含的信息比較多,使用了掩碼,其中包含了引用計(jì)數(shù)。
因此 Person 的實(shí)例對(duì)象的成員變量是在偏移量為16個(gè)字節(jié)開始,前16個(gè)字節(jié)分別存放 metadata 的指針和 refCounts 的引用計(jì)數(shù),Person 的實(shí)例對(duì)象對(duì)應(yīng)的內(nèi)存結(jié)構(gòu)可以對(duì)應(yīng)如下的結(jié)構(gòu)體:
struct PersonStruct {
// 指向類對(duì)象的指針
let metaData: UnsafePointer
let refCounts: __uint64_t
var name: String
let age: Int
}
定義一個(gè)簡(jiǎn)單的 person 實(shí)例對(duì)象,并定義一個(gè)結(jié)構(gòu)體 personStruct 指向 person 內(nèi)存,并修改 personStruct 結(jié)構(gòu)體的 name 屬性和 age 屬性,看 person 對(duì)象的屬性是否有對(duì)應(yīng)的修改
var person = Person(name: "swift", age: 6)
// 將指向person對(duì)象內(nèi)存地址的指針轉(zhuǎn)成指向PersonStruct結(jié)構(gòu)體的指針,實(shí)則還是指向同一個(gè)內(nèi)存地址
var pStructPointer = Unmanaged.passUnretained(person).toOpaque().bindMemory(to: PersonStruct.self, capacity: personSize)
print(pStructPointer)
pStructPointer.pointee.name = "struct"
pStructPointer.pointee.age = 1
person.printData()
// 打印結(jié)果為:name=struct, age=1
這里需要注意的是,不能把指向 person 實(shí)例對(duì)象內(nèi)存地址的指針轉(zhuǎn)成 PersonStruct 結(jié)構(gòu)體,再修改結(jié)構(gòu)體的屬性值。
var pStruct = Unmanaged.passUnretained(person).toOpaque().bindMemory(to: PersonStruct.self, capacity: personSize).pointee
這種寫法是不會(huì)改變 person 對(duì)象的屬性,因?yàn)榻Y(jié)構(gòu)體是值類型,相當(dāng)于把 person 內(nèi)存的值都拷貝了一份
HeapMetadata
HeapMetadata 可理解為 Objective-C 中的類對(duì)象和元類對(duì)象,其對(duì)應(yīng)的結(jié)構(gòu)可在 Metadata.h 中找到
/// In-process native runtime target.
///
/// For interactions in the runtime, this should be the equivalent of working
/// with a plain old pointer type.
struct InProcess {
static constexpr size_t PointerSize = sizeof(uintptr_t);
using StoredPointer = uintptr_t;
using StoredSignedPointer = uintptr_t;
using StoredSize = size_t;
using StoredPointerDifference = ptrdiff_t;
static_assert(sizeof(StoredSize) == sizeof(StoredPointerDifference),
"target uses differently-sized size_t and ptrdiff_t");
template <typename T>
using Pointer = T*;
template <typename T>
using SignedPointer = T;
...
};
/// The common structure of all type metadata.
template <typename Runtime>
struct TargetMetadata {
using StoredPointer = typename Runtime::StoredPointer;
/// The basic header type.
typedef TargetTypeMetadataHeader<Runtime> HeaderType;
...
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
/// the kind value.
StoredPointer Kind;
public:
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
/// Set the metadata kind.
void setKind(MetadataKind kind) {
Kind = static_cast<StoredPointer>(kind);
}
#if SWIFT_OBJC_INTEROP
protected:
const TargetAnyClassMetadata<Runtime> *getClassISA() const {
return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
}
void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
Kind = reinterpret_cast<StoredPointer>(isa);
}
#endif
public:
/// Is this a class object--the metadata record for a Swift class (which also
/// serves as the class object), or the class object for an ObjC class (which
/// is not metadata)?
bool isClassObject() const {
return static_cast<MetadataKind>(getKind()) == MetadataKind::Class;
}
...
};
/// The common structure of all metadata for heap-allocated types. A
/// pointer to one of these can be retrieved by loading the 'isa'
/// field of any heap object, whether it was managed by Swift or by
/// Objective-C. However, when loading from an Objective-C object,
/// this metadata may not have the heap-metadata header, and it may
/// not be the Swift type metadata for the object's dynamic type.
template <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
using HeaderType = TargetHeapMetadataHeader<Runtime>;
TargetHeapMetadata() = default;
constexpr TargetHeapMetadata(MetadataKind kind)
: TargetMetadata<Runtime>(kind) {}
#if SWIFT_OBJC_INTEROP
constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
: TargetMetadata<Runtime>(isa) {}
#endif
};
using HeapMetadata = TargetHeapMetadata<InProcess>;
上面看起來可能還是有點(diǎn)亂,可以看看下面只保留成員變量的結(jié)構(gòu)體
struct TargetMetadata {
uintptr_t Kind;
}
struct TargetHeapMetadata : TargetMetadata<Runtime> {
};
這么一看,結(jié)構(gòu)體中只有一個(gè)成員變量 Kind,其實(shí) Kind 屬性為 MetadataKind 類型,記錄著此 metadata 的實(shí)際類型,其定義在 MetadataValues.h & MetadataKind.def 中能找到:
/// Non-type metadata kinds have this bit set.
const unsigned MetadataKindIsNonType = 0x400;
/// Non-heap metadata kinds have this bit set.
const unsigned MetadataKindIsNonHeap = 0x200;
// The above two flags are negative because the "class" kind has to be zero,
// and class metadata is both type and heap metadata.
/// Runtime-private metadata has this bit set. The compiler must not statically
/// generate metadata objects with these kinds, and external tools should not
/// rely on the stability of these values or the precise binary layout of
/// their associated data structures.
const unsigned MetadataKindIsRuntimePrivate = 0x100;
/// Kinds of Swift metadata records. Some of these are types, some
/// aren't.
enum class MetadataKind : uint32_t {
#define METADATAKIND(name, value) name = value,
#define ABSTRACTMETADATAKIND(name, start, end) \
name##_Start = start, name##_End = end,
#include "MetadataKind.def"
/// ABSTRACTMETADATAKIND(Name, Start, End)
/// Represents an abstraction categorization of a range of metadata kind
/// values. Name is the identifier of the range and Start, End are the
/// beginning and end of the range.
#ifndef ABSTRACTMETADATAKIND
#define ABSTRACTMETADATAKIND(Name, Start, End)
#endif
/// NOMINALTYPEMETADATAKIND(Name, Value)
/// Represents the native metadata kind for a swift nominal type. Name is the
/// name of the kind and Value is the integral value used to identify the
/// value. Delegates to METADATAKIND if not defined.
#ifndef NOMINALTYPEMETADATAKIND
#define NOMINALTYPEMETADATAKIND(Name, Value) METADATAKIND(Name, Value)
#endif
/// A class type.
NOMINALTYPEMETADATAKIND(Class, 0)
/// A struct type.
NOMINALTYPEMETADATAKIND(Struct, 0 | MetadataKindIsNonHeap)
/// An enum type.
/// If we add reference enums, that needs to go here.
NOMINALTYPEMETADATAKIND(Enum, 1 | MetadataKindIsNonHeap)
/// An optional type.
NOMINALTYPEMETADATAKIND(Optional, 2 | MetadataKindIsNonHeap)
/// A foreign class, such as a Core Foundation class.
METADATAKIND(ForeignClass, 3 | MetadataKindIsNonHeap)
/// A type whose value is not exposed in the metadata system.
METADATAKIND(Opaque, 0 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// A tuple.
METADATAKIND(Tuple, 1 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// A monomorphic function.
METADATAKIND(Function, 2 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// An existential type.
METADATAKIND(Existential, 3 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// A metatype.
METADATAKIND(Metatype, 4 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// An ObjC class wrapper.
METADATAKIND(ObjCClassWrapper, 5 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// An existential metatype.
METADATAKIND(ExistentialMetatype, 6 | MetadataKindIsRuntimePrivate | MetadataKindIsNonHeap)
/// A heap-allocated local variable using statically-generated metadata.
METADATAKIND(HeapLocalVariable, 0 | MetadataKindIsNonType)
/// A heap-allocated local variable using runtime-instantiated metadata.
METADATAKIND(HeapGenericLocalVariable,
0 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate)
/// A native error object.
METADATAKIND(ErrorObject,
1 | MetadataKindIsNonType | MetadataKindIsRuntimePrivate)
LastEnumerated = 0x7FF,
};
可能不太好看,MetadataKind 是枚舉類型,其值如下表格:
| name | Value |
|---|---|
| Class | 0x0 |
| Struct | 0x200 |
| Enum | 0x201 |
| Optional | 0x202 |
| ForeignClass | 0x203 |
| Opaque | 0x300 |
| Tuple | 0x301 |
| Function | 0x302 |
| Existential | 0x303 |
| Metatype | 0x304 |
| ObjCClassWrapper | 0x305 |
| ExistentialMetatype | 0x306 |
| HeapLocalVariable | 0x400 |
| HeapGenericLocalVariable | 0x500 |
| ErrorObject | 0x501 |
| LastEnumerated | 0x7FF |
在 TargetMetadata 結(jié)構(gòu)體中有個(gè)函數(shù)可以獲取其類型
struct TargetMetadata {
...
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
/// the kind value.
StoredPointer Kind;
public:
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
/// Set the metadata kind.
void setKind(MetadataKind kind) {
Kind = static_cast<StoredPointer>(kind);
}
...
}
/// Try to translate the 'isa' value of a type/heap metadata into a value
/// of the MetadataKind enum.
inline MetadataKind getEnumeratedMetadataKind(uint64_t kind) {
if (kind > LastEnumeratedMetadataKind)
return MetadataKind::Class;
return MetadataKind(kind);
}
如果 kind 大于 0x7FF 的話,都為 MetadataKind::Class 類型。下面可以看看 Person 類的 Kind 值
print(String(format: "0x%02lx", Unmanaged.passUnretained(person).toOpaque().load(as: __uint64_t.self)))
// 打印結(jié)果:0x1000092d8
也可以通過 LLDB 來獲取其值:

因此 getEnumeratedMetadataKind(uint64_t kind) 返回 MetadataKind::Class
/// Get the nominal type descriptor if this metadata describes a nominal type,
/// or return null if it does not.
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>
getTypeContextDescriptor() const {
switch (getKind()) {
case MetadataKind::Class: {
const auto cls = static_cast<const TargetClassMetadata<Runtime> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
}
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
return static_cast<const TargetValueMetadata<Runtime> *>(this)
->Description;
case MetadataKind::ForeignClass:
return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)
->Description;
default:
return nullptr;
}
}
在函數(shù) getTypeContextDescriptor() 中可以看到,如果 Kind 類型為 MetadataKind::Class 的話,可以轉(zhuǎn)成 TargetClassMetadata 結(jié)構(gòu)體
/// The structure of all class metadata. This structure is embedded
/// directly within the class's heap metadata structure and therefore
/// cannot be extended without an ABI break.
///
/// Note that the layout of this type is compatible with the layout of
/// an Objective-C class.
template <typename Runtime>
struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
// The remaining fields are valid only when isTypeMetadata().
// The Objective-C runtime knows the offsets to some of these fields.
// Be careful when accessing them.
/// Swift-specific class flags.
ClassFlags Flags;
/// The address point of instances of this type.
uint32_t InstanceAddressPoint;
/// The required size of instances of this type.
/// 'InstanceAddressPoint' bytes go before the address point;
/// 'InstanceSize - InstanceAddressPoint' bytes go after it.
uint32_t InstanceSize;
/// The alignment mask of the address point of instances of this type.
uint16_t InstanceAlignMask;
/// Reserved for runtime use.
uint16_t Reserved;
/// The total size of the class object, including prefix and suffix
/// extents.
uint32_t ClassSize;
/// The offset of the address point within the class object.
uint32_t ClassAddressPoint;
// Description is by far the most likely field for a client to try
// to access directly, so we force access to go through accessors.
private:
/// An out-of-line Swift-specific description of the type, or null
/// if this is an artificial subclass. We currently provide no
/// supported mechanism for making a non-artificial subclass
/// dynamically.
TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
public:
/// A function for destroying instance variables, used to clean up after an
/// early return from a constructor. If null, no clean up will be performed
/// and all ivars must be trivial.
TargetSignedPointer<Runtime, ClassIVarDestroyer * __ptrauth_swift_heap_object_destructor> IVarDestroyer;
...
};
using ClassMetadata = TargetClassMetadata<InProcess>;
/// The portion of a class metadata object that is compatible with
/// all classes, even non-Swift ones.
template <typename Runtime>
struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
#if SWIFT_OBJC_INTEROP
// Allow setting the metadata kind to a class ISA on class metadata.
using TargetMetadata<Runtime>::getClassISA;
using TargetMetadata<Runtime>::setClassISA;
#endif
// Note that ObjC classes does not have a metadata header.
/// The metadata for the superclass. This is null for the root class.
ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> Superclass;
// TODO: remove the CacheData and Data fields in non-ObjC-interop builds.
/// The cache data is used for certain dynamic lookups; it is owned
/// by the runtime and generally needs to interoperate with
/// Objective-C's use.
TargetPointer<Runtime, void> CacheData[2];
/// The data pointer is used for out-of-line metadata and is
/// generally opaque, except that the compiler sets the low bit in
/// order to indicate that this is a Swift metatype and therefore
/// that the type metadata header is present.
StoredSize Data;
};
using AnyClassMetadata =
TargetAnyClassMetadata<InProcess>;
接下來通過驗(yàn)證一下,可以定義如下 C++ 結(jié)構(gòu)體:
struct TargetAnyClassMetadata {
struct TargetAnyClassMetadata* Kind;
void* superClass;
void* CacheData[2];
void* Data;
};
struct TargetClassMetadata {
uintptr_t Kind;
struct AnyClassHeapMetadata* superClass;
void* CacheData[2];
void* Data;
uint32_t Flags;
uint32_t InstanceAddressPoint;
uint32_t InstanceSize;
uint16_t InstanceAlignMask;
uint16_t Reserved;
uint32_t ClassSize;
uint32_t ClassAddressPoint;
uintptr_t Description;
uintptr_t IVarDestroyer;
};
打印 TargetClassMetadata 中的 InstanceSize 的值,即為 Person 類創(chuàng)建的實(shí)例對(duì)象所占的內(nèi)存大小
let personMetaData = pStructPointer.pointee.metaData.bindMemory(to: TargetClassMetadata.self, capacity: MemoryLayout<TargetClassMetadata>.stride).pointee
print(personMetaData.InstanceSize)
// 打印結(jié)果為:40
在 Person 中,name 屬性占用16字節(jié),age 屬性占用8字節(jié),隱式繼承的 SwiftObject 的成員變量 metadata 指針和 refCounts 分別都占用 8字節(jié),加起來總共占用40個(gè)字節(jié)用于存放成員變量,但由于內(nèi)存對(duì)齊,實(shí)際分配的內(nèi)存為48字節(jié)
print("person對(duì)象占用的內(nèi)存大小: \(malloc_size(pPointer))")
// 打印結(jié)果為:person對(duì)象占用的內(nèi)存大小: 48
我們可以繼續(xù)獲取其 Kind 值所指向的“元類對(duì)象”,可理解為 Objective-C 中的元類對(duì)象。下面可以打印 Person 的類對(duì)象和元類對(duì)象的地址:
/// 類對(duì)象地址指針
let clsAddress = pStructPointer.pointee.metaData
/// Person元類對(duì)象地址
let metaAddress = String(format: "0x%02lx", personMetaData.Kind)
print("Person類對(duì)象地址: \(clsAddress)")
print("Person元類對(duì)象地址: \(metaAddress)")
打印結(jié)果為:
Person類對(duì)象地址: 0x10000a2d8
Person元類對(duì)象地址: 0x10000a2a0
使用 Hopper Disassembler 查看MachO 文件

??:不能通過 Objective-C 的運(yùn)行時(shí)來獲取 Swift 類的類對(duì)象和元類對(duì)象,通過
objc_getClass()和objc_getMetaClass()這些 Objective-C 運(yùn)行時(shí)runtime方法獲取到的類對(duì)象和元類對(duì)象是動(dòng)態(tài)創(chuàng)建出來的,不可取
RefCount 引用計(jì)數(shù)
實(shí)例對(duì)象的第二個(gè)成員變量 refCounts 從名字上看是存放引用計(jì)數(shù),但并不是直接存放的,而且采用了掩碼進(jìn)行存放,類似于 Objective-C 中的 isa 指針,其定義可在 RefCount.h 中找到
// 64-bit inline
// 64-bit out of line
// 32-bit out of line
template <>
struct RefCountBitOffsets<8> {
/*
The bottom 32 bits (on 64 bit architectures, fewer on 32 bit) of the refcount
field are effectively a union of two different configurations:
---Normal case---
Bit 0: Does this object need to call out to the ObjC runtime for deallocation
Bits 1-31: Unowned refcount
---Immortal case---
All bits set, the object does not deallocate or have a refcount
*/
static const size_t PureSwiftDeallocShift = 0;
static const size_t PureSwiftDeallocBitCount = 1;
static const uint64_t PureSwiftDeallocMask = maskForField(PureSwiftDealloc);
static const size_t UnownedRefCountShift = shiftAfterField(PureSwiftDealloc);
static const size_t UnownedRefCountBitCount = 31;
static const uint64_t UnownedRefCountMask = maskForField(UnownedRefCount);
static const size_t IsImmortalShift = 0; // overlaps PureSwiftDealloc and UnownedRefCount
static const size_t IsImmortalBitCount = 32;
static const uint64_t IsImmortalMask = maskForField(IsImmortal);
static const size_t IsDeinitingShift = shiftAfterField(UnownedRefCount);
static const size_t IsDeinitingBitCount = 1;
static const uint64_t IsDeinitingMask = maskForField(IsDeiniting);
static const size_t StrongExtraRefCountShift = shiftAfterField(IsDeiniting);
static const size_t StrongExtraRefCountBitCount = 30;
static const uint64_t StrongExtraRefCountMask = maskForField(StrongExtraRefCount);
static const size_t UseSlowRCShift = shiftAfterField(StrongExtraRefCount);
static const size_t UseSlowRCBitCount = 1;
static const uint64_t UseSlowRCMask = maskForField(UseSlowRC);
static const size_t SideTableShift = 0;
static const size_t SideTableBitCount = 62;
static const uint64_t SideTableMask = maskForField(SideTable);
static const size_t SideTableUnusedLowBits = 3;
static const size_t SideTableMarkShift = SideTableBitCount;
static const size_t SideTableMarkBitCount = 1;
static const uint64_t SideTableMarkMask = maskForField(SideTableMark);
};
typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;
template <typename RefCountBits>
class RefCounts {
std::atomic<RefCountBits> refCounts;
...
};
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
掩碼對(duì)應(yīng)的值如下表所示:
| 掩碼名稱 | 掩碼起始位置 | 位數(shù) |
|---|---|---|
| PureSwiftDeallocShift | 0x1UL<<0 | 1 |
| UnownedRefCountShift | 0x1UL<<1 | 31 |
| IsImmortalShift | 0x1UL<<0 | 32 |
| IsDeinitingShift | 0x1UL<<32 | 1 |
| StrongExtraRefCountShift | 0x1UL<<33 | 30 |
| UseSlowRCShift | 0x1UL<<63 | 1 |
| SideTableShift | 0x1UL<<0 | 62 |
| SideTableMarkShift | 0x1UL<<62 | 1 |

通過代碼驗(yàn)證一下 UnownedRefCountShift 和 StrongExtraRefCountShift
let p1 = Person(name: "swift", age: 6)
let p2 = p1
let p3 = p1
unowned let p4 = p1
unowned let p5 = p1
上面有3個(gè)強(qiáng)引用,2個(gè)無主引用(總數(shù)為2+1,初始值為1),接下來獲取 p1 對(duì)象的 refCounts 值:

0x0000000600000006 中對(duì)應(yīng)強(qiáng)引用計(jì)數(shù) StrongExtraRefCountShift 的值為 0x3,對(duì)應(yīng)無主引用計(jì)數(shù) UnownedRefCountShift 的值為0x3
若對(duì)象存在弱引用,其弱引用計(jì)數(shù)在 sidetable 中的
weak var p6 = p1

其值已發(fā)生改變,SideTableMarkShift 標(biāo)志位為 1。
Person 內(nèi)存圖解
我自己畫了一幅圖來描述 Person 的內(nèi)存結(jié)構(gòu):

??:
Person元類對(duì)象不是TargetClassMetadata類型的,Person類對(duì)象才是