UIViewController *oldVC = [UIViewController new];__weak typeof(oldVC) weakVC = oldVC; // 旧的UIViewController *newVC = [UIViewController new];weakVC = newVC; // 新的接下来看看weak底层逻辑吧。
利用__weak修饰的指针指向一个对象时,会走源码中的objc_initWeak。
打开objc4-838.1源码,搜索objc_initWeak函数
storeWeak函数就是处置惩罚__weak修饰的弱对象指向一个对象的处置惩罚:
// Update a weak variable.// If HaveOld is true, the variable has an existing value // that needs to be cleaned up. This value might be nil.// If HaveNew is true, there is a new value that needs to be // assigned into the variable. This value might be nil.// If CrashIfDeallocating is true, the process is halted if newObj is // deallocating or newObj's class does not support weak references. // If CrashIfDeallocating is false, nil is stored instead.enum CrashIfDeallocating { DontCrashIfDeallocating = false, DoCrashIfDeallocating = true};// HaveOld: weak指针是否之前就指向了对象 即weakVC是否指向过oldVC// HaveNew: weak指针是否将指向的新的对象 即weakVC是否将要指向newVC// CrashIfDeallocating: 被弱引用的对象是否正在析构,如果析构则Crashtemplate <HaveOld haveOld, HaveNew haveNew, enum CrashIfDeallocating crashIfDeallocating>// location: 弱引用指针的地点 即weakVC的地点// newObj: 将被弱引用指针指向的对象 即newVC对象static id storeWeak(id *location, objc_object *newObj){ ASSERT(haveOld || haveNew); if (!haveNew) ASSERT(newObj == nil); Class previouslyInitializedClass = nil; id oldObj; // 获取 weakVC之前指向的对象oldVC,若没有指向过,则为nil SideTable *oldTable; // 获取 weakVC之前指向的对象oldVC的散列表,若没有指向过,则为nil SideTable *newTable; // 获取 weakVC将被弱引用的对象newVC的散列表 // Acquire locks for old and new values. // Order by lock address to prevent lock ordering problems. // Retry if the old value changes underneath us. retry: if (haveOld) { // 如果weakVC曾经指向过oldVC,获取 oldVC对象 和 oldVC散列表 oldObj = *location; oldTable = &SideTables()[oldObj]; } else { oldTable = nil; } if (haveNew) { // 如果weakVC将要指向newVC,获取 newVC散列表 newTable = &SideTables()[newObj]; } else { newTable = nil; } SideTable::lockTwo<haveOld, haveNew>(oldTable, newTable); // 加锁 // 清除非常情况(不消管):如果weakVC曾经指向过oldVC,而且weakVC指向的还不是oldVC if (haveOld && *location != oldObj) { SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable); goto retry; } // Prevent a deadlock between the weak reference machinery // and the +initialize machinery by ensuring that no // weakly-referenced object has an un-+initialized isa. // 清除非常情况(不消管):newVC的类对象还没有被初始化,就去初始化 if (haveNew && newObj) { Class cls = newObj->getIsa(); if (cls != previouslyInitializedClass && !((objc_class *)cls)->isInitialized()) { SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable); class_initialize(cls, (id)newObj); // If this class is finished with +initialize then we're good. // If this class is still running +initialize on this thread // (i.e. +initialize called storeWeak on an instance of itself) // then we may proceed but it will appear initializing and // not yet initialized to the check above. // Instead set previouslyInitializedClass to recognize it on retry. previouslyInitializedClass = cls; goto retry; } } // Clean up old value, if any. if (haveOld) { // 如果weakVC曾经指向过oldVC,则把之前的弱引用注销掉 weak_unregister_no_lock(&oldTable->weak_table, oldObj, location); } // Assign new value, if any. // weakVC去注册新的弱引用,并指向newVC if (haveNew) { newObj = (objc_object *) // 怎么注册?将weakVC的地点存储到SideTable里weak_table_t里去 weak_register_no_lock(&newTable->weak_table, (id)newObj, location, crashIfDeallocating ? CrashIfDeallocating : ReturnNilIfDeallocating); // weak_register_no_lock returns nil if weak store should be rejected // Set is-weakly-referenced bit in refcount table. // 如果不是TaggedPointer或nil,将isa里的是否被弱引用weakly_referenced 置为true if (!_objc_isTaggedPointerOrNil(newObj)) { newObj->setWeaklyReferenced_nolock(); // 将isa的是否被弱引用置为true } // Do not set *location anywhere else. That would introduce a race. // 将weakVC的地点生存newVC *location = (id)newObj; } else { // No new value. The storage is not changed. } SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable); // 解锁 // This must be called without the locks held, as it can invoke // arbitrary code. In particular, even if _setWeaklyReferenced // is not implemented, resolveInstanceMethod: may be, and may // call back into the weak reference machinery. callSetWeaklyReferenced((id)newObj); return (id)newObj;}weak底层调用:objc_initWeak -> storeWeak storeWeak的底层逻辑:
打开objc4-838.1源码,搜索objc_retain函数
rootRetain函数就是处置惩罚对象的引用计数的逻辑:
ALWAYS_INLINE idobjc_object::rootRetain(bool tryRetain, objc_object::RRVariant variant){ if (slowpath(isTaggedPointer())) return (id)this; bool sideTableLocked = false; bool transcribeToSideTable = false; // 先去获取对象的isa指针,由于引用计数信息存储在isa里 isa_t oldisa; isa_t newisa; oldisa = LoadExclusive(&isa.bits); if (variant == RRVariant::FastOrMsgSend) { // These checks are only meaningful for objc_retain() // They are here so that we avoid a re-load of the isa. if (slowpath(oldisa.getDecodedClass(false)->hasCustomRR())) { ClearExclusive(&isa.bits); if (oldisa.getDecodedClass(false)->canCallSwiftRR()) { return swiftRetain.load(memory_order_relaxed)((id)this); } return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(retain)); } } if (slowpath(!oldisa.nonpointer)) { // a Class is a Class forever, so we can perform this check once // outside of the CAS loop if (oldisa.getDecodedClass(false)->isMetaClass()) { ClearExclusive(&isa.bits); return (id)this; } } // 焦点逻辑在这个do...while!!! do { transcribeToSideTable = false; newisa = oldisa; // 1.不是nonpointer_isa的情况,sidetable存储引用计数 if (slowpath(!newisa.nonpointer)) { ClearExclusive(&isa.bits); if (tryRetain) return sidetable_tryRetain() ? (id)this : nil; else return sidetable_retain(sideTableLocked); } // 下面代码逻辑 是nonpointer_isa的情况 // don't check newisa.fast_rr; we already called any RR overrides if (slowpath(newisa.isDeallocating())) { ClearExclusive(&isa.bits); if (sideTableLocked) { ASSERT(variant == RRVariant::Full); sidetable_unlock(); } if (slowpath(tryRetain)) { return nil; } else { return (id)this; } } // 2.是nonpointer_isa的情况,引用技能位extra_rc存得下,直接+1 uintptr_t carry; newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); // extra_rc++ // 3.是nonpointer_isa的情况,引用技能位extra_rc存不下,extra_rc保存一半的引用计数,并准备将另一半copy到sidetable if (slowpath(carry)) { // newisa.extra_rc++ overflowed // 判定extra_rc是否超出 if (variant != RRVariant::Full) { ClearExclusive(&isa.bits); return rootRetain_overflow(tryRetain); } // Leave half of the retain counts inline and // prepare to copy the other half to the side table. // extra_rc存不下,保存一半的引用计数,并准备将另一半copy到sidetable if (!tryRetain && !sideTableLocked) sidetable_lock(); sideTableLocked = true; transcribeToSideTable = true; newisa.extra_rc = RC_HALF; newisa.has_sidetable_rc = true; } } while (slowpath(!StoreExclusive(&isa.bits, &oldisa.bits, newisa.bits))); if (variant == RRVariant::Full) { if (slowpath(transcribeToSideTable)) { // Copy the other half of the retain counts to the side table. sidetable_addExtraRC_nolock(RC_HALF); } if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock(); } else { ASSERT(!transcribeToSideTable); ASSERT(!sideTableLocked); } return (id)this;}总结: retain源码调用流程:objc_retain --> objc_object::retain() --> objc_object::rootRetain
rootRetain操纵逻辑:
打开objc4-838.1源码,搜索objc_release函数
rootRelease函数就是处置惩罚对象的引用计数的逻辑:
ALWAYS_INLINE boolobjc_object::rootRelease(bool performDealloc, objc_object::RRVariant variant){ if (slowpath(isTaggedPointer())) return false; bool sideTableLocked = false; // 获取对象的isa,由于引用计数信息存储在isa里 isa_t newisa, oldisa; oldisa = LoadExclusive(&isa.bits); if (variant == RRVariant::FastOrMsgSend) { // These checks are only meaningful for objc_release() // They are here so that we avoid a re-load of the isa. if (slowpath(oldisa.getDecodedClass(false)->hasCustomRR())) { ClearExclusive(&isa.bits); if (oldisa.getDecodedClass(false)->canCallSwiftRR()) { swiftRelease.load(memory_order_relaxed)((id)this); return true; } ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(release)); return true; } } if (slowpath(!oldisa.nonpointer)) { // a Class is a Class forever, so we can perform this check once // outside of the CAS loop if (oldisa.getDecodedClass(false)->isMetaClass()) { ClearExclusive(&isa.bits); return false; } }retry: // 引用计数真正操纵逻辑在do...while里 do { newisa = oldisa; // 1.如果不是nonpointer_isa,操纵sidetable里的引用计数-1 if (slowpath(!newisa.nonpointer)) { ClearExclusive(&isa.bits); return sidetable_release(sideTableLocked, performDealloc); } // 判定对象是否正在开释,如果是,则直接return if (slowpath(newisa.isDeallocating())) { ClearExclusive(&isa.bits); if (sideTableLocked) { ASSERT(variant == RRVariant::Full); sidetable_unlock(); } return false; } // don't check newisa.fast_rr; we already called any RR overrides // 将nonpointer_isa里的引用计数位extra_rc举行-1操纵 uintptr_t carry; newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry); // extra_rc-- if (slowpath(carry)) { // don't ClearExclusive() goto underflow; // 如果extra_rc的值为0的情况,走underflow代码块 } } while (slowpath(!StoreReleaseExclusive(&isa.bits, &oldisa.bits, newisa.bits))); if (slowpath(newisa.isDeallocating())) goto deallocate; // 开释对象内存 if (variant == RRVariant::Full) { if (slowpath(sideTableLocked)) sidetable_unlock(); } else { ASSERT(!sideTableLocked); } return false; underflow: // newisa.extra_rc-- underflowed: borrow from side table or deallocate // abandon newisa to undo the decrement newisa = oldisa; // 如果nonpointer_isa的sidetable标志位 has_sidetable_rc == 1 if (slowpath(newisa.has_sidetable_rc)) { if (variant != RRVariant::Full) { ClearExclusive(&isa.bits); return rootRelease_underflow(performDealloc); } // Transfer retain count from side table to inline storage. // 将引用计数从sidetable转移回extra_rc if (!sideTableLocked) { ClearExclusive(&isa.bits); sidetable_lock(); sideTableLocked = true; // Need to start over to avoid a race against // the nonpointer -> raw pointer transition. oldisa = LoadExclusive(&isa.bits); goto retry; } // Try to remove some retain counts from the side table. // 把sidetable里的引用计数移除 auto borrow = sidetable_subExtraRC_nolock(RC_HALF); // 如果sidetable上没有多余的东西,我们就把sidetable清算干净 bool emptySideTable = borrow.remaining == 0; // we'll clear the side table if no refcounts remain there if (borrow.borrowed > 0) { // Side table retain count decreased. // Try to add them to the inline count. // sidetable保存引用计数-1。实验将它们添加到内联计数中。 bool didTransitionToDeallocating = false; newisa.extra_rc = borrow.borrowed - 1; // redo the original decrement too newisa.has_sidetable_rc = !emptySideTable; bool stored = StoreReleaseExclusive(&isa.bits, &oldisa.bits, newisa.bits); if (!stored && oldisa.nonpointer) { // Inline update failed. // Try it again right now. This prevents livelock on LL/SC // architectures where the side table access itself may have // dropped the reservation. uintptr_t overflow; newisa.bits = addc(oldisa.bits, RC_ONE * (borrow.borrowed-1), 0, &overflow); newisa.has_sidetable_rc = !emptySideTable; if (!overflow) { stored = StoreReleaseExclusive(&isa.bits, &oldisa.bits, newisa.bits); if (stored) { didTransitionToDeallocating = newisa.isDeallocating(); } } } if (!stored) { // Inline update failed. // Put the retains back in the side table. ClearExclusive(&isa.bits); sidetable_addExtraRC_nolock(borrow.borrowed); oldisa = LoadExclusive(&isa.bits); goto retry; } // Decrement successful after borrowing from side table. // 减量乐成后,从sidetable拿回引用计数给extra_rc。 if (emptySideTable) sidetable_clearExtraRC_nolock(); if (!didTransitionToDeallocating) { if (slowpath(sideTableLocked)) sidetable_unlock(); return false; } } else { // Side table is empty after all. Fall-through to the dealloc path. } }deallocate: // Really deallocate. ASSERT(newisa.isDeallocating()); ASSERT(isa.isDeallocating()); if (slowpath(sideTableLocked)) sidetable_unlock(); __c11_atomic_thread_fence(__ATOMIC_ACQUIRE); if (performDealloc) { ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc)); } return true;}总结: release源码调用流程:objc_release --> objc_object::release() --> objc_object::rootRelease
rootRelease操纵逻辑: