Swift源码解析之弱引用

2020-01-09 00:12:25王冬梅

这就是 RefCounts 的内存布局,我这里省略了所有的方法和类型定义。你可以把 RefCounts 想象成一个线程安全的 wrapper,模板参数 RefCountBits 指定了真实的内部类型,在 Swift ABI 里总共有两种:


typedef RefCounts<InlineRefCountBits> InlineRefCounts;
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;

前者是用在 HeapObject 中的,而后者是用在 HeapObjectSideTableEntry(Side Table)中的,这两种类型后文我会一一讲到。

一般来讲,Swift 对象并不会用到 Side Table,一旦对象被 weak 或 unowned 引用,该对象就会分配一个 Side Table。

InlineRefCountBits

定义:


typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;

template <RefCountInlinedness refcountIsInline>
class RefCountBitsT {

 friend class RefCountBitsT<RefCountIsInline>;
 friend class RefCountBitsT<RefCountNotInline>;

 static const RefCountInlinedness Inlinedness = refcountIsInline;

 typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::Type
 BitsType;
 typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::SignedType
 SignedBitsType;
 typedef RefCountBitOffsets<sizeof(BitsType)>
 Offsets;

 BitsType bits;

 // ...

};

通过模板替换之后,InlineRefCountBits 实际上就是一个 uint64_t,相关的一堆类型就是为了通过模板元编程让代码可读性更高(或者更低,哈哈哈)。

下面我们来模拟一下对象引用计数 +1:

调用 SIL 接口 swift::swift_retain:


HeapObject *swift::swift_retain(HeapObject *object) {
 return _swift_retain(object);
}

static HeapObject *_swift_retain_(HeapObject *object) {
 SWIFT_RT_TRACK_INVOCATION(object, swift_retain);
 if (isValidPointerForNativeRetain(object))
 object->refCounts.increment(1);
 return object;
}

auto swift::_swift_retain = _swift_retain_;