SIL
SIL(Swift Intermediate Language) ,不管是用OC开发还是Swift开发,后端都是通过llvm进行编译的.
OC 是通过Clang编译器编译成IR 再生成.0
Swift是通过Swift编译器编译成IR,再生成可执行文件
SIL 文件分析
Swift在编译过程中使用的前端编译器是swiftc 可通过 swiftc -h 来查看命令
用以下命令生成sil文件并打开它
swiftc -emit-sil main.swift >> ./main.sil && open main.sil
再查找allocating_init方法
分析源码
在控制台输入XCode中的代码,已知会调用一个swift_allocObject函数,搜索找到后打断点
从上图中可以看到返回值是
HeapObject,HeapObject是一个结构体,创建出来的实例变量在内存中的存储结构就是HeapObject,这个结构体中包含
metadata
requiredSize
requiredAlignmentMask(对齐,在分配空间时按照以空间节省时间的方式,按8的倍数来补齐,可以快速的找到对应的内存空间)
进入到HeapObject的初始化函数中查看
refCounts(InlineRefCounts::Immortal)是引用计数,swift是采用arc来进行引用计数的,refCounts是一个类占8个字节, metadata(newMetadata) 是指针类型,占8个字节, 再加上int age 8字节, name string的16字节 共40字节,这就是实例对象在内存中存储的结构。
类结构
在上面的HeapObject介绍中看到其中包含一个metadata,查看它
using HeapMetadata = TargetHeapMetadata<InProcess>;
这句表示HeapMetadata是TargetHeapMetadata的别名, 查看TargetHeapMetadata
TargetHeapMetadata继承TargetMetadata 这里有一个初始化方法,点开查看MetadataKind
这里又引入了一个
#include "MetadataKind.def"文件,打开查看
这里记录着所有源数据类型,也就是说在
TargetHeapMetadata的初始化方法中出现的MetadataKing king是一个代表着源数据类型的一个参数
回到TargetHeapMetadata中点开查他的父类TargetMetadata, 其中又一个方法
点开查看
这个方法是用来匹配我们的源类型,如果匹配成功,把我们当前的
metadata强转成ClassMetadata, 用lldb查看下
类的总结:
如果metadatade的枚举值是class 那他的就返回的是TargetClassMetadata,之后又继承自TargetAnyClassMetadata,再继承子TargetHeapMetadata再继承自TargetMetadata
组合到一块
struct swift_class_t: NSObject{
void *kind; //isa, kind(unsigned long) //如果要与oc交互,kind就可以看成是isa 如果是纯swift它就是kind
void *superClass;
void *cacheData
void *data
uint32_t flags; //4
uint32_t instanceAddressOffset; //4
uint32_t instanceSize;//4
uint16_t instanceAlignMask; //2
uint16_t reserved; //2
uint32_t classSize; //4
uint32_t classAddressOffset; //4
void *description;
// ...
};
属性
存储属性
是要占用堆空间的内存
计算属性
计算属性不占用内存空间
Metadata(8) + RefCounts(8) + width(8) = 24
so属性area就没有占用空间,从SIL查看下
area也只是包含了get set方法没有初始化
延迟存储属性
从 SIL看下