之前了解过isa在64bit系统后是一个共用体结构:
// isa共用体union isa_t {uintptr_t bits;Class cls;struct {uintptr_t nonpointer : 1; \uintptr_t has_assoc : 1; \uintptr_t has_cxx_dtor : 1; \uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \uintptr_t magic : 6; \uintptr_t weakly_referenced : 1; \uintptr_t unused : 1; \uintptr_t has_sidetable_rc : 1; \uintptr_t extra_rc : 19};};
里面的extra_rc保存的就是引用计数,占用了19位的空间,如果这个19位空间不够保存引用计数的话,就会将has_sidetable_rc的标志设置为1,并且将引用计数保存到sidetable中。
通过查看 objc源码 中的NSObject.mm,SideTable结构如下:
struct SideTable {spinlock_t slock;RefcountMap refcnts;weak_table_t weak_table;};
引用计数会保存在RefcountMap这个哈希表中。
对象调用retain方法时,会将RefcountMap中对应的引用计数+1。
在调用release方法时会将RefcountMap中对应的引用计数-1,如果引用计数为0,会调用对象的dealloc方法。
uintptr_tobjc_object::sidetable_release(bool locked, bool performDealloc){#if SUPPORT_NONPOINTER_ISAASSERT(!isa.nonpointer);#endifSideTable& table = SideTables()[this];bool do_dealloc = false;if (!locked) table.lock();auto it = table.refcnts.try_emplace(this, SIDE_TABLE_DEALLOCATING);auto &refcnt = it.first->second;if (it.second) {do_dealloc = true;} else if (refcnt < SIDE_TABLE_DEALLOCATING) {// SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.do_dealloc = true;refcnt |= SIDE_TABLE_DEALLOCATING;} else if (! (refcnt & SIDE_TABLE_RC_PINNED)) {refcnt -= SIDE_TABLE_RC_ONE;}table.unlock();if (do_dealloc && performDealloc) {((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));}return do_dealloc;}
