Objective-C 之 Runtime 对象

Objective-C 之 Runtime 对象而 objc_object 这个结构体中只有一个 isa_t 类型的成员 isa,它包含了当前对象所属于的类的信息。 isa_t 是一个联合体,这就意味着 isa_t 中保存的既可以是一个 Class 类型的指针,也可以是一个 64 位的 bits,但在某一个时刻,只能保存二者…

数据结构

当不确定一个对象的类型的时候,通常使用 id 类型进行表示

- (id)copy;

id 代表一个对象,它是指向一个实例对象的指针

typedef struct objc_object *id;

实际上,id 是一个 objc_object 结构体类型指针的别名

struct objc_object {
    isa_t isa;
};

objc_object 这个结构体中只有一个 isa_t 类型的成员 isa,它包含了当前对象所属于的类的信息。

isa_t

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

isa_t 是一个联合体,这就意味着 isa_t 中保存的既可以是一个 Class 类型的指针,也可以是一个 64 位的 bits,但在某一个时刻,只能保存二者中的一个。

# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_BITFIELD \
      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 deallocating : 1;                                       \
      uintptr_t has_sidetable_rc : 1;                                       \
      uintptr_t extra_rc : 19
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)

# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
# define ISA_BITFIELD \
      uintptr_t nonpointer : 1;                                         \
      uintptr_t has_assoc : 1;                                         \
      uintptr_t has_cxx_dtor : 1;                                         \
      uintptr_t shiftcls : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating : 1;                                         \
      uintptr_t has_sidetable_rc : 1;                                         \
      uintptr_t extra_rc : 8
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)

在不同架构下 bits 内存布局有所不同,但是结构体中的成员和其代表的含义都是相同的,只是具体结构体的实现和位数可能有些差别。

isa 初始化

inline void objc_object::initClassIsa(Class cls) {
    if (DisableNonpointerIsa  ||  cls->instancesRequireRawIsa()) {
        initIsa(cls, false/*not nonpointer*/, false);
    } else {
        initIsa(cls, true/*nonpointer*/, false);
    }
}

inline void objc_object::initInstanceIsa(Class cls, bool hasCxxDtor) {
    initIsa(cls, true, hasCxxDtor);
}

不论是初始化类还是实例的 isa 都是调用了下面的方法

inline void 
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{   
    if (!nonpointer) {
        isa = isa_t((uintptr_t)cls);
    } else {
        isa_t newisa(0);
        newisa.bits = ISA_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.shiftcls = (uintptr_t)cls >> 3;
        isa = newisa;
    }
}

如果是老版本 isa 中就是保存 Class 类型的指针。如果是新版本,就对 64 位的 bits 进行配置

其中 ISA_MAGIC_VALUE 实际上配置了结构体中成员 nonpointermagic 的值。

  • nonpointer 如果是 0 那么 isa 中就是保存 Class 类型的指针,如果是 1 就保存的是 bits
  • magic 用于调试器判断当前对象是真的对象还是没有初始化的空间

接着配置了 has_cxx_dtor 的值,该值表示当前对象有 C++ 或者 ObjC 的析构器(destructor),如果没有析构器就会快速释放内存。

最后将类的指针右移了 3 位后赋值给了成员 shiftcls。这是因为类的指针是按照字节(8bits)对齐的,其指针后三位都是没有意义的 0,因此可以右移 3 位进行消除,以减小无意义的内存占用。

isa_t 成员

成员名 含义
nonpointer 区分新老版本,0(老版本)表示原始指针,也就是 Class cls,指针直接指向类对象;1(新版本)表示非指针,也就是 uintptr_t bits64 位的数据中不单单只保存类对象的指针
has_assoc 对象含有或者曾经含有关联引用(associated),没有关联引用的可以更快地释放
has_cxx_dtor 对象有 C++ 或者 ARC 的析构函数(destructor),如果没有析构函数可以更快地释放
shiftcls 保存类的指针的非零位,也就是原类指针右移 3 位消除为内存对其而产生的无意义的 0 后剩余的部分
magic 用于调试器判断当前对象是已实现的对象还是没有初始化的空间
weakly_referenced 当前对象被 ARC 的弱变量指向或者曾经被指向,没有弱引用的对象可以更快地释放
deallocating 对象正在释放(dealloc)
has_sidetable_rc 对象的引用计数太大了,存不下
extra_rc 对象的引用计数超过 1,会存在这个这个里面,如果引用计数为 10,该值就为 9

函数

公共函数

ISA

获取非 tagged pointer 类型的对象所属的类。也就是 non pointer 类型对象的情况

// ISA() assumes this is NOT a tagged pointer object
Class ISA();

inline Class 
objc_object::ISA() 
{
    ASSERT(!isTaggedPointer()); 
    // 通过位与运算获取数据中保存的类对象指针
    return (Class)(isa.bits & ISA_MASK);
}

rawISA

获取非 tagged pointer 类型并且也不是 non pointer 类型对象所属的类。也就是 isa 是类对象指针的情况

// rawISA() assumes this is NOT a tagged pointer object or a non pointer ISA
Class rawISA();

inline Class
objc_object::rawISA()
{
    ASSERT(!isTaggedPointer() && !isa.nonpointer);
    // 直接获取类对象指针
    return (Class)isa.bits;
}

getIsa

获取 tagged pointer 类型对象所属的类

// getIsa() allows this to be a tagged pointer object
Class getIsa();

inline Class 
objc_object::getIsa() 
{
    // 如果当前对象不是 tagged pointer 类型的,就通过 ISA() 函数获取类指针
    if (fastpath(!isTaggedPointer())) return ISA();

    extern objc_class OBJC_CLASS_$___NSUnrecognizedTaggedPointer;
    uintptr_t slot, ptr = (uintptr_t)this;
    Class cls;

    // 根据掩码从 isa 的 bits 中获取保存在原始数据中的类的标识符
    slot = (ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_SLOT_MASK;
    // 通过标识符从保存注册基础类的数组中查询对应的类
    cls = objc_tag_classes[slot];
    // 如果不是基础类,而是注册的扩展类,就根据 slot 去保存扩展类的数组中查询
    if (slowpath(cls == (Class)&OBJC_CLASS_$___NSUnrecognizedTaggedPointer)) {
        slot = (ptr >> _OBJC_TAG_EXT_SLOT_SHIFT) & _OBJC_TAG_EXT_SLOT_MASK;
        cls = objc_tag_ext_classes[slot];
    }
    return cls;
}

isaBits

获取 isa 中的 bits 原始数据

uintptr_t isaBits() const;

inline uintptr_t objc_object::isaBits() const {
    return isa.bits;
}

initIsa

初始化原始类型(不支持 nonpointer)的 isa

void initIsa(Class cls /*nonpointer=false*/);

inline void objc_object::initIsa(Class cls) {
    initIsa(cls, false, false);
}

initClassIsa

初始化类对象的 isa

void initClassIsa(Class cls /*nonpointer=maybe*/);

inline void objc_object::initClassIsa(Class cls) {
    if (DisableNonpointerIsa  ||  cls->instancesRequireRawIsa()) {
        // 如果关闭了 nonpointer 功能,或者类的实例对象需要原始 isa 
        initIsa(cls, false/*not nonpointer*/, false);
    } else {
        // 支持 nonpointer 功能
        initIsa(cls, true/*nonpointer*/, false);
    }
}

initProtocolIsa

初始化协议对象的 isa

void initProtocolIsa(Class cls /*nonpointer=maybe*/);

inline void objc_object::initProtocolIsa(Class cls) {
    // 可以看到,协议对象和类对象是相同的初始化方法
    return initClassIsa(cls);
}

initInstanceIsa

初始化实例对象的 isa

void initInstanceIsa(Class cls, bool hasCxxDtor);
inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    ASSERT(!cls->instancesRequireRawIsa());
    ASSERT(hasCxxDtor == cls->hasCxxDtor());

    // 支持 nonpointer
    initIsa(cls, true, hasCxxDtor);
}

所有类型的初始化 isa 方法的核心逻辑都放到了 initIsa 函数中,initIsa 函数在上面的「isa 初始化」中已经看过

changeIsa

更改已经完成初始化对象的 isa

// changeIsa() should be used to change the isa of existing objects.
// If this is a new object, use initIsa() for performance.
Class changeIsa(Class newCls);

inline Class 
objc_object::changeIsa(Class newCls)
{
    // This is almost always true but there are 
    // enough edge cases that we can't assert it.
    // assert(newCls->isFuture() || 
    // newCls->isInitializing() || newCls->isInitialized());

    ASSERT(!isTaggedPointer()); 

    isa_t oldisa;
    isa_t newisa;

    bool sideTableLocked = false;
    bool transcribeToSideTable = false;

    // 开启循环,直到 isa.bits 中的值被成功更新成 newisa.bits
    do {
        // 默认不需要将引用计数添加到 SideTables 中保存
        transcribeToSideTable = false;
        // 原子操作获取原 isa 指针
        oldisa = LoadExclusive(&isa.bits);
        if ((oldisa.bits == 0  ||  oldisa.nonpointer)  &&
            !newCls->isFuture()  &&  newCls->canAllocNonpointer())
        {
            // 如果新类不是未实现的懒加载类,并且新类支持 nonpointer,只要原 isa 指针指向的内存中没数据,或者原 isa 指针是 nonpointer 类型就走这部分逻辑
            // 0 -> nonpointer
            // nonpointer -> nonpointer
            // 如果原 isa 中没数据,和初始化 isa 的操作一样,设置新 isa 的 nonpointer 和 magic 位中的数据
            if (oldisa.bits == 0) newisa.bits = ISA_MAGIC_VALUE;
            // 如果原 isa 中有数据,直接将新 isa 指向原 isa
            else newisa = oldisa;
            // isa.magic is part of ISA_MAGIC_VALUE
            // isa.nonpointer is part of ISA_MAGIC_VALUE
            // 设置新 isa 的 has_cxx_dtor 位
            newisa.has_cxx_dtor = newCls->hasCxxDtor();
            // 新 isa 中保存新的类指针
            newisa.shiftcls = (uintptr_t)newCls >> 3;
        }
        else if (oldisa.nonpointer) {
            // 如果原 isa 支持 nonpointer 而新 isa 不支持,就走这部分逻辑
            // nonpointer -> raw pointer
            // Need to copy retain count et al to side table.
            // Acquire side table lock before setting isa to 
            // prevent races such as concurrent -release.
            // 锁住 SideTables 表
            if (!sideTableLocked) sidetable_lock();
            // 标识为 SideTables 表已加锁
            sideTableLocked = true;
            // 标识需要 SideTables 表来保存引用计数
            transcribeToSideTable = true;
            // 新 isa 用原始指针的方式保存新的类指针
            newisa.cls = newCls;
        }
        else {
            // 如果新老 isa 都不支持 nonpointer,就直接用新 isa 指向新的类指针
            // raw pointer -> raw pointer
            newisa.cls = newCls;
        }
    } while (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits));

    if (transcribeToSideTable) {
        // 如果需要转到 SideTables 表中保存,就像原 isa 中引用计数以及释放状态和弱引用情况复制到 SideTables 表中保存
        // Copy oldisa's retain count et al to side table.
        // oldisa.has_assoc: nothing to do
        // oldisa.has_cxx_dtor: nothing to do
        sidetable_moveExtraRC_nolock(oldisa.extra_rc, 
                                     oldisa.deallocating, 
                                     oldisa.weakly_referenced);
    }

    // 解锁已加锁的 SideTables 表
    if (sideTableLocked) sidetable_unlock();

    // 返回原 isa 的类指针
    if (oldisa.nonpointer) {
        // 如果原 isa 支持 nonpointer,通过其 shiftcls 成员获取类指针
        return (Class)((uintptr_t)oldisa.shiftcls << 3);
    }
    else {
        // 如果原 isa 不支持 nonpointer,直接返回类指针
        return oldisa.cls;
    }
}

在这个函数里,把更改对象的 isa 的操作分为了三种情况:

  1. 没数据或者是 nonpointer 类型的原 isa,变为 nonpointer 类型的新 isa,操作就是用原 isa 的数据初始化新 isa,然后新 isa 保存新的类指针
  2. nonpointer 类型的原 isa 变为原始指针类型的新 isa,这种情况下,除了将新 isa 直接指向新的类指针外,还需要把原来保存在原 isa 中的引用计数复制到 SideTables 表中保存
  3. 原始指针类型的原 isa 变为同类型的新 isa,直接将新 isa 指向新的类指针即可

hasNonpointerIsa

当前 isa 是否是 nonpointer 类型的

bool hasNonpointerIsa();

inline bool objc_object::hasNonpointerIsa() {
    // 返回 isa 的 nonpointer 类型标志位
    return isa.nonpointer;
}

isTaggedPointer

当前对象是否是 taggedPointer 类型的

bool isTaggedPointer();

inline bool objc_object::isTaggedPointer() {
    // 调用了下面的函数进行处理
    return _objc_isTaggedPointer(this);
}

static inline bool 
_objc_isTaggedPointer(const void * _Nullable ptr)
{
    // 通过与掩码进行位与运算获取标志位中的值
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

isBasicTaggedPointer

当前对象是否是基础类型的 taggedPointer

bool isBasicTaggedPointer();

inline bool 
objc_object::isBasicTaggedPointer() 
{
    // 如果是 taggedPointer 但不是扩展类型的,就是基础类型
    return isTaggedPointer()  &&  !isExtTaggedPointer();
}

isExtTaggedPointer

当前对象是否是扩展类型的 taggedPointer

bool isExtTaggedPointer();

inline bool objc_object::isExtTaggedPointer() {
    // 先解码混淆
    uintptr_t ptr = _objc_decodeTaggedPointer(this);
    // 同样是通过与掩码进行位与运算获取标志位中的值
    return (ptr & _OBJC_TAG_EXT_MASK) == _OBJC_TAG_EXT_MASK;
}

isClass

当前对象是否是一个类对象

bool isClass();

inline bool
objc_object::isClass()
{
    // 如果当前对象是 taggedPointer 类型,那就不是
    if (isTaggedPointer()) return false;
    // 根据当前对象所属的类是否是元类进行判断
    return ISA()->isMetaClass();
}

hasAssociatedObjects

当前对象是否有关联对象

bool hasAssociatedObjects();

inline bool objc_object::hasAssociatedObjects() {
    // 如果当前对象是 taggedPointer 类型,那就是是
    if (isTaggedPointer()) return true;
    // 如果当前对象的 isa 是 nonpointer 类型,那就根据 isa 的 has_assoc 标志位判断
    if (isa.nonpointer) return isa.has_assoc;
    // 默认为是
    return true;
}

setHasAssociatedObjects

设置当前对象的关联对象的状态

void setHasAssociatedObjects();

inline void objc_object::setHasAssociatedObjects() {
    // 如果当前对象是 taggedPointer 类型,不需要设置,默认就是 true
    if (isTaggedPointer()) return;

    // 开启循环,直到 isa.bits 中的值被成功更新成 newisa.bits
 retry:
    // 原子操作获取原 isa 中的数据
    isa_t oldisa = LoadExclusive(&isa.bits);
    // 创建新的临时变量保存数据
    isa_t newisa = oldisa;
    // 如果当前对象的 isa 不是 nonpointer 类型,或者当前对象已有关联对象
    if (!newisa.nonpointer  ||  newisa.has_assoc) {
        // 清除原 isa 中的数据的原子独占
        ClearExclusive(&isa.bits);
        // 直接返回
        return;
    }
    // 设置新变量中 has_assoc 位的值为 true 
    newisa.has_assoc = true;
    if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;
}

isWeaklyReferenced

当前对象是否被弱引用指向

bool isWeaklyReferenced();

inline bool
objc_object::isWeaklyReferenced()
{
    ASSERT(!isTaggedPointer());
    // 如果当前对象的 isa 是 nonpointer 类型,那就根据 isa 的 weakly_referenced 标志位判断
    if (isa.nonpointer) return isa.weakly_referenced;
    // 否则就去 SideTables 表中查
    else return sidetable_isWeaklyReferenced();
}

setWeaklyReferenced_nolock

设置当前对象的被弱引用指向的状态

void setWeaklyReferenced_nolock();

inline void
objc_object::setWeaklyReferenced_nolock()
{
    // 开启循环,直到 isa.bits 中的值被成功更新成 newisa.bits
 retry:
     // 原子操作获取原 isa 中的数据
    isa_t oldisa = LoadExclusive(&isa.bits);
    // 创建新的临时变量保存数据
    isa_t newisa = oldisa;
    // 如果当前对象的 isa 不是 nonpointer 类型
    if (slowpath(!newisa.nonpointer)) {
        // 清除原 isa 中的数据的原子独占
        ClearExclusive(&isa.bits);
        // 去 SideTables 表中设置弱引用指向状态
        sidetable_setWeaklyReferenced_nolock();
        // 直接返回
        return;
    }
    // 如果已设置过
    if (newisa.weakly_referenced) {
        // 清除原 isa 中的数据的原子独占
        ClearExclusive(&isa.bits);
        // 直接返回
        return;
    }
    // 设置新变量中 weakly_referenced 位的值为 true 
    newisa.weakly_referenced = true;
    if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;
}

hasCxxDtor

当前对象是否有 C++ 或者 ARC 的析构函数

bool hasCxxDtor();

inline bool
objc_object::hasCxxDtor()
{
    ASSERT(!isTaggedPointer());
    // 如果当前对象的 isa 是 nonpointer 类型,那就根据 isa 的 has_cxx_dtor 标志位判断
    if (isa.nonpointer) return isa.has_cxx_dtor;
    // 否则,就根据类对象的方法判断
    else return isa.cls->hasCxxDtor();
}

retain

引用计数 +1

id retain();

// Equivalent to calling [this retain], with shortcuts if there is no override
inline id 
objc_object::retain()
{
    ASSERT(!isTaggedPointer());
    
    // 如果当前对象没有自定义(override)retain 方法
    if (fastpath(!ISA()->hasCustomRR())) {
        // 调用 rootRetain 函数处理
        return rootRetain();
    }

    // 否则通过发消息的方式调用自定义的 retain 方法
    return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(retain));
}

release

引用计数 -1

void release();

inline void
objc_object::release()
{
    ASSERT(!isTaggedPointer());
    
    // 如果当前对象没有自定义(override)release 方法
    if (fastpath(!ISA()->hasCustomRR())) {
        // 调用 rootRelease 函数处理
        rootRelease();
        return;
    }
    
    // 否则通过发消息的方式调用自定义的 release 方法
    ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(release));
}

autorelease

添加到自动释放池

id autorelease();

inline id 
objc_object::autorelease()
{
    ASSERT(!isTaggedPointer());
    
    // 如果当前对象没有自定义(override)autorelease 方法
    if (fastpath(!ISA()->hasCustomRR())) {
        // 调用 rootAutorelease 函数处理
        return rootAutorelease();
    }

    // 否则通过发消息的方式调用自定义的 autorelease 方法
    return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(autorelease));
}

rootRetain

引用计数 +1 的默认实现

id rootRetain();

ALWAYS_INLINE id objc_object::rootRetain() {
    // 调用了私有函数 rootRetain 去实现
    return rootRetain(false, false);
}

rootRelease

引用计数 -1 的默认实现

bool rootRelease();

ALWAYS_INLINE bool objc_object::rootRelease() {
    // 调用了私有函数 rootRelease 去实现
    return rootRelease(true, false);
}

rootAutorelease

添加到自动释放池的默认实现

id rootAutorelease();

inline id 
objc_object::rootAutorelease()
{
    // 如果当前对象是 taggedPointer 类型,直接返回
    if (isTaggedPointer()) return (id)this;
    // 如果允许优化返回值,就直接返回,不添加自动释放池中,也不执行引用计数的加减操作,以消除多余的保留/释放对。
    // 简要的说,如果已优化的被调用者,发现调用者也得到了优化,那么就把把引用计数存放到 TLS(thread-local storage)中,跳过引用计数的相关过程
    if (prepareOptimizedReturn(ReturnAtPlus1)) return (id)this;

    // 如果不接受优化,就调用私有函数 rootAutorelease2 添加到自动释放池中
    return rootAutorelease2();
}

rootTryRetain

尝试去引用计数 +1

bool rootTryRetain();

ALWAYS_INLINE bool objc_object::rootTryRetain() {
    // 尝试调用私有函数 rootRetain 去 +1,并返回 +1 操作是否成功
    return rootRetain(true, false) ? true : false;
}

rootReleaseShouldDealloc

执行引用计数 -1 的默认实现,并返回是否要执行 dealloc,该方法不会自动执行销毁方法

bool rootReleaseShouldDealloc();

ALWAYS_INLINE bool objc_object::rootReleaseShouldDealloc() {
    // 调用了私有函数 rootRelease 去实现
    return rootRelease(false, false);
}

rootRetainCount

当前引用计数

uintptr_t rootRetainCount();

inline uintptr_t 
objc_object::rootRetainCount()
{
    // 如果当前对象是 taggedPointer 类型的,直接返回自己
    if (isTaggedPointer()) return (uintptr_t)this;

    // 为 SideTables 表加锁
    sidetable_lock();
    // 原子操作获取原 isa 指针
    isa_t bits = LoadExclusive(&isa.bits);
    // 清除原 isa 中的数据的原子独占
    ClearExclusive(&isa.bits);
    // 如果当前对象的 isa 是 nonpointer 类型的
    if (bits.nonpointer) {
        // 获取 isa 中 extra_rc 位的数据并 +1
        uintptr_t rc = 1 + bits.extra_rc;
        // 如果 isa 的 has_sidetable_rc 位也有数据,也就是引用计数太大 extra_rc 位存不下
        if (bits.has_sidetable_rc) {
            // 从 SideTables 表中获取剩下的引用计数,并累加
            rc += sidetable_getExtraRC_nolock();
        }
        // 为 SideTables 表解锁
        sidetable_unlock();
        // 返回计算完成的引用计数
        return rc;
    }

    // 为 SideTables 表解锁
    sidetable_unlock();
    // 如果当前对象的 isa 不是 nonpointer 类型的,从 SideTables 表中获取引用计数
    return sidetable_retainCount();
}

rootIsDeallocating

当前对象是否正在释放(dealloc)

bool rootIsDeallocating();

inline bool objc_object::rootIsDeallocating() {
    // 如果当前对象是 taggedPointer 类型,直接返回否
    if (isTaggedPointer()) return false;
    // 如果当前对象的 isa 是 nonpointer 类型,那就根据 isa 的 deallocating 标志位判断
    if (isa.nonpointer) return isa.deallocating;
    // 否则,就去 SideTables 表中查
    return sidetable_isDeallocating();
}

clearDeallocating

清除当前对象相关引用:弱引用和引用计数

void clearDeallocating();

inline void 
objc_object::clearDeallocating()
{
    if (slowpath(!isa.nonpointer)) {
        // 如果当前对象的 isa 不是 nonpointer 类型
        // 就去 SideTables 表中清除
        // Slow path for raw pointer isa.
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
        // 如果当前对象的 isa 是 nonpointer 类型
        // 如果有弱引用,或者引用计数过大使用 SideTables 表保存更多的引用计数
        // 就去 SideTables 表中清除弱引用和引用计数对应的数据
        // Slow path for non-pointer isa with weak refs and/or side table data.
        clearDeallocating_slow();
    }

    assert(!sidetable_present());
}

rootDealloc

对象销毁方法的默认实现

void rootDealloc();

inline void
objc_object::rootDealloc()
{
    // 如果当前对象是 taggedPointer 类型,直接返回否
    if (isTaggedPointer()) return;  // fixme necessary?

    if (fastpath(isa.nonpointer  &&  
                 !isa.weakly_referenced  &&  
                 !isa.has_assoc  &&  
                 !isa.has_cxx_dtor  &&  
                 !isa.has_sidetable_rc))
    {
        // 如果当前对象的 isa 是 nonpointer 类型的
        // 并且没有弱引用、没有关联对象、没有 C++ 析构函数、没有用 SideTables 表保存更多的引用计数
        // 直接释放当前对象
        assert(!sidetable_present());
        free(this);
    } 
    else {
        // 调用 object_dispose 函数去调用 C++ 析构函数、移除关联对象,并调用 clearDeallocating 函数移除弱引用和引用计数
        object_dispose((id)this);
    }
}

私有函数

initIsa

初始化 isa 数据结构

void initIsa(Class newCls, bool nonpointer, bool hasCxxDtor);

inline void 
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{ 
    ASSERT(!isTaggedPointer()); 
    
    if (!nonpointer) {
        // 如果当前对象的 isa 不是 nonpointer 类型
        // 直接将 isa 指向类对象
        isa = isa_t((uintptr_t)cls);
    } else {
        ASSERT(!DisableNonpointerIsa);
        ASSERT(!cls->instancesRequireRawIsa());
        // 如果当前对象的 isa 是 nonpointer 类型
        // 创建临时变量保存数据
        isa_t newisa(0);

        // 设置 isa 的 nonpointer 和 magic 位中的数据
        newisa.bits = ISA_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        // 设置 isa 的 has_cxx_dtor 位中的数据
        newisa.has_cxx_dtor = hasCxxDtor;
        // 设置 isa 的 shiftcls 位中的数据,保存类对象指针地址
        newisa.shiftcls = (uintptr_t)cls >> 3;

        // This write must be performed in a single store in some cases
        // (for example when realizing a class because other threads
        // may simultaneously try to use the class).
        // fixme use atomics here to guarantee single-store and to
        // guarantee memory order w.r.t. the class index table
        // ...but not too atomic because we don't want to hurt instantiation
        // 赋值保存新创建的 isa 
        isa = newisa;
    }
}

rootAutorelease2

普通的(未进过优化的)添加到自动释放池中

id rootAutorelease2();

__attribute__((noinline,used))
id 
objc_object::rootAutorelease2()
{
    ASSERT(!isTaggedPointer());
    // 获取自动释放池分页,并将当前对象添加进去
    return AutoreleasePoolPage::autorelease((id)this);
}

overrelease_error

过度释放对象错误

uintptr_t overrelease_error();

NEVER_INLINE uintptr_t objc_object::overrelease_error() {
    // 当对象被过度释放时 crash 并展示错误原因
    _objc_inform_now_and_on_crash("%s object %p overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug", object_getClassName((id)this), this);
    objc_overrelease_during_dealloc_error();
    return 0; // allow rootRelease() to tail-call this
}

rootRetain

引用计数 +1 的私有实现

id rootRetain(bool tryRetain, bool handleOverflow);

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;

    // 开启循环,直到 isa.bits 中的值被成功更新成 newisa.bits
    do {
        transcribeToSideTable = false;
        // 原子操作获取原 isa 中的数据
        oldisa = LoadExclusive(&isa.bits);
        // 新 isa 指向原 isa 
        newisa = oldisa;
        // 如果当前对象的 isa 不是 nonpointer 类型
        if (slowpath(!newisa.nonpointer)) {
            // 清除原 isa 中的数据的原子独占
            ClearExclusive(&isa.bits);
            // 如果当前对象的 isa 指向的类对象是元类(也就是说当前对象不是实例对象,而是类对象),直接返回
            if (rawISA()->isMetaClass()) return (id)this;
            // 如果不需要去尝试 +1 并且 SideTables 表锁住了,就将其解锁
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            // 如果需要尝试 +1 就调用 sidetable_tryRetain 函数处理 +1
            if (tryRetain) return sidetable_tryRetain() ? (id)this : nil;
            // 否则就调用 sidetable_retain 函数处理 +1
            else return sidetable_retain();
        }
        // don't check newisa.fast_rr; we already called any RR overrides
        // 如果需要尝试 +1 但是当前对象正在销毁中
        if (slowpath(tryRetain && newisa.deallocating)) {
            // 清除原 isa 中的数据的原子独占
            ClearExclusive(&isa.bits);
            // 如果不需要去尝试 +1 并且 SideTables 表锁住了,就将其解锁
            if (!tryRetain && sideTableLocked) sidetable_unlock();
            // 直接返回
            return nil;
        }
        // 创建临时变量保存 isa 中引用计数是否溢出
        uintptr_t carry;
        // 为 isa 中的 extra_rc 位 +1 ,并保存引用计数
        newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc++

        // 如果 extra_rc 位已经存满导致溢出
        if (slowpath(carry)) {
            // newisa.extra_rc++ overflowed
            // 如果不需要处理上溢的情况
            if (!handleOverflow) {
                // 清除原 isa 中的数据的原子独占
                ClearExclusive(&isa.bits);
                // 调用 rootRetain_overflow 函数去处理溢出情况的 +1 操作
                return rootRetain_overflow(tryRetain);
            }
            // Leave half of the retain counts inline and 
            // prepare to copy the other half to the side table.
            // 如果不需要尝试 +1 并且 SideTables 表未加锁,就将其加锁
            if (!tryRetain && !sideTableLocked) sidetable_lock();
            // 标识 SideTables 表已加锁
            sideTableLocked = true;
            // 标识需要 SideTables 表来保存引用计数
            transcribeToSideTable = true;
            // 新 isa 的 extra_rc 标志位只保留总数的一半的引用计数
            newisa.extra_rc = RC_HALF;
            // 新 isa 的 has_sidetable_rc 标志位标识引用计数已溢出
            newisa.has_sidetable_rc = true;
        }
    } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));

    // 如果需要 SideTables 表来保存引用计数
    if (slowpath(transcribeToSideTable)) {
        // Copy the other half of the retain counts to the side table.
        // 将引用计数总数的另一半复制到 SideTables 表中保存
        sidetable_addExtraRC_nolock(RC_HALF);
    }
    
    // 如果不需要去尝试 +1 并且 SideTables 表锁住了,就将其解锁
    if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
    return (id)this;
}

这个函数中实现了引用计数 +1 的逻辑,从中可以看到其策略为:

  1. 如果当前对象的 isa 不是 nonpointer 类型
    • 直接将引用计数保存到 SideTables 表中
  2. 如果当前对象的 isa 是 nonpointer 类型
    • 如果 isa 的 extra_rc 标志位没满,就将引用计数保存到 extra_rc 标志位中
    • 如果 isa 的 extra_rc 标志位溢出,就将 extra_rc 标志位总数的一半保留,另一半存到 SideTables 表

rootRelease

引用计数 -1 的私有实现

bool rootRelease(bool performDealloc, bool handleUnderflow);

ALWAYS_INLINE bool 
objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
{
    // 如果当前对象是 taggedPointer 类型的
    // 不需要操作,直接返回
    if (isTaggedPointer()) return false;

    bool sideTableLocked = false;

    isa_t oldisa;
    isa_t newisa;

 retry:
    // 开启循环,直到 isa.bits 中的值被成功更新成 newisa.bits
    do {
        // 原子操作获取原 isa 中的数据并保存到临时变量 newisa 中
        oldisa = LoadExclusive(&isa.bits);
        newisa = oldisa;
        // 如果当前对象的 isa 不是 nonpointer 类型
        if (slowpath(!newisa.nonpointer)) {
            // 清除原 isa 中的数据的原子独占
            ClearExclusive(&isa.bits);
            // 如果当前对象的 isa 指向的类对象是元类(也就是说当前对象不是实例对象,而是类对象),直接返回并标识未释放
            if (rawISA()->isMetaClass()) return false;
            // 如果 SideTables 表锁住了,就将其解锁
            if (sideTableLocked) sidetable_unlock();
            // 否则就调用 sidetable_release 函数处理 -1
            return sidetable_release(performDealloc);
        }
        // don't check newisa.fast_rr; we already called any RR overrides
        // 创建临时变量保存 isa 中引用计数是否溢出
        uintptr_t carry;
        // 为 isa 中的 extra_rc 位 -1 ,并保存引用计数
        newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc--
        // 如果 extra_rc 位已经清零导致溢出
        if (slowpath(carry)) {
            // don't ClearExclusive()
            // 跳转到 underflow 进行逻辑处理
            goto underflow;
        }
    } while (slowpath(!StoreReleaseExclusive(&isa.bits, 
                                             oldisa.bits, newisa.bits)));
    
    // 走到这说明引用计数的 -1 操作已完成
    
    // 如果 SideTables 表锁住了,就将其解锁
    if (slowpath(sideTableLocked)) sidetable_unlock();
    // 返回并标识未释放
    return false;

 underflow:
    // newisa.extra_rc-- underflowed: borrow from side table or deallocate

    // abandon newisa to undo the decrement
    // 放弃掉前面对 newisa 的处理,重新指向原 isa 
    newisa = oldisa;

    // 如果 isa 的 has_sidetable_rc 标志位标识引用计数已溢出
    if (slowpath(newisa.has_sidetable_rc)) {
        // 如果不需要处理下溢的情况
        if (!handleUnderflow) {
            // 清除原 isa 中的数据的原子独占
            ClearExclusive(&isa.bits);
            // 调用 rootRelease_underflow 函数去处理溢出情况的 -1 操作
            return rootRelease_underflow(performDealloc);
        }

        // Transfer retain count from side table to inline storage.
        // 如果 SideTables 表未加锁
        if (!sideTableLocked) {
            // 清除原 isa 中的数据的原子独占
            ClearExclusive(&isa.bits);
            // 为 SideTables 表加锁
            sidetable_lock();
            // 标识 SideTables 表已加锁
            sideTableLocked = true;
            // Need to start over to avoid a race against 
            // the nonpointer -> raw pointer transition.
            // 跳转到 retry 重新开始,避免 isa 从 nonpointer 类型转换成原始类型导致的问题
            goto retry;
        }

        // Try to remove some retain counts from the side table. 
        // 先从 SideTables 表中获取并删除一部分(isa 的 extra_rc 标志位总数一半的数量)引用计数
        // 获取并删除的数量可能比请求的数量少
        size_t borrowed = sidetable_subExtraRC_nolock(RC_HALF);

        // To avoid races, has_sidetable_rc must remain set 
        // even if the side table count is now zero.

        // 如果从 SideTables 表中获取到了引用计数
        if (borrowed > 0) {
            // Side table retain count decreased.
            // Try to add them to the inline count.
            // 将获得的引用计数保存到 isa 的 extra_rc 标志位中
            newisa.extra_rc = borrowed - 1;  // redo the original decrement too
            // 将 isa.bits 中的值更新为 newisa.bits
            bool stored = StoreReleaseExclusive(&isa.bits, 
                                                oldisa.bits, newisa.bits);
            // 如果更新失败
            if (!stored) {
                // Inline update failed. 
                // Try it again right now. This prevents livelock on LL/SC 
                // architectures where the side table access itself may have 
                // dropped the reservation.
                // 重新原子操作获取原 isa 中的数据并保存到临时变量 newisa2 中
                isa_t oldisa2 = LoadExclusive(&isa.bits);
                isa_t newisa2 = oldisa2;
                // 如果当前对象的 isa 是 nonpointer 类型
                if (newisa2.nonpointer) {
                    // 将从 SideTables 表中获取的引用计数保存到 newisa2 的 extra_rc 标志位中
                    uintptr_t overflow;
                    newisa2.bits = 
                        addc(newisa2.bits, RC_ONE * (borrowed-1), 0, &overflow);
                    // 如果没有溢出再次将 isa.bits 中的值更新为 newisa2.bits
                    if (!overflow) {
                        stored = StoreReleaseExclusive(&isa.bits, oldisa2.bits, 
                                                       newisa2.bits);
                    }
                }
            }
            
            // 如果还是更新失败
            if (!stored) {
                // Inline update failed.
                // Put the retains back in the side table.
                // 把从 SideTables 表中获取的引用计数重新保存回表中
                sidetable_addExtraRC_nolock(borrowed);
                // 跳转到 retry 重新开始
                goto retry;
            }

            // Decrement successful after borrowing from side table.
            // This decrement cannot be the deallocating decrement - the side 
            // table lock and has_sidetable_rc bit ensure that if everyone 
            // else tried to -release while we worked, the last one would block.
            // 完成对 SideTables 表中数据的操作后,为其解锁
            sidetable_unlock();
            // 返回并标识未释放
            return false;
        }
        else {
            // Side table is empty after all. Fall-through to the dealloc path.
        }
    }

    // Really deallocate.
    // 能走到这,说明引用计数在 -1 操作后清零
    
    // 如果当前对象正在释放
    if (slowpath(newisa.deallocating)) {
        // 清除原 isa 中的数据的原子独占
        ClearExclusive(&isa.bits);
        // 如果 SideTables 表加锁便为其解锁
        if (sideTableLocked) sidetable_unlock();
        // 调用 overrelease_error 函数返回重复释放错误
        return overrelease_error();
        // does not actually return
    }
    // 标识当前对象正在释放
    newisa.deallocating = true;
    // 如果更新 isa.bits 的值为 newisa.bits 失败,跳转到 retry 再处理
    if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;
    // 如果 SideTables 表加锁便为其解锁
    if (slowpath(sideTableLocked)) sidetable_unlock();
    // 建立非原子和宽松原子访问的内存同步排序
    __c11_atomic_thread_fence(__ATOMIC_ACQUIRE);
    // 如果需要调用释放方法
    if (performDealloc) {
        // 通过发消息的方式调用 dealloc 方法
        ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));
    }
    // 返回并标识已释放
    return true;
}

引用计数 -1 的逻辑看起来很长,但其实就三步:

  1. 先在 retry 中做 -1 操作
    • 如果当前对象的 isa 不是 nonpointer 类型,直接去 SideTables 表中 -1
    • 如果当前对象的 isa 是 nonpointer 类,就去 isa 的 extra_rc 标志位 -1
  2. 如果在 retry 中出现了下溢,就去 underflow 中把 SideTables 表中存储的引用计数拿出来存到 isa 的 extra_rc 标志位中,再跳回 retry 中做 -1 操作
  3. 如果发现 SideTables 表中存储的引用计数也为零,就发送消息调用 dealloc 方法进行释放

rootRetain_overflow

处理上溢的引用计数 +1 操作

id rootRetain_overflow(bool tryRetain);

NEVER_INLINE id objc_object::rootRetain_overflow(bool tryRetain) {
    // 将处理上溢参数设置为 true
    return rootRetain(tryRetain, true);
}

rootRelease_underflow

处理下溢的引用计数 -1 操作

uintptr_t rootRelease_underflow(bool performDealloc);

NEVER_INLINE uintptr_t objc_object::rootRelease_underflow(bool performDealloc) {
    // 将处理下溢参数设置为 true
    return rootRelease(performDealloc, true);
}

clearDeallocating_slow

清除 SideTables 表中保存当前对象弱引用和引用计数对应的数据

void clearDeallocating_slow();

NEVER_INLINE void
objc_object::clearDeallocating_slow()
{
    ASSERT(isa.nonpointer  &&  (isa.weakly_referenced || isa.has_sidetable_rc));

    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    // 为 SideTable 表加锁
    table.lock();
    // 如果当前对象有被弱引用
    if (isa.weakly_referenced) {
        // 调用 weak_clear_no_lock 函数将保存在 SideTable 表中,所有弱引用当前对象的指针置 nil,并将当前对象从表中移除
        weak_clear_no_lock(&table.weak_table, (id)this);
    }
    // 如果当前对象引用计数上溢
    if (isa.has_sidetable_rc) {
        // 清除当前对象保存在 SideTable 表中的引用计数
        table.refcnts.erase(this);
    }
    // 为 SideTable 表解锁
    table.unlock();
}

sidetable_lock

为 SideTable 表加锁

void sidetable_lock();

void 
objc_object::sidetable_lock()
{
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    // 为 SideTable 表加锁
    table.lock();
}

sidetable_unlock

为 SideTable 表解锁

void sidetable_unlock();

void 
objc_object::sidetable_unlock()
{
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    // 为 SideTable 表解锁
    table.unlock();
}

sidetable_moveExtraRC_nolock

将引用计数和弱引用数据保存到 SideTable 表中,该函数用于将 isa 从 nonpointer 类型转为原指针类型时使用

void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);

void 
objc_object::sidetable_moveExtraRC_nolock(size_t extra_rc, 
                                          bool isDeallocating, 
                                          bool weaklyReferenced)
{
    ASSERT(!isa.nonpointer);        // should already be changed to raw pointer
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 获取当前对象的引用计数表
    size_t& refcntStorage = table.refcnts[this];
    size_t oldRefcnt = refcntStorage;
    // not deallocating - that was in the isa
    ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);  
    ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);  

    // 创建临时变量标识是否上溢
    uintptr_t carry;
    // 将传入的引用计数的数量条件到表中保存
    size_t refcnt = addc(oldRefcnt, extra_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
    // 如果发生了上溢,设置标识为已满
    if (carry) refcnt = SIDE_TABLE_RC_PINNED;
    // 如果正在销毁对象,设置标识为正在销毁
    if (isDeallocating) refcnt |= SIDE_TABLE_DEALLOCATING;
    // 如果被弱引用了,设置标识为被弱引用
    if (weaklyReferenced) refcnt |= SIDE_TABLE_WEAKLY_REFERENCED;

    // 更新数据
    refcntStorage = refcnt;
}

sidetable_addExtraRC_nolock

将一部分引用计数从 isa 的 extra_rc 标志位移动到 SideTable 表中

bool sidetable_addExtraRC_nolock(size_t delta_rc);

bool objc_object::sidetable_addExtraRC_nolock(size_t delta_rc) {
    ASSERT(isa.nonpointer);
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 获取当前对象的引用计数表
    size_t& refcntStorage = table.refcnts[this];
    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 =
            SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
        return true;
    }
    else {
        // 否则,更新数据
        refcntStorage = newRefcnt;
        return false;
    }
}

sidetable_subExtraRC_nolock

将一部分引用计数从 SideTable 表中移动到 isa 的 extra_rc 标志位

size_t sidetable_subExtraRC_nolock(size_t delta_rc);

size_t 
objc_object::sidetable_subExtraRC_nolock(size_t delta_rc)
{
    ASSERT(isa.nonpointer);
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 获取当前对象的引用计数表
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果引用计数表为空,直接返回 0
    if (it == table.refcnts.end()  ||  it->second == 0) {
        // Side table retain count is zero. Can't borrow.
        return 0;
    }
    size_t oldRefcnt = it->second;

    // isa-side bits should not be set here
    ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
    ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);

    // 从表中移除传入的引用计数的数量
    size_t newRefcnt = oldRefcnt - (delta_rc << SIDE_TABLE_RC_SHIFT);
    ASSERT(oldRefcnt > newRefcnt);  // shouldn't underflow
    // 更新数据
    it->second = newRefcnt;
    // 返回实际从表中获取的数量
    return delta_rc;
}

sidetable_getExtraRC_nolock

获取 SideTable 表中保存的引用计数数量

size_t sidetable_getExtraRC_nolock();

size_t objc_object::sidetable_getExtraRC_nolock() {
    ASSERT(isa.nonpointer);
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果引用计数表为空,直接返回 0
    if (it == table.refcnts.end()) return 0;
    // 否则返回表中保存的引用计数数量
    else return it->second >> SIDE_TABLE_RC_SHIFT;
}

sidetable_isDeallocating

获取 SideTable 表中保存的当前对象是否正在销毁的状态

bool sidetable_isDeallocating();

bool 
objc_object::sidetable_isDeallocating()
{
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // NO SPINLOCK HERE
    // _objc_rootIsDeallocating() is called exclusively by _objc_storeWeak(), 
    // which already acquired the lock on our behalf.


    // fixme can't do this efficiently with os_lock_handoff_s
    // if (table.slock == 0) {
    // _objc_fatal("Do not call -_isDeallocating.");
    // }

    // 获取当前对象的引用计数表 
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果表不为空,并且 SIDE_TABLE_DEALLOCATING 标志位有数据,就返回 true,否则返回 false
    return (it != table.refcnts.end()) && (it->second & SIDE_TABLE_DEALLOCATING);
}

sidetable_clearDeallocating

清除 isa 是原始指针类型对象的 SideTable 表

void sidetable_clearDeallocating();

void 
objc_object::sidetable_clearDeallocating()
{
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // clear any weak table items
    // clear extra retain count and deallocating bit
    // (fixme warn or abort if extra retain count == 0 ?)
    // 为 SideTable 表加锁
    table.lock();
    // 获取当前对象的引用计数表 
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果表不为空
    if (it != table.refcnts.end()) {
        // 如果被弱指针引用过,就将所有弱引用当前对象的指针置 nil,并将当前对象从表中移除
        if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
            weak_clear_no_lock(&table.weak_table, (id)this);
        }
        // 清除引用计数数据
        table.refcnts.erase(it);
    }
    // 为 SideTable 表解锁
    table.unlock();
}

sidetable_isWeaklyReferenced

获取 SideTable 表中保存的当前对象是否被弱指针引用过

bool sidetable_isWeaklyReferenced();

bool objc_object::sidetable_isWeaklyReferenced() {
    bool result = false;

    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    // 为 SideTable 表加锁
    table.lock();

    // 获取当前对象的引用计数表 
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果表不为空
    if (it != table.refcnts.end()) {
        // 获取表中 SIDE_TABLE_WEAKLY_REFERENCED 标志位的数据
        result = it->second & SIDE_TABLE_WEAKLY_REFERENCED;
    }

    // 为 SideTable 表解锁
    table.unlock();

    // 返回结果
    return result;
}

sidetable_setWeaklyReferenced_nolock

将当前对象的弱引用状态保存到 SideTable 表中

void sidetable_setWeaklyReferenced_nolock();

void objc_object::sidetable_setWeaklyReferenced_nolock() {
#if SUPPORT_NONPOINTER_ISA
    ASSERT(!isa.nonpointer);
#endif

    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 设置表中 SIDE_TABLE_WEAKLY_REFERENCED 标志位的数据
    table.refcnts[this] |= SIDE_TABLE_WEAKLY_REFERENCED;
}

sidetable_retain

将 SideTable 表中的引用计数 +1,用于 isa 为原始指针的情况

id sidetable_retain();

id
objc_object::sidetable_retain()
{
#if SUPPORT_NONPOINTER_ISA
    ASSERT(!isa.nonpointer);
#endif
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    
    // 为 SideTable 表加锁
    table.lock();
    // 获取当前对象的引用计数表 
    size_t& refcntStorage = table.refcnts[this];
    // 如果引用计数表没有满
    if (! (refcntStorage & SIDE_TABLE_RC_PINNED)) {
        // 为引用计数 +1
        refcntStorage += SIDE_TABLE_RC_ONE;
    }
    // 为 SideTable 表解锁
    table.unlock();

    return (id)this;
}

sidetable_retain_slow

未找到实现

id sidetable_retain_slow(SideTable& table);

sidetable_release

将 SideTable 表中的引用计数 -1,用于 isa 为原始指针的情况

uintptr_t sidetable_release(bool performDealloc = true);

uintptr_t
objc_object::sidetable_release(bool performDealloc)
{
#if SUPPORT_NONPOINTER_ISA
    ASSERT(!isa.nonpointer);
#endif
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 创建临时变量标识是否执行销毁方法
    bool do_dealloc = false;

    // 为 SideTable 表加锁
    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)) {
        // 如果表没满,执行 -1 操作
        refcnt -= SIDE_TABLE_RC_ONE;
    }
    // 为 SideTable 表解锁
    table.unlock();
    // 如果需要销毁,并且传参标识要执行销毁方法
    if (do_dealloc  &&  performDealloc) {
        // 通过发消息的方式调用 dealloc 方法
        ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));
    }
    // 返回是否要执行销毁方法
    return do_dealloc;
}

sidetable_release_slow

未找到实现

uintptr_t sidetable_release_slow(SideTable& table, bool performDealloc = true);

sidetable_tryRetain

尝试将 SideTable 表中的引用计数 +1,用于 isa 为原始指针的情况

bool sidetable_tryRetain();

bool objc_object::sidetable_tryRetain() {
#if SUPPORT_NONPOINTER_ISA
    ASSERT(!isa.nonpointer);
#endif
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // NO SPINLOCK HERE
    // _objc_rootTryRetain() is called exclusively by _objc_loadWeak(), 
    // which already acquired the lock on our behalf.

    // fixme can't do this efficiently with os_lock_handoff_s
    // if (table.slock == 0) {
    // _objc_fatal("Do not call -_tryRetain.");
    // }

    // 创建临时变量标识是否 +1 成功
    bool result = true;
    
    auto it = table.refcnts.try_emplace(this, SIDE_TABLE_RC_ONE);
    auto &refcnt = it.first->second;
    if (it.second) {
        // there was no entry
        // 如果无数据,不做处理
    } else if (refcnt & SIDE_TABLE_DEALLOCATING) {
        // 如果正在销毁,不做处理
        result = false;
    } else if (! (refcnt & SIDE_TABLE_RC_PINNED)) {
        // 如果表没满,执行 +1 操作
        refcnt += SIDE_TABLE_RC_ONE;
    }
    
    // 返回执行结果
    return result;
}

sidetable_retainCount

获取 SideTable 表中保存的引用计数的数量,用于 isa 为原始指针的情况

uintptr_t sidetable_retainCount();

uintptr_t
objc_object::sidetable_retainCount()
{
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];

    // 创建临时变量保存数量
    size_t refcnt_result = 1;
    
    // 为 SideTable 表加锁
    table.lock();
    // 获取当前对象的引用计数表 
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果表不为空
    if (it != table.refcnts.end()) {
        // this is valid for SIDE_TABLE_RC_PINNED too
        // 获取表中保存的数量
        refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;
    }
    // 为 SideTable 表解锁
    table.unlock();
    // 返回结果
    return refcnt_result;
}

sidetable_present

用于调试时,断言 SideTable 表中未保存该对象

bool sidetable_present();

bool
objc_object::sidetable_present()
{
    // 创建变量标识表中未保存该对象
    bool result = false;
    // 获取当前对象的 SideTable 表
    SideTable& table = SideTables()[this];
    
    // 为 SideTable 表加锁
    table.lock();

    // 获取当前对象的引用计数表 
    RefcountMap::iterator it = table.refcnts.find(this);
    // 如果当前对象没数据,返回 true
    if (it != table.refcnts.end()) result = true;

    // 如果弱引用表中没数据,返回 true
    if (weak_is_registered_no_lock(&table.weak_table, (id)this)) result = true;

    // 为 SideTable 表解锁
    table.unlock();

    // 返回结果
    return result;
}

今天的文章Objective-C 之 Runtime 对象分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19370.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注