结构
相关的结构体
以下结构体是Any的实现会涉及到的,大部分都是Swift的源码中简化过来的
struct Any { // 没有找到源码中的声明,主要从编译产物中翻译过来
int8_t data[24]; // 用于存储对象数据
Metadata *meta; // 记录对象的类型
}
struct HeapObject { // 类似于Objective-C的实例对象
Metadata* metadata;
// uint_t refCounts; // swift对象的引用计数等
}
struct Metadata { // 类似于Objective-C的类
int64_t kind;
// 不通类型会有不同的数据段,此次省略
}
struct ValueWitnessTable {
uintptr_t initializeBufferWithCopyOfBuffer;
uintptr_t destroy;
uintptr_t initializeWithCopy;
uintptr_t assignWithCopy;
uintptr_t initializeWithTake;
uintptr_t assignWithTake;
uintptr_t getEnumTagSinglePayload;
uintptr_t storeEnumTagSinglePayload;
int_t size;
int_t stride;
uint32_t flags;
uint32_t extraInhabitantCount;
uint_t getEnumTag;
uintptr_t destructiveProjectEnumData;
uintptr_t destructiveInjectEnumTag;
}
内存布局
Any对象是由24个字节和一个Metadata的指针组成。简化后如下显示
存储
Any对象的24个字节,可能存储如下两种数据:
- 直接存储对象数据,如大小较小的Struct对象
- 使用8个字节(64位),存储一个HeapObject的指针(Swift的引用对象)
赋值
针对不同类型的数据,Any对象的赋值有如下几种:
Struct / Enum
- 小于等于 24字节
- 存储目标的Metadata对象
- 直接对象数据
- 大于 24字节
- 存储目标的Metadata对象
- 调用
swift_allocObject创建HeapObject对象 - 存储HeapObject的指针
Class
- 存储目标的Metadata对象
- 调用
swift_retain增加引用计数 - 存储HeapObject的指针
Any
赋值Any对象时,通过copy函数$sypWOc(编译器生成的Any对象的Copy函数)。
$sypWOc主要执行以下操作:
- 复制Metadata对象
- 读取ValueWitnessTable对象(Any -> Metadata -> ValueWitnessTable)
- 通过ValueWitnessTable对象的initializeBufferWithCopyOfBuffer函数,复制数据
销毁
编译器会生成Any对象的destroy函数(__swift_destroy_boxed_opaque_existential_0),主要执行以下操作:
- 读取ValueWitnessTable对象(Any -> Metadata -> ValueWitnessTable)
- 通过ValueWitnessTable对象的flags,做位判断(IsNonInline = 0x0002000)
- 如果是inline(即结果为0),调用ValueWitnessTable对象的
destroy进行销毁;否则,调用swift_release,减少引用计数