- 引用计数器的存储
在64bit中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中。
//refcnts是一个存放着对象引用计数的散列表typedef objc::DenseMap<DisguisedPtr<objc_object>,size_t,true> RefcountMap;/*** The global weak references table. Stores object ids as keys,* and weak_entry_t structs as their values.*/struct weak_table_t {weak_entry_t *weak_entries;size_t num_entries;uintptr_t mask;uintptr_t max_hash_displacement;};struct SideTable {spinlock_t slock;RefcountMap refcnts;weak_table_t weak_table;SideTable() {memset(&weak_table, 0, sizeof(weak_table));}~SideTable() {_objc_fatal("Do not delete SideTable.");}};
引用计数器的计算
inline uintptr_tobjc_object::rootRetainCount(){if (isTaggedPointer()) return (uintptr_t)this;sidetable_lock();isa_t bits = LoadExclusive(&isa.bits);ClearExclusive(&isa.bits);if (bits.nonpointer) { //优化过的isa指针uintptr_t rc = 1 + bits.extra_rc;if (bits.has_sidetable_rc) { //引用计数器不是存储在isa中,而是存储在sidetable中rc += sidetable_getExtraRC_nolock();}sidetable_unlock();return rc;}sidetable_unlock();return sidetable_retainCount();}size_tobjc_object::sidetable_getExtraRC_nolock(){assert(isa.nonpointer);SideTable& table = SideTables()[this];RefcountMap::iterator it = table.refcnts.find(this); //通过this这个key取出对象的引用计数if (it == table.refcnts.end()) return 0;else return it->second >> SIDE_TABLE_RC_SHIFT;}ALWAYS_INLINE boolobjc_object::rootRelease(bool performDealloc, bool handleUnderflow){if (isTaggedPointer()) return false;bool sideTableLocked = false;isa_t oldisa;isa_t newisa;retry:do {oldisa = LoadExclusive(&isa.bits);newisa = oldisa;if (slowpath(!newisa.nonpointer)) {ClearExclusive(&isa.bits);//调用sidetable释放。if (sideTableLocked) sidetable_unlock();}// don't check newisa.fast_rr; we already called any RR overridesuintptr_t carry;newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry); // extra_rc--if (slowpath(carry)) {// don't ClearExclusive()goto underflow;}} while (slowpath(!StoreReleaseExclusive(&isa.bits,oldisa.bits, newisa.bits)));if (slowpath(sideTableLocked)) sidetable_unlock();return false;}uintptr_tobjc_object::sidetable_release(bool performDealloc){#if SUPPORT_NONPOINTER_ISAassert(!isa.nonpointer);#endifSideTable& table = SideTables()[this];bool do_dealloc = false;table.lock();RefcountMap::iterator it = table.refcnts.find(this);if (it == table.refcnts.end()) {do_dealloc = true;table.refcnts[this] = SIDE_TABLE_DEALLOCATING;} else if (it->second < SIDE_TABLE_DEALLOCATING) {// SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.do_dealloc = true;it->second |= SIDE_TABLE_DEALLOCATING;} else if (! (it->second & SIDE_TABLE_RC_PINNED)) {it->second -= SIDE_TABLE_RC_ONE;}table.unlock();//到了一定的条件执行deallocif (do_dealloc && performDealloc) {((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);}return do_dealloc;}
- ARC帮我们做了什么?
ARC是LLVM编译器和Runtime系统相互协作的结果,利用编译器自动帮我们生成内存管理相关的代码,在程序运行的过程中又帮我们处理弱引用(weak)这种操作。
