Swift. 类、属性

235 阅读2分钟

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函数,搜索找到后打断点 从上图中可以看到返回值是HeapObjectHeapObject是一个结构体,创建出来的实例变量在内存中的存储结构就是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>;

这句表示HeapMetadataTargetHeapMetadata的别名, 查看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看下