Swift引用計(jì)數(shù)
-
Swift引用計(jì)數(shù)官方文檔描述如下Strong and unowned variables point at the object. Weak variables point at the object's side table. Storage layout: HeapObject { isa /// 只存儲(chǔ) strong unowned 引用計(jì)數(shù) InlineRefCounts { atomic<InlineRefCountBits> { strong RC + unowned RC + flags OR HeapObjectSideTableEntry* } } } /// 存儲(chǔ) weak 以及 strong unowned的引用計(jì)數(shù) HeapObjectSideTableEntry { SideTableRefCounts { object pointer atomic<SideTableRefCountBits> { strong RC + unowned RC + weak RC + flags } } } -
獲取
class-refcount的swift源碼提供的函數(shù)如下,直接粘貼進(jìn)項(xiàng)目可以直接打印:(純Swift-class)/// 獲取強(qiáng)引用計(jì)數(shù) @_silgen_name("swift_retainCount") public func _getRetainCount(_ Value: AnyObject) -> UInt /// 獲取unowned引用計(jì)數(shù) @_silgen_name("swift_unownedRetainCount") public func _getUnownedRetainCount(_ Value : AnyObject) -> UInt /// 獲取weak引用計(jì)數(shù) @_silgen_name("swift_weakRetainCount") public func _getWeakRetainCount(_ Value : AnyObject) -> UInt
一個(gè)
swift-class初始化的時(shí)候weak-refcount和unowned-refcount以及strong-refcount默認(rèn)都是1-
一個(gè)
Class引用計(jì)數(shù)存儲(chǔ)位置的/// RefCountNotInline 當(dāng)使用weak時(shí)的標(biāo)識(shí) /// RefCountIsInline 當(dāng)前未使用weak enum RefCountInlinedness { RefCountNotInline = false, RefCountIsInline = true }; -
如果當(dāng)前
class沒有使用weak引用計(jì)數(shù),存儲(chǔ)的bits標(biāo)識(shí)是RefCountBitsT<RefCountIsInline> InlineRefCountBitstypedef RefCountBitsT<RefCountIsInline> InlineRefCountBits; -
如果當(dāng)前
class中使用的weak引用計(jì)數(shù), 存儲(chǔ)的bits標(biāo)識(shí)是class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline>/// sideTable 主要記錄weak的引用及時(shí) class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline> { /// weak 引用計(jì)數(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 引用計(jì)數(shù) 如果 SideTableRefCountBits初始化 默認(rèn)是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 /// 標(biāo)識(shí)是否需要釋放 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的一些標(biāo)識(shí),包括是否存在side-table,是否是靜態(tài)變量 ,還包含好引用計(jì)數(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引用計(jì)數(shù) void setStrongExtraRefCount(uint32_t value) { assert(!hasSideTable()); setField(StrongExtraRefCount, value); } /// 增加strong引用計(jì)數(shù) bool incrementStrongExtraRefCount(uint32_t inc) { // This deliberately overflows into the UseSlowRC field. bits += BitsType(inc) << Offsets::StrongExtraRefCountShift; return (SignedBitsType(bits) >= 0); } } -
其中
RefCountBitsInt模板類負(fù)責(zé)適配不同的機(jī)型,如果32位機(jī)型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使用的模板實(shí)體類
/// strong unowned 引用計(jì)數(shù)
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
/// weak strong unowned 引用計(jì)數(shù)
typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
-
RefCounts內(nèi)存模型///模板類 template <typename RefCountBits> class RefCounts { /// strong unknown 引用計(jì)數(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. /// 判斷當(dāng)前對(duì)象是否需要釋放 bool canBeFreedNow() const { auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); return (!bits.hasSideTable() && /// 釋放可以被釋放 bits.getIsDeiniting() && /// 額外的引用計(jì)數(shù) bits.getStrongExtraRefCount() == 0 && /// 這里的unknown的引用計(jì)數(shù)為1也會(huì)被釋放 bits.getUnownedRefCount() == 1); } /// Weak 存儲(chǔ)的位置 // 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 引用計(jì)數(shù)管理 HeapObjectSideTableEntry* formWeakReference(); /// 判斷對(duì)象是否需要釋放 template <PerformDeinit performDeinit> bool doDecrementSlow(RefCountBits oldbits, uint32_t dec) { RefCountBits newbits; bool deinitNow; do { ///記錄 newbits = oldbits; /// 獲取有沒有使用引用計(jì)數(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對(duì)象釋放 ///getHeapObject() 獲取當(dāng)前對(duì)象的內(nèi)存地址 _swift_release_dealloc(getHeapObject()); } return deinitNow; } } -
關(guān)于
HeapObjectSideTableEntry的定義class HeapObjectSideTableEntry { // FIXME: does object need to be atomic? /// 存儲(chǔ)的對(duì)象 std::atomic<HeapObject*> object; /// 引用計(jì)數(shù) SideTableRefCounts refCounts; public: HeapObjectSideTableEntry(HeapObject *newObject) : object(newObject), refCounts() { } }