• 引用计数器的存储

    在64bit中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中。

    1. //refcnts是一个存放着对象引用计数的散列表
    2. typedef objc::DenseMap<DisguisedPtr<objc_object>,size_t,true> RefcountMap;
    3. /**
    4. * The global weak references table. Stores object ids as keys,
    5. * and weak_entry_t structs as their values.
    6. */
    7. struct weak_table_t {
    8. weak_entry_t *weak_entries;
    9. size_t num_entries;
    10. uintptr_t mask;
    11. uintptr_t max_hash_displacement;
    12. };
    13. struct SideTable {
    14. spinlock_t slock;
    15. RefcountMap refcnts;
    16. weak_table_t weak_table;
    17. SideTable() {
    18. memset(&weak_table, 0, sizeof(weak_table));
    19. }
    20. ~SideTable() {
    21. _objc_fatal("Do not delete SideTable.");
    22. }
    23. };

    引用计数器的计算

    1. inline uintptr_t
    2. objc_object::rootRetainCount()
    3. {
    4. if (isTaggedPointer()) return (uintptr_t)this;
    5. sidetable_lock();
    6. isa_t bits = LoadExclusive(&isa.bits);
    7. ClearExclusive(&isa.bits);
    8. if (bits.nonpointer) { //优化过的isa指针
    9. uintptr_t rc = 1 + bits.extra_rc;
    10. if (bits.has_sidetable_rc) { //引用计数器不是存储在isa中,而是存储在sidetable中
    11. rc += sidetable_getExtraRC_nolock();
    12. }
    13. sidetable_unlock();
    14. return rc;
    15. }
    16. sidetable_unlock();
    17. return sidetable_retainCount();
    18. }
    19. size_t
    20. objc_object::sidetable_getExtraRC_nolock()
    21. {
    22. assert(isa.nonpointer);
    23. SideTable& table = SideTables()[this];
    24. RefcountMap::iterator it = table.refcnts.find(this); //通过this这个key取出对象的引用计数
    25. if (it == table.refcnts.end()) return 0;
    26. else return it->second >> SIDE_TABLE_RC_SHIFT;
    27. }
    28. ALWAYS_INLINE bool
    29. objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
    30. {
    31. if (isTaggedPointer()) return false;
    32. bool sideTableLocked = false;
    33. isa_t oldisa;
    34. isa_t newisa;
    35. retry:
    36. do {
    37. oldisa = LoadExclusive(&isa.bits);
    38. newisa = oldisa;
    39. if (slowpath(!newisa.nonpointer)) {
    40. ClearExclusive(&isa.bits);
    41. //调用sidetable释放。
    42. if (sideTableLocked) sidetable_unlock();
    43. }
    44. // don't check newisa.fast_rr; we already called any RR overrides
    45. uintptr_t carry;
    46. newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry); // extra_rc--
    47. if (slowpath(carry)) {
    48. // don't ClearExclusive()
    49. goto underflow;
    50. }
    51. } while (slowpath(!StoreReleaseExclusive(&isa.bits,
    52. oldisa.bits, newisa.bits)));
    53. if (slowpath(sideTableLocked)) sidetable_unlock();
    54. return false;
    55. }
    56. uintptr_t
    57. objc_object::sidetable_release(bool performDealloc)
    58. {
    59. #if SUPPORT_NONPOINTER_ISA
    60. assert(!isa.nonpointer);
    61. #endif
    62. SideTable& table = SideTables()[this];
    63. bool do_dealloc = false;
    64. table.lock();
    65. RefcountMap::iterator it = table.refcnts.find(this);
    66. if (it == table.refcnts.end()) {
    67. do_dealloc = true;
    68. table.refcnts[this] = SIDE_TABLE_DEALLOCATING;
    69. } else if (it->second < SIDE_TABLE_DEALLOCATING) {
    70. // SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
    71. do_dealloc = true;
    72. it->second |= SIDE_TABLE_DEALLOCATING;
    73. } else if (! (it->second & SIDE_TABLE_RC_PINNED)) {
    74. it->second -= SIDE_TABLE_RC_ONE;
    75. }
    76. table.unlock();
    77. //到了一定的条件执行dealloc
    78. if (do_dealloc && performDealloc) {
    79. ((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);
    80. }
    81. return do_dealloc;
    82. }
    • ARC帮我们做了什么?

    ARC是LLVM编译器和Runtime系统相互协作的结果,利用编译器自动帮我们生成内存管理相关的代码,在程序运行的过程中又帮我们处理弱引用(weak)这种操作。