Swift引用計數(shù)
-
Swift
引用計數(shù)官方文檔描述如下Strong and unowned variables point at the object. Weak variables point at the object's side table. Storage layout: HeapObject { isa /// 只存儲 strong unowned 引用計數(shù) InlineRefCounts { atomic<InlineRefCountBits> { strong RC + unowned RC + flags OR HeapObjectSideTableEntry* } } } /// 存儲 weak 以及 strong unowned的引用計數(shù) HeapObjectSideTableEntry { SideTableRefCounts { object pointer atomic<SideTableRefCountBits> { strong RC + unowned RC + weak RC + flags } } }
-
獲取
class-refcount
的swift源碼提供的函數(shù)如下,直接粘貼
進項目可以直接打印:(純Swift-class)/// 獲取強引用計數(shù) @_silgen_name("swift_retainCount") public func _getRetainCount(_ Value: AnyObject) -> UInt /// 獲取unowned引用計數(shù) @_silgen_name("swift_unownedRetainCount") public func _getUnownedRetainCount(_ Value : AnyObject) -> UInt /// 獲取weak引用計數(shù) @_silgen_name("swift_weakRetainCount") public func _getWeakRetainCount(_ Value : AnyObject) -> UInt
一個
swift-class
初始化的時候weak-refcount
和unowned-refcount
以及strong-refcount
默認都是1
-
一個
Class
引用計數(shù)存儲位置的/// RefCountNotInline 當使用weak時的標識 /// RefCountIsInline 當前未使用weak enum RefCountInlinedness { RefCountNotInline = false, RefCountIsInline = true };
-
如果當前
class
沒有使用weak
引用計數(shù),存儲的bits
標識是RefCountBitsT<RefCountIsInline> InlineRefCountBits
typedef RefCountBitsT<RefCountIsInline> InlineRefCountBits;
-
如果當前
class
中使用的weak
引用計數(shù), 存儲的bits標識是class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline>
/// sideTable 主要記錄weak的引用及時 class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline> { /// weak 引用計數(shù) 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 引用計數(shù) 如果 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
,是否是靜態(tài)變量 ,還包含好引用計數(shù)的增加和減少// 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位數(shù) typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::Type BitsType; typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::SignedType SignedBitsType; /// 根據(jù) 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引用計數(shù) void setStrongExtraRefCount(uint32_t value) { assert(!hasSideTable()); setField(StrongExtraRefCount, value); } /// 增加strong引用計數(shù) 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 引用計數(shù)
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
/// weak strong unowned 引用計數(shù)
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
-
RefCounts
內(nèi)存模型///模板類 template <typename RefCountBits> class RefCounts { /// strong unknown 引用計數(shù) std::atomic<RefCountBits> refCounts; public: /// 是否初始化 enum Initialized_t { Initialized }; /// 是否是常量, 不需要使用內(nèi)存管理 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() && /// 額外的引用計數(shù) bits.getStrongExtraRefCount() == 0 && /// 這里的unknown的引用計數(shù)為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 引用計數(shù)管理 HeapObjectSideTableEntry* formWeakReference(); /// 判斷對象是否需要釋放 template <PerformDeinit performDeinit> bool doDecrementSlow(RefCountBits oldbits, uint32_t dec) { RefCountBits newbits; bool deinitNow; do { ///記錄 newbits = oldbits; /// 獲取有沒有使用引用計數(shù)的地方 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) { /// 原子性的加鎖----非原子性釋放 不用使用柵欄函數(shù) std::atomic_thread_fence(std::memory_order_acquire); /// 調(diào)用swift對象釋放 ///getHeapObject() 獲取當前對象的內(nèi)存地址 _swift_release_dealloc(getHeapObject()); } return deinitNow; } }
-
關(guān)于
HeapObjectSideTableEntry
的定義class HeapObjectSideTableEntry { // FIXME: does object need to be atomic? /// 存儲的對象 std::atomic<HeapObject*> object; /// 引用計數(shù) SideTableRefCounts refCounts; public: HeapObjectSideTableEntry(HeapObject *newObject) : object(newObject), refCounts() { } }