Swift 泛型底层实现原理

Swift 是如何管理协议类型与泛型类型的生命周期与方法调用?

协议类型在内存中的存储形式是 Extential Container,Extential Container 占 5 个内存单元(也称 词),其作用如下:

  • 3 个词作为 Value Buffer。
  • 1 个词作为 Value Witness Table 的索引,主要用于管理生命周期。
  • 1 个词作为 Protocol Witness Table 的索引,主要用于管理方法调用。

请添加图片描述

泛型类型由于在调用时能够确定具体的类型,所以不需要使用 Extential Container。在调用泛型方法时,只需要将 Value Witness Table/Protocol Witness Table 作为额外参数进行传递。

内存管理

泛型类型使用 VWT 进行内存管理,VWT 由编译器生成,其存储了该类型的 size、aligment(对齐方式)以及针对该类型的基本内存操作。其结构如下所示(以 C 代码表示):

struct value_witness_table {
   
   
    size_t size, align;
    void (*copy_init)(opaque *dst, const opaque *src, type *T);
    void (*copy_assign)(opaque *dst, const opaque *src, type *T);
    void (*move_init)(opaque *dst, const opaque *src, type *T);
    void (*move_assign)(opaque *dst, const opaque *src, type *T);
    void (*destroy)(opaque *val, type *T);
}

对泛型类型进行内存操作(如:内存拷贝)时,最终会调用对应泛型类型的 VWT 中的基本内存操作。泛型类型不同,其对应的 VWT 也不同。下图所示为一个小的值类型和一个引用类型的 VWT。

  • 对于一个小的值类型,如:integer。该类型的 copy 和 move 操作会进行内存拷贝;destroy 操作则不进行任何操作。
  • 对于一个引用类型,如:class。该类型的 copy 操作会对引用计数加 1;move 操作会拷贝指针,而不会更新引用计数;destroy 操作会对引用计数减 1。

请添加图片描述

方法调用

上一节,我们介绍了泛型的内存管理。那么,泛型的方法调用又是如何实现的呢?

我们以如下一个泛型函数为例进行介绍。

func f<T>(_ t: T) -> T {
   
   
    let copy = t
    return copy
}

编译器对上述的泛型函数进行编译后,会得到如下代码(以 C 代码代替 LLVM IR)。

// T: 泛型参数
void f(opaque *result, opaque *t, type *T) {
   
   
    opaque *copy = alloca(T->vwt->size);
    T->vwt->copy_init(copy, t, T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值