Swift引用计数
-
Swift
引用计数官方文档描述如下Strong and unowned variables point at the object. Weak variables point at the object's side table. Storage layout: HeapObject { isa /// 只存储 strong unowned 引用计数 InlineRefCounts { atomic<InlineRefCountBits> { strong RC + unowned RC + flags OR HeapObjectSideTableEntry* } } } /// 存储 weak 以及 strong unowned的引用计数 HeapObjectSideTableEntry { SideTableRefCounts { object pointer atomic<SideTableRefCountBits> { strong RC + unowned RC + weak RC + flags } } }
-
获取
class-refcount
的swift源码提供的函数如下,直接粘贴
进项目可以直接打印:(纯Swift-class)/// 获取强引用计数 @_silgen_name("swift_retainCount") public func _getRetainCount(_ Value: AnyObject) -> UInt /// 获取unowned引用计数 @_silgen_name("swift_unownedRetainCount") public func _getUnownedRetainCount(_ Value : AnyObject) -> UInt /// 获取weak引用计数 @_silgen_name("swift_weakRetainCount") public func _getWeakRetainCount(_ Value : AnyObject) -> UInt
一个
swift-class
初始化的时候weak-refcount
和unowned-refcount
以及strong-refcount
默认都是1
-
一个
Class
引用计数存储位置的/// RefCountNotInline 当使用weak时的标识 /// RefCountIsInline 当前未使用weak enum RefCountInlinedness { RefCountNotInline = false, RefCountIsInline = true };
-
如果当前
class
没有使用weak
引用计数,存储的bits
标识是RefCountBitsT<RefCountIsInline> InlineRefCountBits
typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;
-
如果当前
class
中使用的weak
引用计数, 存储的bits标识是class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline>
/// sideTable 主要记录weak的引用及时 class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline> { /// weak 引用计数 uint32_t weakBits; public: SideTableRefCountBits() = default; constexpr SideTableRefCountBits(uint32_t strongExtraCount, uint32_t unownedCount) : RefCountBitsT<RefCountNotInline>(strongExtraCount, unownedCount) // weak refcount starts at 1 on behalf of the unowned count /// Weak 引用计数 如果 SideTableRefCountBits初始化 默认是1 , weakBits(1) { } LLVM_ATTRIBUTE_ALWAYS_INLINE SideTableRefCountBits(HeapObjectSideTableEntry* side) = delete; LLVM_ATTRIBUTE_ALWAYS_INLINE SideTableRefCountBits(InlineRefCountBits newbits) : RefCountBitsT<RefCountNotInline>(&newbits), weakBits(1) { } LLVM_ATTRIBUTE_ALWAYS_INLINE void incrementWeakRefCount() { weakBits++; } LLVM_ATTRIBUTE_ALWAYS_INLINE /// 标识是否需要释放 bool decrementWeakRefCount() { assert(weakBits > 0); weakBits--; return weakBits == 0; } LLVM_ATTRIBUTE_ALWAYS_INLINE uint32_t getWeakRefCount() { return weakBits; } // Side table ref count never has a side table of its own. LLVM_ATTRIBUTE_ALWAYS_INLINE bool hasSideTable() { return false; } };
-
bits
的的模板类,主要记录class
的一些标识,包括是否存在side-table
,是否是静态变量 ,还包含好引用计数的增加和减少// Basic encoding of refcount and flag data into the object's header. /// RefCountBitsT template <RefCountInlinedness refcountIsInline> class RefCountBitsT { friend class RefCountBitsT<RefCountIsInline>; friend class RefCountBitsT<RefCountNotInline>; static const RefCountInlinedness Inlinedness = refcountIsInline; /// 萃取 type的 bits位数 typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::Type BitsType; typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::SignedType SignedBitsType; /// 根据 type 萃取 偏移量 typedef RefCountBitOffsets<sizeof(BitsType)> Offsets; BitsType bits; /// 获取side-table HeapObjectSideTableEntry *getSideTable() const { assert(hasSideTable()); // Stored value is a shifted pointer. return reinterpret_cast<HeapObjectSideTableEntry *> (uintptr_t(getField(SideTable)) << Offsets::SideTableUnusedLowBits); } /// 增加strong引用计数 void setStrongExtraRefCount(uint32_t value) { assert(!hasSideTable()); setField(StrongExtraRefCount, value); } /// 增加strong引用计数 bool incrementStrongExtraRefCount(uint32_t inc) { // This deliberately overflows into the UseSlowRC field. bits += BitsType(inc) << Offsets::StrongExtraRefCountShift; return (SignedBitsType(bits) >= 0); } }
-
其中
RefCountBitsInt
模板类负责适配不同的机型,如果32位机型overflow就是用64位template <RefCountInlinedness refcountIsInline, size_t sizeofPointer> struct RefCountBitsInt; /// 64 位 template <RefCountInlinedness refcountIsInline> struct RefCountBitsInt<refcountIsInline, 8> { typedef uint64_t Type; typedef int64_t SignedType; }; // 32-bit out of line // 32 位 template <> struct RefCountBitsInt<RefCountNotInline, 4> { typedef uint64_t Type; typedef int64_t SignedType; }; // 32-bit inline template <> struct RefCountBitsInt<RefCountIsInline, 4> { typedef uint32_t Type; typedef int32_t SignedType; };
-
RefCounts
中RefCountBits
使用的模板实体类
/// strong unowned 引用计数
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
/// weak strong unowned 引用计数
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
-
RefCounts
内存模型///模板类 template <typename RefCountBits> class RefCounts { /// strong unknown 引用计数 std::atomic<RefCountBits> refCounts; public: /// 是否初始化 enum Initialized_t { Initialized }; /// 是否是常量, 不需要使用内存管理 enum Immortal_t { Immortal }; /// Return true if the object can be freed directly right now. /// (transition DEINITING -> DEAD) /// This is used in swift_deallocObject(). /// Can be freed now means: /// no side table /// unowned reference count is 1 /// The object is assumed to be deiniting with no strong references already. /// 判断当前对象是否需要释放 bool canBeFreedNow() const { auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); return (!bits.hasSideTable() && /// 释放可以被释放 bits.getIsDeiniting() && /// 额外的引用计数 bits.getStrongExtraRefCount() == 0 && /// 这里的unknown的引用计数为1也会被释放 bits.getUnownedRefCount() == 1); } /// Weak 存储的位置 // WEAK public: // Returns the object's side table entry (creating it if necessary) with // its weak ref count incremented. // Returns nullptr if the object is already deiniting. // Use this when creating a new weak reference to an object. /// weak 引用计数管理 HeapObjectSideTableEntry* formWeakReference(); /// 判断对象是否需要释放 template <PerformDeinit performDeinit> bool doDecrementSlow(RefCountBits oldbits, uint32_t dec) { RefCountBits newbits; bool deinitNow; do { ///记录 newbits = oldbits; /// 获取有没有使用引用计数的地方 bool fast = newbits.decrementStrongExtraRefCount(dec); if (fast) { // Decrement completed normally. New refcount is not zero. deinitNow = false; } /// 判断是否是常量 else if (oldbits.isImmortal()) { return false; /// 判断是否存在side-Table } else if (oldbits.hasSideTable()) { // Decrement failed because we're on some other slow path. return doDecrementSideTable<performDeinit>(oldbits, dec); } else { // Decrement underflowed. Begin deinit. // LIVE -> DEINITING deinitNow = true; assert(!oldbits.getIsDeiniting()); // FIXME: make this an error? newbits = oldbits; // Undo failed decrement of newbits. newbits.setStrongExtraRefCount(0); newbits.setIsDeiniting(true); } } while (!refCounts.compare_exchange_weak(oldbits, newbits, std::memory_order_release, std::memory_order_relaxed)); if (performDeinit && deinitNow) { /// 原子性的加锁----非原子性释放 不用使用栅栏函数 std::atomic_thread_fence(std::memory_order_acquire); /// 调用swift对象释放 ///getHeapObject() 获取当前对象的内存地址 _swift_release_dealloc(getHeapObject()); } return deinitNow; } }
-
关于
HeapObjectSideTableEntry
的定义class HeapObjectSideTableEntry { // FIXME: does object need to be atomic? /// 存储的对象 std::atomic<HeapObject*> object; /// 引用计数 SideTableRefCounts refCounts; public: HeapObjectSideTableEntry(HeapObject *newObject) : object(newObject), refCounts() { } }