Swift实例对象内存结构 - ShenYj/ShenYj.github.io GitHub Wiki
Swift 对象结构本质也是一个结构体 HeapObject
-
HeapObject.h
源码中关于HeapObject
结构体的定义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/c++
的代码最多的就是这种类型定义和别名,我是跳来跳去翻了好久-
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS
到底是个啥-
首先得知存在一个
InlineRefCounts refCounts
类型的成员变量#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS InlineRefCounts refCounts
-
InlineRefCounts
又是个别名typedef RefCounts<InlineRefCountBits> InlineRefCounts;
目前掌握的信息:
-
RefCounts
是个模板类, 运行期取决RefCountBits
的一个类型参数,从上一步得知,这个模板参数类型为InlineRefCountBits
template <typename RefCountBits> class RefCounts { std::atomic<RefCountBits> refCounts; ... }
-
而这里的
InlineRefCountBits
又是个别名typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;
其实这里还有一处定义
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
再网上查询到的资料描述是: 模板参数 RefCountBits 指定了真实的内部类型,在 Swift ABI 里总共有两种:前者是用在 HeapObject 中的,而后者是用在 HeapObjectSideTableEntry(Side Table)中的一般来讲,Swift 对象并不会用到 Side Table,一旦对象被 weak 或 unowned 引用,该对象就会分配一个 Side Table。-
RefCountIsInline
是一个enum
类型// RefCountIsInline: refcount stored in an object // RefCountNotInline: refcount stored in an object's side table entry enum RefCountInlinedness { RefCountNotInline = false, RefCountIsInline = true };
-
RefCountBitsT
是个模板类, 并且有个关键的成员变量bits
(省略其他代码)class RefCountBitsT { typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::Type BitsType; BitsType bits; ... }
-
根据
BitsType
别名的定义: 将RefCountBitsInt
这个结构体中的Type
起别名为BitsType
// 64-bit inline // 64-bit out of line template <RefCountInlinedness refcountIsInline> struct RefCountBitsInt<refcountIsInline, 8> { typedef uint64_t Type; typedef int64_t SignedType; };
-
最终得到这个
bits
类型就是uint64_t
-
-
包含两个成员
-
HeapMetadata const *metadata;
8字节 (等同于OC里面的类对象) -
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
8字节 (引用计数)
两个指针类型,初始默认大小: 16
字节
class Person {
var age: Int = 1 // 8 字节
var name: String = "abc" // 16 字节, Swift 中 String 也是结构体类型
}
print(MemoryLayout<Int>.size) -> 8
print(MemoryLayout<String>.size) -> 16
- HeapObject (metadata 8字节 (等同于OC里面的类对象), reCount 8字节 (引用计数)) 默认16字节大小
- 加上两个属性, 占用内存大小: 8 + 8 + 8 + 16 => 40字节
Swift | Object-C | |
---|---|---|
底层 | objc_class -> objc_object | HeapObject |
Size大小 | metadata, refCounts 大于16字节 | isa,superclass,cache,bits 大于32字节 |
这里的大小是两根指针的占用空间, 在探究Swift的
MetaData
继承关系后可见 Swift的内存结构设计了很多的成员变量, 比如从TargetClassMetadata
中继承了大部分的成员变量