objc4源码解析&retain

259 阅读1分钟

objc4源码基于779.1版本。文章纯属个人学习见解,谬误之处,望指正。

retain

方法调用栈

    • (id)retain
      • _objc_rootRetain(id obj)
        • objc_object::rootRetain()
          • objc_object::rootRetain(bool tryRetain, bool handleOverflow)
            • objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)

源码详注

  1. NSObject.mm - line:2254
- (id)retain {
    return _objc_rootRetain(self);
}
  1. NSObject.mm - line:1679
NEVER_INLINE id
_objc_rootRetain(id obj)
{
    ASSERT(obj);

    return obj->rootRetain();
}

3.objc-object.h - line:477

ALWAYS_INLINE id 
objc_object::rootRetain()
{
    return rootRetain(false, false);
}
  1. objc-object.h - line: 489
ALWAYS_INLINE id 
objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
    // 是 TaggedPointer 直接返回
    if (isTaggedPointer()) return (id)this;

    bool sideTableLocked = false;
    bool transcribeToSideTable = false;

    isa_t oldisa;
    isa_t newisa;

    do {
        transcribeToSideTable = false;
        // 获取isa
        oldisa = LoadExclusive(&isa.bits);
        
        // 新指针指向
        newisa = oldisa;
        
        if (slowpath(!newisa.nonpointer)) { // 是否为普通指针,直接操作sidetable
            ClearExclusive(&isa.bits);
            // 是元类直接返回
            if (rawISA()->isMetaClass()) return (id)this;
            
            // 是否需要解锁
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            if (tryRetain) return sidetable_tryRetain() ? (id)this : nil;
            else return sidetable_retain();
        }
        // don't check newisa.fast_rr; we already called any RR overrides
        // 当前对象的 isa 正在销毁
        if (slowpath(tryRetain && newisa.deallocating)) {
            ClearExclusive(&isa.bits);
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            return nil;
        }
        uintptr_t carry;
        // 引用计数+1
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc++

        if (slowpath(carry)) {
            // newisa.extra_rc++ overflowed
            // 引用计数 extra_rc 溢出
            if (!handleOverflow) {
                // 处理溢出
                ClearExclusive(&isa.bits);
                // 重新调用了当前方法rootRetain,handleOverflow = true
                return rootRetain_overflow(tryRetain);
            }
            // Leave half of the retain counts inline and 
            // prepare to copy the other half to the side table.
            if (!tryRetain && !sideTableLocked) sidetable_lock();
            sideTableLocked = true;
            transcribeToSideTable = true;
            // 保留一半的计数,准备复制一半到side table
            // 2^7 = 128
            newisa.extra_rc = RC_HALF;
            // 标记有side table存储
            newisa.has_sidetable_rc = true;
        }
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits))); // 原子交换函数

    if (slowpath(transcribeToSideTable)) {
        // Copy the other half of the retain counts to the side table.
        // 将另一半存在 side table
        sidetable_addExtraRC_nolock(RC_HALF);
    }

    if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
    return (id)this;
}
  1. NSObject.mm - line:1329
bool 
objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)
{
    ASSERT(isa.nonpointer);
    // 获取side table
    SideTable& table = SideTables()[this];

    // 获取引用计数的size
    size_t& refcntStorage = table.refcnts[this];
    // 赋值给oldRefcnt
    size_t oldRefcnt = refcntStorage;
    // isa-side bits should not be set here
    ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
    ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);

    if (oldRefcnt & SIDE_TABLE_RC_PINNED) return true;

    // 溢出标志
    uintptr_t carry;
    
    
    size_t newRefcnt = 
        addc(oldRefcnt, delta_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
    if (carry) {
        // 如果溢出,直接把refcntStorage 设置成最大值
        refcntStorage =
            SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
        return true;
    }
    else {
        refcntStorage = newRefcnt;
        return false;
    }
}