之前了解过isa在64bit系统后是一个共用体结构:

    1. // isa共用体
    2. union isa_t {
    3. uintptr_t bits;
    4. Class cls;
    5. struct {
    6. uintptr_t nonpointer : 1; \
    7. uintptr_t has_assoc : 1; \
    8. uintptr_t has_cxx_dtor : 1; \
    9. uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
    10. uintptr_t magic : 6; \
    11. uintptr_t weakly_referenced : 1; \
    12. uintptr_t unused : 1; \
    13. uintptr_t has_sidetable_rc : 1; \
    14. uintptr_t extra_rc : 19
    15. };
    16. };

    里面的extra_rc保存的就是引用计数,占用了19位的空间,如果这个19位空间不够保存引用计数的话,就会将has_sidetable_rc的标志设置为1,并且将引用计数保存到sidetable中。
    通过查看 objc源码 中的NSObject.mm,SideTable结构如下:

    1. struct SideTable {
    2. spinlock_t slock;
    3. RefcountMap refcnts;
    4. weak_table_t weak_table;
    5. };

    引用计数会保存在RefcountMap这个哈希表中。
    对象调用retain方法时,会将RefcountMap中对应的引用计数+1。
    在调用release方法时会将RefcountMap中对应的引用计数-1,如果引用计数为0,会调用对象的dealloc方法。

    1. uintptr_t
    2. objc_object::sidetable_release(bool locked, bool performDealloc)
    3. {
    4. #if SUPPORT_NONPOINTER_ISA
    5. ASSERT(!isa.nonpointer);
    6. #endif
    7. SideTable& table = SideTables()[this];
    8. bool do_dealloc = false;
    9. if (!locked) table.lock();
    10. auto it = table.refcnts.try_emplace(this, SIDE_TABLE_DEALLOCATING);
    11. auto &refcnt = it.first->second;
    12. if (it.second) {
    13. do_dealloc = true;
    14. } else if (refcnt < SIDE_TABLE_DEALLOCATING) {
    15. // SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
    16. do_dealloc = true;
    17. refcnt |= SIDE_TABLE_DEALLOCATING;
    18. } else if (! (refcnt & SIDE_TABLE_RC_PINNED)) {
    19. refcnt -= SIDE_TABLE_RC_ONE;
    20. }
    21. table.unlock();
    22. if (do_dealloc && performDealloc) {
    23. ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));
    24. }
    25. return do_dealloc;
    26. }