Objective-C 之 Runtime 数据结构篇

807 阅读46分钟

对象

当不确定一个对象的类型的时候,通常使用 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;
}

在获取一个对象所属的类时,返回值的类型是 Class

- (Class)class;

Class 代表一个类,它是指向一个类对象的指针

typedef struct objc_class *Class;

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

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
};

可以看到 objc_class 中有三个成员。

  • 首先,objc_class 是继承自 objc_object,也就是说类也是一个对象。其中从 objc_object 继承下来的成员 isa,它包含了当前类对象所属的元类的信息。

  • 其次,成员 superclass 指向了该类的父类

  • 接着,成员 cache 中缓存了最近调用过的方法

  • 最后,成员 bits 根据注释可以知道 bits = 指向 class_rw_t 类型结构体的指针 + 自定义的 rr/alloc 标识

函数

公共函数

data

获取类中的数据

// 返回值是一个 class_rw_t 类型的指针,说明类中的数据是以 class_rw_t 类型保存的
class_rw_t *data() const {
    // 通过调用成员 bits 的公共函数 data() 获取数据
    return bits.data();
}

setData

设置类中的数据

// 设置值要求是一个 class_rw_t 类型的指针
void setData(class_rw_t *newData) {
    // 通过调用成员 bits 的公共函数 setData() 设置数据
    bits.setData(newData);
}

setInfo

设置标志位信息

void setInfo(uint32_t set) {
    // 必须满足要么是一个未实现的懒加载类,要么已经实现
    ASSERT(isFuture()  ||  isRealized());
    // 先调用 data 函数获取类的 class_rw_t 实例数据
    // 再调动 class_rw_t 实例的 setFlags 函数设置标志位信息
    data()->setFlags(set);
}

clearInfo

清除标志位信息

void clearInfo(uint32_t clear) {
    // 必须满足要么是一个未实现的懒加载类,要么已经实现
    ASSERT(isFuture()  ||  isRealized());
    // 先调用 data 函数获取类的 class_rw_t 实例数据
    // 再调动 class_rw_t 实例的 clearFlags 函数清除标志位信息
    data()->clearFlags(clear);
}

changeInfo

设置和清除标志位信息

void changeInfo(uint32_t set, uint32_t clear) {
    // 必须满足要么是一个未实现的懒加载类,要么已经实现
    ASSERT(isFuture()  ||  isRealized());
    // 要设置的标志位和要清除的标志位不能是同一个
    ASSERT((set & clear) == 0);
    // 先调用 data 函数获取类的 class_rw_t 实例数据
    // 再调动 class_rw_t 实例的 changeFlags 函数设置和清除标志位信息
    data()->changeFlags(set, clear);
}

hasCustomRR

获取当前类及其超类是否自定义了 retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 这些方法之一

bool hasCustomRR() const {
    // 调用成员 bits 的 getBit 函数获取 FAST_HAS_DEFAULT_RR 标志位的数据
    return !bits.getBit(FAST_HAS_DEFAULT_RR);
}

setHasDefaultRR

标识当前类及其超类没有自定义retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 这些方法之一

void setHasDefaultRR() {
    // 调用成员 bits 的 setBits 函数设置 FAST_HAS_DEFAULT_RR 标志位的数据
    bits.setBits(FAST_HAS_DEFAULT_RR);
}

setHasCustomRR

标识当前类及其超类自定义了retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 这些方法之一

void setHasCustomRR() {
    // 调用成员 bits 的 clearBits 函数将 FAST_HAS_DEFAULT_RR 标志位的数据置零
    bits.clearBits(FAST_HAS_DEFAULT_RR);
}

hasCustomAWZ

获取当前类及其超类是否自定义了 alloc/allocWithZone: 这些方法之一

bool hasCustomAWZ() const {
    // 调用成员 cache 的 getBit 函数获取 FAST_CACHE_HAS_DEFAULT_AWZ 标志位的数据
    return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ);
}

setHasDefaultAWZ

标识当前类及其超类没有自定义 alloc/allocWithZone: 这些方法之一

void setHasDefaultAWZ() {
    // 调用成员 cache 的 setBits 函数设置 FAST_CACHE_HAS_DEFAULT_AWZ 标志位的数据
    cache.setBit(FAST_CACHE_HAS_DEFAULT_AWZ);
}

setHasCustomAWZ

标识当前类及其超类自定义了 alloc/allocWithZone: 这些方法之一

void setHasCustomAWZ() {
    // 调用成员 cache 的 clearBits 函数将 FAST_CACHE_HAS_DEFAULT_AWZ 标志位的数据置零
    cache.clearBit(FAST_CACHE_HAS_DEFAULT_AWZ);
}

hasCustomCore

获取当前类及其超类是否自定义了 new/self/class/respondsToSelector/isKindOfClass 这些方法之一

bool hasCustomCore() const {
    // 调用成员 cache 的 getBit 函数获取 FAST_CACHE_HAS_DEFAULT_CORE 标志位的数据
    return !cache.getBit(FAST_CACHE_HAS_DEFAULT_CORE);
}

setHasDefaultCore

标识当前类及其超类没有自定义 new/self/class/respondsToSelector/isKindOfClass 这些方法之一

void setHasDefaultCore() {
    // 调用成员 cache 的 setBits 函数设置 FAST_CACHE_HAS_DEFAULT_CORE 标志位的数据
    return cache.setBit(FAST_CACHE_HAS_DEFAULT_CORE);
}

setHasCustomCore

标识当前类及其超类自定义了 new/self/class/respondsToSelector/isKindOfClass 这些方法之一

void setHasCustomCore() {
    // 调用成员 cache 的 clearBits 函数将 FAST_CACHE_HAS_DEFAULT_CORE 标志位的数据置零
    return cache.clearBit(FAST_CACHE_HAS_DEFAULT_CORE);
}

hasCxxCtor

获取当前类及其超类是否有 .cxx_construct C++ 构造方法的实现

bool hasCxxCtor() {
    // 当前类必须已经实现
    ASSERT(isRealized());
    // 调用成员 cache 的 getBit 函数获取 FAST_CACHE_HAS_CXX_CTOR 标志位的数据
    return cache.getBit(FAST_CACHE_HAS_CXX_CTOR);
}

setHasCxxCtor

标识当前类及其超类有 .cxx_construct C++ 构造方法的实现

void setHasCxxCtor() {
    // 调用成员 cache 的 setBits 函数设置 FAST_CACHE_HAS_CXX_CTOR 标志位的数据
    cache.setBit(FAST_CACHE_HAS_CXX_CTOR);
}

hasCxxDtor

获取当前类及其超类是否有 .cxx_destruct C++ 析构方法的实现

bool hasCxxDtor() {
    // 当前类必须已经实现
    ASSERT(isRealized());
    // 调用成员 cache 的 getBit 函数获取 FAST_CACHE_HAS_CXX_DTOR 标志位的数据
    return cache.getBit(FAST_CACHE_HAS_CXX_DTOR);
}

setHasCxxDtor

标识当前类及其超类有 .cxx_destruct C++ 析构方法的实现

void setHasCxxDtor() {
    // 调用成员 cache 的 setBits 函数设置 FAST_CACHE_HAS_CXX_DTOR 标志位的数据
    cache.setBit(FAST_CACHE_HAS_CXX_DTOR);
}

instancesRequireRawIsa

获取类的实例对象是否需要原始 isa(isa 直接指向类)

bool instancesRequireRawIsa() {
    // 调用成员 cache 的 getBit 函数获取 FAST_CACHE_REQUIRES_RAW_ISA 标志位的数据
    return cache.getBit(FAST_CACHE_REQUIRES_RAW_ISA);
}

setInstancesRequireRawIsa

标识类的实例对象需要原始 isa(isa 直接指向类)

void setInstancesRequireRawIsa() {
    // 调用成员 cache 的 setBits 函数设置 FAST_CACHE_REQUIRES_RAW_ISA 标志位的数据
    cache.setBit(FAST_CACHE_REQUIRES_RAW_ISA);
}

setInstancesRequireRawIsaRecursively

将当前类及其所有子类,全部标识为其类的实例对象需要原始 isa(isa 直接指向类)

void setInstancesRequireRawIsaRecursively(bool inherited = false);

void objc_class::setInstancesRequireRawIsaRecursively(bool inherited)
{
    // 获取当前类对象
    Class cls = (Class)this;
    // 加锁
    runtimeLock.assertLocked();
    
    // 如果当前类的实例对象已经被要求是原始 isa,就直接返回
    if (instancesRequireRawIsa()) return;
    
    // 遍历当前类及其子类
    foreach_realized_class_and_subclass(cls, [=](Class c){
        // 如果该类的实例对象已经被要求是原始 isa,就直接跳过
        if (c->instancesRequireRawIsa()) {
            return false;
        }

        // 标识该类的实例对象需要是原始 isa 类型
        c->setInstancesRequireRawIsa();

        // 打印日志相关
        if (PrintRawIsa) c->printInstancesRequireRawIsa(inherited || c != cls);
        return true;
    });
}

printInstancesRequireRawIsa

void printInstancesRequireRawIsa(bool inherited);

void
objc_class::printInstancesRequireRawIsa(bool inherited)
{
    // 必须已经标识为要打印原始 isa
    ASSERT(PrintRawIsa);
    // 必须是该类的实例对象已经被要求是原始 isa
    ASSERT(instancesRequireRawIsa());
    // 打印原始 isa 相关信息
    _objc_inform("RAW ISA:  %s%s%s", nameForLogging(), 
                 isMetaClass() ? " (meta)" : "", 
                 inherited ? " (inherited)" : "");
}

canAllocNonpointer

获取当前类的实例对象可否以 Nonpointer 类型创建

bool canAllocNonpointer() {
    // 必须是正常类,而非懒加载类
    ASSERT(!isFuture());
    // 如果该类的实例对象不要求是原始 isa 类型就可以用 Nonpointer 类型
    return !instancesRequireRawIsa();
}

isSwiftStable

获取当前类是否为 Swift 最新稳定类

bool isSwiftStable() {
    // 调用成员 bits 的 isSwiftStable 函数获取
    return bits.isSwiftStable();
}

isSwiftLegacy

获取当前类是否为 Swift 老版稳定类

bool isSwiftLegacy() {
    // 调用成员 bits 的 isSwiftLegacy 函数获取
    return bits.isSwiftLegacy();
}

isAnySwift

获取当前类是否为 Swift 类

bool isAnySwift() {
    // 调用成员 bits 的 isAnySwift 函数获取
    return bits.isAnySwift();
}

isSwiftStable_ButAllowLegacyForNow

获取当前类是否为 Swift 类

bool isSwiftStable_ButAllowLegacyForNow() {
    // 调用成员 bits 的 isSwiftStable_ButAllowLegacyForNow 函数获取
    // 其中 isSwiftStable_ButAllowLegacyForNow 函数内部调用了 isAnySwift 函数
    return bits.isSwiftStable_ButAllowLegacyForNow();
}

isStubClass

获取当前类是否为存根类

bool isStubClass() const {
    // 获取类对象的 isa 数据
    uintptr_t isa = (uintptr_t)isaBits();
    // 如果 isa 数据在 5 位以内就是存根类
    return 1 <= isa && isa < 16;
}

isUnfixedBackwardDeployingStableSwift

判断是否为未修复的向后兼容的老版 Swift 稳定类

bool isUnfixedBackwardDeployingStableSwift() {
    // Only classes marked as Swift legacy need apply.
    // 只处理老版 Swift 稳定类
    if (!bits.isSwiftLegacy()) return false;

    // Check the true legacy vs stable distinguisher.
    // The low bit of Swift's ClassFlags is SET for true legacy
    // and UNSET for stable pretending to be legacy.
    // 获取 Swift 类的标志位。即类对象地址的第 1 位的值
    uint32_t swiftClassFlags = *(uint32_t *)(&bits + 1);
    // 根据标志位判断是否为真的老版 Swift 稳定类
    bool isActuallySwiftLegacy = bool(swiftClassFlags & 1);
    // 返回结果
    return !isActuallySwiftLegacy;
}

fixupBackwardDeployingStableSwift

修复向后兼容的老版 Swift 稳定类的标志位

void fixupBackwardDeployingStableSwift() {
    // 如果是未修复的向后兼容的老版 Swift 稳定类
    if (isUnfixedBackwardDeployingStableSwift()) {
        // Class really is stable Swift, pretending to be pre-stable.
        // Fix its lie.
        // 设置其标志位为稳定版 Swift 类,并清除老版 Swift 稳定版标志位
        bits.setIsSwiftStable();
    }
}

swiftMetadataInitializer

获取 Swift 元类初始化器

_objc_swiftMetadataInitializer swiftMetadataInitializer() {
    // 调用成员 bits 的 swiftMetadataInitializer 函数获取
    return bits.swiftMetadataInitializer();
}

hasAutomaticIvars

获取该类的成员变量是否为自动布局

bool hasAutomaticIvars() {
    // 通过 data 函数获取保存在 ro 成员中的 flags 标志位数据
    // 获取其标志位 RO_IS_ARC 和 RO_HAS_WEAK_WITHOUT_ARC 中保存的数据
    // 如果标志位标示该类是用 ARC 编译的类,或者类不是 ARC 编译的类,但具有 ARC 样式的弱 ivar 布局,就返回 true
    return data()->ro->flags & (RO_IS_ARC | RO_HAS_WEAK_WITHOUT_ARC);
}

isARC

获取该类的成员变量是否由 ARC 管理

bool isARC() {
    // 通过 data 函数获取保存在 ro 成员中的 flags 标志位数据
    // 获取其标志位 RO_IS_ARC 中保存的数据
    return data()->ro->flags & RO_IS_ARC;
}

forbidsAssociatedObjects

获取该类是否禁止其实例对象关联对象

bool forbidsAssociatedObjects() {
    // 通过 data 函数获取保存在 ro 成员中的 flags 标志位数据
    // 获取其标志位 RW_FORBIDS_ASSOCIATED_OBJECTS 中保存的数据
    return (data()->flags & RW_FORBIDS_ASSOCIATED_OBJECTS);
}

shouldGrowCache

获取该类是否要增加缓存

bool shouldGrowCache() {
    // 直接返回 true,也就是一定会增加缓存
    return true;
}

setShouldGrowCache

设置该类是否要增加缓存

void setShouldGrowCache(bool) {
    // 无实现
    // fixme good or bad for memory use?
}

isInitializing

获取该类是否正在初始化

bool isInitializing() {
    // 通过 getMeta 函数获取该类的元类
    // 通过 data 函数获取该类元类的数据
    // 获取其标志位 RW_INITIALIZING 中保存的数据
    return getMeta()->data()->flags & RW_INITIALIZING;
}

setInitializing

设置该类是否正在初始化的状态

void setInitializing() {
    // 当前类不能是元类
    ASSERT(!isMetaClass());
    // 通过 ISA 函数获取该类的元类
    // 通过 setInfo 函数设置其元类 RW_INITIALIZING 标志位的数据
    ISA()->setInfo(RW_INITIALIZING);
}

isInitialized

获取该类是否已经初始化

bool isInitialized() {
    // 通过 getMeta 函数获取该类的元类
    // 通过 data 函数获取该类元类的数据
    // 获取其标志位 RW_INITIALIZED 中保存的数据
    return getMeta()->data()->flags & RW_INITIALIZED;
}

setInitialized

设置该类是否已经初始化的状态

void setInitialized();

void 
objc_class::setInitialized()
{
    Class metacls;
    Class cls;

    // 当前类不能是元类
    ASSERT(!isMetaClass());

    // 获取当前类的类对象并保存到临时变量中
    cls = (Class)this;
    // 获取当前类的元类并保存到临时变量中
    metacls = cls->ISA();

    // 加锁
    mutex_locker_t lock(runtimeLock);

    // Special cases:
    // - NSObject AWZ  class methods are default.
    // - NSObject RR   class and instance methods are default.
    // - NSObject Core class and instance methods are default.
    // adjustCustomFlagsForMethodChange() also knows these special cases.
    // attachMethodLists() also knows these special cases.

    // 扫描当前类的 +alloc / +allocWithZone: 方法是否为默认实现,并设置标志位进行标识
    objc::AWZScanner::scanInitializedClass(cls, metacls);
    // 扫描当前类的 retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 方法是否为默认实现,并设置标志位进行标识
    objc::RRScanner::scanInitializedClass(cls, metacls);
    // 扫描当前类的 +new, ±class, ±self, ±isKindOfClass:, ±respondsToSelector 方法是否为默认实现,并设置标志位进行标识
    objc::CoreScanner::scanInitializedClass(cls, metacls);

    // Update the +initialize flags.
    // Do this last.
    // 通过 changeInfo 函数设置其元类 RW_INITIALIZED 标志位的数据,并清除 RW_INITIALIZING 标志位的数据
    metacls->changeInfo(RW_INITIALIZED, RW_INITIALIZING);
}

isLoadable

获取该类是否为可加载的

bool isLoadable() {
    // 必须是已经实现的类
    ASSERT(isRealized());
    // 任何一个类都注册了 +load 方法,所以都是可加载的,就返回 true
    return true;  // any class registered for +load is definitely loadable
}

getLoadMethod

获取当前类的 +load 方法实现

IMP getLoadMethod();

IMP 
objc_class::getLoadMethod()
{
    // 加锁
    runtimeLock.assertLocked();

    const method_list_t *mlist;

    // 当前类必须已实现
    ASSERT(isRealized());
    // 当前类对象所属的类必须已实现
    ASSERT(ISA()->isRealized());
    // 当前类不能是元类
    ASSERT(!isMetaClass());
    // 当前类对象所属的类必须是元类
    ASSERT(ISA()->isMetaClass());

    // 通过 ISA 函数获取该类的元类
    // 通过 data 函数设置其元类数据
    // 通过调用其元类 ro 成员的 baseMethods 函数获取在编译时生成的方法列表
    mlist = ISA()->data()->ro->baseMethods();
    // 遍历类方法列表,如果类方法的 SEL 为 load,就返回其 IMP
    if (mlist) {
        for (const auto& meth : *mlist) {
            const char *name = sel_cname(meth.name);
            if (0 == strcmp(name, "load")) {
                return meth.imp;
            }
        }
    }

    return nil;
}

isRealized

获取该类是否已实现

bool isRealized() const {
    // 前提为当前类不是存根类
    // 通过 data 函数获取该类的数据
    // 获取其标志位 RW_REALIZED 中保存的数据
    return !isStubClass() && (data()->flags & RW_REALIZED);
}

isFuture

获取该类是否为懒加载类

bool isFuture() const {
    // 通过 data 函数获取该类的数据
    // 获取其标志位 RW_FUTURE 中保存的数据
    return data()->flags & RW_FUTURE;
}

isMetaClass

获取该类是否为元类

bool isMetaClass() {
    // 当前类必须存在
    ASSERT(this);
    // 当前类必须已实现
    ASSERT(isRealized());
#if FAST_CACHE_META
    // 通过其 cache 成员的 getBit 函数获取标志位 FAST_CACHE_META 中保存的数据
    return cache.getBit(FAST_CACHE_META);
#else
    return data()->ro->flags & RO_META;
#endif
}

isMetaClassMaybeUnrealized

获取该类是否为元类,但该类可能还未实现

bool isMetaClassMaybeUnrealized() {
    // 调用成员 bits 的 safe_ro 函数安全的获取其编译时产生 ro 数据
    // 获取其标志位 RO_META 中保存的数据
    return bits.safe_ro()->flags & RO_META;
}

getMeta

获取该类的元类

Class getMeta() {
    // 如果当前类就是元类,便返回自己
    if (isMetaClass()) return (Class)this;
    // 否则通过 ISA 函数获取其元类
    else return this->ISA();
}

isRootClass

获取该类是否为根类

bool isRootClass() {
    // 如果当前类的 superclass 成员为空,那当前类便是根类
    return superclass == nil;
}

isRootMetaclass

获取该类是否为根元类

bool isRootMetaclass() {
    // 如果当前类对象所属的类就是自己,那当前类便是根元类
    return ISA() == (Class)this;
}

mangledName

获取该类的修饰别名

const char *mangledName() { 
    // fixme can't assert locks here
    // 当前类必须存在
    ASSERT(this);

    if (isRealized()  ||  isFuture()) {
        // 如果当前类已实现,或者是一个懒加载类
        // 通过 data 函数获取保存在 ro 成员中 name 的数据
        return data()->ro->name;
    } else {
        // 否则,先通过 data 函数获取 class_ro_t 类型的数据,然后获取数据中 name 的值
        return ((const class_ro_t *)data())->name;
    }
}

demangledName

获取该类的解析别名

const char *demangledName();

mutex_t DemangleCacheLock;
static objc::DenseSet<const char *> *DemangleCache;
const char *
objc_class::demangledName()
{
    // Return previously demangled name if available.
    // 如果当前类已实现,或者为懒加载类
    if (isRealized()  ||  isFuture()) {
        // 通过 data 函数获取该类的数据
        // 获取数据中成员 demangledName 保存的值
        // 如果有值的话,直接返回
        if (data()->demangledName) return data()->demangledName;
    }

    // Try demangling the mangled name.
    // 获取当前类的修饰别名
    const char *mangled = mangledName();
    // 生成符合 Swift-v1-mangled 样式的解析别名
    char *de = copySwiftV1DemangledName(mangled);
    // 如果当前类已实现,或者为懒加载类
    if (isRealized()  ||  isFuture()) {
        // Class is already realized or future. 
        // Save demangling result in rw data.
        // We may not own runtimeLock so use an atomic operation instead.
        // 将生成的解析别名保存到 rw 的 demangledName 成员中
        if (! OSAtomicCompareAndSwapPtrBarrier(nil, (void*)(de ?: mangled), 
                                               (void**)&data()->demangledName)) 
        {
            // 如果没保存成功,就将解析别名释放掉
            if (de) free(de);
        }
        // 返回即通过
        return data()->demangledName;
    }

    // Class is not yet realized.
    // 如果没能生成符合 Swift-v1-mangled 样式的解析别名,就直接返回当前类的修饰别名
    if (!de) {
        // Name is not mangled. Return it without caching.
        return mangled;
    }

    // Class is not yet realized and name is mangled.
    // Allocate the name but don't save it in the class.
    // Save the name in a side cache instead to prevent leaks.
    // When the class is actually realized we may allocate a second
    // copy of the name, but we don't care.
    // (Previously we would try to realize the class now and save the
    // name there, but realization is more complicated for Swift classes.)

    // Only objc_copyClassNamesForImage() should get here.
    // fixme lldb's calls to class_getName() can also get here when
    // interrogating the dyld shared cache. (rdar://27258517)
    // fixme runtimeLock.assertLocked();
    // fixme ASSERT(realize);

    const char *cached;
    {
        // 加锁
        mutex_locker_t lock(DemangleCacheLock);
        // 如果没有 DemangleCache 容器,就生成一个
        if (!DemangleCache) {
            DemangleCache = new objc::DenseSet<const char *>{};
        }
        // 将解析别名插入到 DemangleCache 首位
        cached = *DemangleCache->insert(de).first;
    }
    // 如果没能成功缓存,就将解析别名释放掉
    if (cached != de) free(de);
    // 返回缓存中保存的解析别名
    return cached;
}

nameForLogging

获取该类用于显示/打印的名称

const char *nameForLogging();

const char *
objc_class::nameForLogging()
{
    // Handle the easy case directly.
    // 如果当前类已实现,或者为懒加载类
    if (isRealized()  ||  isFuture()) {
        // 通过 data 函数获取该类的数据中成员 demangledName 有值的话直接返回
        if (data()->demangledName) return data()->demangledName;
    }

    char *result;

    // 获取当前类的修饰别名
    const char *name = mangledName();
    // 获取当前类符合 Swift-v1-mangled 样式的解析别名
    char *de = copySwiftV1DemangledName(name);
    // 如果有解析别名,就返回解析别名
    if (de) result = de;
    // 否则就返回修饰别名
    else result = strdup(name);

    // 将名称保存在线程本地FIFO缓冲区中
    saveTemporaryString(result);
    // 返回结果
    return result;
}

unalignedInstanceStart

获取该类未经过字节对齐处理前的成员变量布局的开始位置

uint32_t unalignedInstanceStart() const {
    // 当前类必须已实现
    ASSERT(isRealized());
    // 通过 data 函数获取该类的数据
    // 获取数据中的 ro 成员
    // 返回 ro 成员 instanceStart 中保存的值
    return data()->ro->instanceStart;
}

alignedInstanceStart

获取该类已经过对齐处理后的成员变量布局的开始位置

uint32_t alignedInstanceStart() const {
    // 对当前类未经过字节对齐处理前的成员变量布局的开始位置进行字节对齐处理,并返回
    return word_align(unalignedInstanceStart());
}

unalignedInstanceSize

获取该类未经过字节对齐处理前的实例对象内存布局的大小

uint32_t unalignedInstanceSize() const {
    // 当前类必须已实现
    ASSERT(isRealized());
    // 通过 data 函数获取该类的数据
    // 获取数据中的 ro 成员
    // 返回 ro 成员 instanceSize 中保存的值
    return data()->ro->instanceSize;
}

alignedInstanceSize

获取该类已经过对齐处理后的实例对象内存布局的大小

uint32_t alignedInstanceSize() const {
    // 对当前类未经过字节对齐处理前的实例对象内存布局的大小进行字节对齐处理,并返回
    return word_align(unalignedInstanceSize());
}

instanceSize

获取该类实例对象占用的内存大小

size_t instanceSize(size_t extraBytes) const {
    // 调用成员 cache 的 hasFastInstanceSize 函数获取实例对象内存布局的大小,如果有就直接返回
    if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
        return cache.fastInstanceSize(extraBytes);
    }
    
    // 获取当前类已经过对齐处理后的实例对象内存布局的大小,并加上传入的参数
    size_t size = alignedInstanceSize() + extraBytes;
    // CF requires all objects be at least 16 bytes.
    // 实例对象内存布局的大小最小为 16 字节
    if (size < 16) size = 16;
    // 返回大小
    return size;
}

setInstanceSize

设置该类实例对象占用的内存大小

void setInstanceSize(uint32_t newSize) {
    // 当前类必须已实现
    ASSERT(isRealized());
    // 当前类设置过正在实现标识
    ASSERT(data()->flags & RW_REALIZING);
    // 如果新大小与 instanceSize 中保存的不同
    if (newSize != data()->ro->instanceSize) {
        // rw 的 ro 成员必须是 class_ro_t 类型的数据
        ASSERT(data()->flags & RW_COPIED_RO);
        // 将新数据保存到 instanceSize 中 
        *const_cast<uint32_t *>(&data()->ro->instanceSize) = newSize;
    }
    // 调用成员 cache 的 setFastInstanceSize 函数保存新的实例对象内存大小
    cache.setFastInstanceSize(newSize);
}

cache_t

struct cache_t {
    explicit_atomic<struct bucket_t *> _buckets;
    explicit_atomic<mask_t> _mask;
    uint16_t _occupied;
};

用来缓存调用过方法的是一个 cache_t 类型的结构体,共有三个成员。

第一个成员 _buckets 是一个 bucket_t 类型的数组。

第二个成员 _mask 保存着总共申请用来缓存的数量。

第三个成员 _flags 用于在 64 位时,保存一些类的相关信息。

第四个成员 _occupied 保存着目前已经使用缓存的数量。

公共函数

emptyBuckets

获取一个空容器

static bucket_t *emptyBuckets();

struct bucket_t *cache_t::emptyBuckets()
{   
    // 获取一个空容器,转换成 bucket_t * 类型后返回
    return (bucket_t *)&_objc_empty_cache;
}

buckets

获取当前容器

struct bucket_t *buckets();

struct bucket_t *cache_t::buckets() 
{
    // 调用成员 `_buckets` 的 load 函数获取当前正在使用的容器
    return _buckets.load(memory_order::memory_order_relaxed);
}

mask

获取当前缓存大小

mask_t mask();

mask_t cache_t::mask() 
{
    // 调用成员 `_mask` 的 load 函数获取当前的缓存大小
    return _mask.load(memory_order::memory_order_relaxed);
}

occupied

获取当前已使用多少缓存

mask_t occupied();

mask_t cache_t::occupied() 
{
    // 直接返回成员 `_occupied` 
    return _occupied;
}

incrementOccupied

增加缓存的数量

void incrementOccupied();

void cache_t::incrementOccupied() 
{
    // 成员 `_occupied` 计数 +1
    _occupied++;
}

setBucketsAndMask

重新设置容器和掩码

void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask);

void cache_t::setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask)
{
    // objc_msgSend uses mask and buckets with no locks.
    // It is safe for objc_msgSend to see new buckets but old mask.
    // (It will get a cache miss but not overrun the buckets' bounds).
    // It is unsafe for objc_msgSend to see old buckets and new mask.
    // Therefore we write new buckets, wait a lot, then write new mask.
    // objc_msgSend reads mask first, then buckets.

#ifdef __arm__
    // ensure other threads see buckets contents before buckets pointer
    mega_barrier();

    _buckets.store(newBuckets, memory_order::memory_order_relaxed);
    
    // ensure other threads see new buckets before new mask
    mega_barrier();
    
    _mask.store(newMask, memory_order::memory_order_relaxed);
    _occupied = 0;
#elif __x86_64__ || i386
    // ensure other threads see buckets contents before buckets pointer
    // 保存新的容器
    _buckets.store(newBuckets, memory_order::memory_order_release);
    
    // ensure other threads see new buckets before new mask
    // 保存新的掩码
    _mask.store(newMask, memory_order::memory_order_release);
    // 缓存计数置空
    _occupied = 0;
#else
#error Don't know how to do setBucketsAndMask on this architecture.
#endif
}

initializeToEmpty

初始化缓存

void initializeToEmpty();

void cache_t::initializeToEmpty()
{
    // 将当前内存中所有字节置空
    bzero(this, sizeof(*this));
    // 将容器置空
    _buckets.store((bucket_t *)&_objc_empty_cache, memory_order::memory_order_relaxed);
}

capacity

获取当前缓存容量

unsigned capacity();

unsigned cache_t::capacity()
{
    // 调用 mask 获取缓存大小,如果有就 +1 后返回,没有就返回 0
    return mask() ? mask()+1 : 0; 
}

isConstantEmptyCache

获取当前缓存是否为空

bool isConstantEmptyCache();

bool cache_t::isConstantEmptyCache()
{
    // 一共有两个判断条件
    // 一个是没有使用量
    // 一个是空容器
    return 
        occupied() == 0  &&  
        buckets() == emptyBucketsForCapacity(capacity(), false);
}

canBeFreed

获取当前缓存是否可以释放

bool canBeFreed();

bool cache_t::canBeFreed()
{
    // 如果缓存不为空,就可以释放
    return !isConstantEmptyCache();
}

getBit

获取指定标志位数据

bool getBit(uint16_t flags) const {
    // 通过位与获取成员 _flags 中指定位的数据
    return _flags & flags;
}

setBit

设置指定标志位数据

void setBit(uint16_t set) {
    // 原子性的设置成员 _flags 中指定位的数据
    __c11_atomic_fetch_or((_Atomic(uint16_t) *)&_flags, set, __ATOMIC_RELAXED);
}

clearBit

清空指定标志位数据

void clearBit(uint16_t clear) {
    // 原子性的清空成员 _flags 中指定位的数据
    __c11_atomic_fetch_and((_Atomic(uint16_t) *)&_flags, ~clear, __ATOMIC_RELAXED);
}

hasFastInstanceSize

是否保存有快速获取实例变量的内存布局大小

bool hasFastInstanceSize(size_t extra) const
{
    // 如果参数 extra 是编译时常量,并且为 0,那么就取成员 _flags 掩码 FAST_CACHE_ALLOC_MASK16 的值
    if (__builtin_constant_p(extra) && extra == 0) {
        return _flags & FAST_CACHE_ALLOC_MASK16;
    }
    // 否则就取成员 _flags 掩码 FAST_CACHE_ALLOC_MASK 的值
    return _flags & FAST_CACHE_ALLOC_MASK;
}

fastInstanceSize

快速获取实例变量的内存布局大小

size_t fastInstanceSize(size_t extra) const
{
    // 成员 _flags 中必须有保存
    ASSERT(hasFastInstanceSize(extra));

    if (__builtin_constant_p(extra) && extra == 0) {
        // 如果参数 extra 是编译时常量,并且为 0,那么就取成员 _flags 掩码 FAST_CACHE_ALLOC_MASK16 的值
        return _flags & FAST_CACHE_ALLOC_MASK16;
    } else {
        // 否则就取成员 _flags 掩码 FAST_CACHE_ALLOC_MASK 的值
        // 再加上传入的参数
        // 接着减去通过 setFastInstanceSize 添加的 FAST_CACHE_ALLOC_DELTA16
        // 最后通过 align16 函数对结果进行 16 字节对齐
        size_t size = _flags & FAST_CACHE_ALLOC_MASK;
        // remove the FAST_CACHE_ALLOC_DELTA16 that was added
        // by setFastInstanceSize
        return align16(size + extra - FAST_CACHE_ALLOC_DELTA16);
    }
}

setFastInstanceSize

设置快速获取实例变量的内存布局大小

void setFastInstanceSize(size_t newSize)
{
    // Set during realization or construction only. No locking needed.
    // 通过位与 FAST_CACHE_ALLOC_MASK 的反码,将成员 _flags 的数据初始化
    uint16_t newBits = _flags & ~FAST_CACHE_ALLOC_MASK;
    uint16_t sizeBits;

    // Adding FAST_CACHE_ALLOC_DELTA16 allows for FAST_CACHE_ALLOC_MASK16
    // to yield the proper 16byte aligned allocation size with a single mask
    // 先通过 word_align 函数将传入的参数进行字节对齐
    // 然后加上 FAST_CACHE_ALLOC_DELTA16 掩码,
    // 这么做的目的是可以通过 FAST_CACHE_ALLOC_MASK16 使用单个掩码获取正确的以 16字节对齐内存布局大小
    sizeBits = word_align(newSize) + FAST_CACHE_ALLOC_DELTA16;
    // 最后位与 FAST_CACHE_ALLOC_MASK 掩码
    sizeBits &= FAST_CACHE_ALLOC_MASK;
    // 只有当传入的大小没有从保存的位数中溢出,才通过位或运算保存到 newBits。否则,newBits 中保存的是初始化的数据
    if (newSize <= sizeBits) {
        newBits |= sizeBits;
    }
    // 成员 _flags 保存处理好的数据
    _flags = newBits;
}

bytesForCapacity

获取指定缓存容量占用的字节大小

static size_t bytesForCapacity(uint32_t cap);

size_t cache_t::bytesForCapacity(uint32_t cap) 
{
    // fixme put end marker inline when capacity+1 malloc is inefficient
    // 先获取结构体 bucket_t 占用的内存字节大小
    // 再乘上传入的缓存容量 + 1 后的值
    return sizeof(bucket_t) * (cap + 1);
}

endMarker

获取缓存的结束标识

static struct bucket_t * endMarker(struct bucket_t *b, uint32_t cap);

bucket_t *cache_t::endMarker(struct bucket_t *b, uint32_t cap) 
{
    // bytesForCapacity() chooses whether the end marker is inline or not
    // 先根据容量计算缓存占用的内存大小
    // 再计算缓存指针内存地址加上占用的大小
    // 最后 -1 就是缓存在内存中的结束地址
    return (bucket_t *)((uintptr_t)b + bytesForCapacity(cap)) - 1;
}

reallocate

重新生成缓存

void reallocate(mask_t oldCapacity, mask_t newCapacity, bool freeOld);

ALWAYS_INLINE
void cache_t::reallocate(mask_t oldCapacity, mask_t newCapacity, bool freeOld)
{
    // 保存当前缓存容器
    bucket_t *oldBuckets = buckets();
    // 根据容量生成一个新缓存容器
    bucket_t *newBuckets = allocateBuckets(newCapacity);

    // Cache's old contents are not propagated. 
    // This is thought to save cache memory at the cost of extra cache fills.
    // fixme re-measure this

    ASSERT(newCapacity > 0);
    ASSERT((uintptr_t)(mask_t)(newCapacity-1) == newCapacity-1);

    // 用新的缓存容器和容量重置当前缓存
    setBucketsAndMask(newBuckets, newCapacity - 1);
    
    // 如果需要释放老缓存
    if (freeOld) {
        // 把老缓存添加到 garbage_refs 表中,以便稍后释放
        cache_collect_free(oldBuckets, oldCapacity);
    }
}

insert

保存发送消息到缓存中

void insert(Class cls, SEL sel, IMP imp, id receiver);

ALWAYS_INLINE
void cache_t::insert(Class cls, SEL sel, IMP imp, id receiver)
{
#if CONFIG_USE_CACHE_LOCK
    cacheUpdateLock.assertLocked();
#else
    runtimeLock.assertLocked();
#endif

    ASSERT(sel != 0 && cls->isInitialized());

    // Use the cache as-is if it is less than 3/4 full
    // 缓存占用量 +1
    mask_t newOccupied = occupied() + 1;
    // 获取老的缓存容量
    unsigned oldCapacity = capacity(), capacity = oldCapacity;
    if (slowpath(isConstantEmptyCache())) {
        // 如果当前缓存为空
        // Cache is read-only. Replace it.
        // 如果老容量也是空的,那么容量就设置为 4
        if (!capacity) capacity = INIT_CACHE_SIZE;
        // 调用 reallocate 函数重新生成容量为 4 的缓存
        reallocate(oldCapacity, capacity, /* freeOld */false);
    }
    else if (fastpath(newOccupied <= capacity / 4 * 3)) {
        // 如果新缓存占用量不足总容量的 3/4,就不作处理
        // Cache is less than 3/4 full. Use it as-is.
    }
    else {
        // 如果新缓存占用量超过了总容量的 3/4
        // 如果老容量为空的,那么容量就设置为 4;否则,新容量扩充为之前的两倍
        capacity = capacity ? capacity * 2 : INIT_CACHE_SIZE;
        // 总容量大小不能超过 65536(即 2 的 256 次方)
        if (capacity > MAX_CACHE_SIZE) {
            capacity = MAX_CACHE_SIZE;
        }
        // 调用 reallocate 函数重新生成容量为 65536 的缓存
        reallocate(oldCapacity, capacity, true);
    }

    // 获取缓存
    bucket_t *b = buckets();
    // 获取容量
    mask_t m = capacity - 1;
    // 根据方法名和容量生成一个哈希值
    mask_t begin = cache_hash(sel, m);
    mask_t i = begin;

    // Scan for the first unused slot and insert there.
    // There is guaranteed to be an empty slot because the
    // minimum size is 4 and we resized at 3/4 full.
    // 开始遍历,直到找到一个空的卡槽将消息相关数据插入
    do {
        // 如果缓存中哈希值 i 对应的是一个空的卡槽
        if (fastpath(b[i].sel() == 0)) {
            // 当前缓存使用量 +1
            incrementOccupied();
            // 将消息相关数据插入到哈希值 i 对应的位置
            b[i].set<Atomic, Encoded>(sel, imp, cls);
            // 跳出循环,并直接返回
            return;
        }
        // 如果缓存中哈希值 i 对应的卡槽已经保存了该方法
        if (b[i].sel() == sel) {
            // The entry was added to the cache by some other thread
            // before we grabbed the cacheUpdateLock.
            // 也是跳出循环,并直接返回
            return;
        }
        // 如果哈希值 i 对应的卡槽已经保存了其他方法,就查看哈希值(i + 1)对应的卡槽
    } while (fastpath((i = cache_next(i, m)) != begin));

    // 如果遍历完整个缓存的容量的每一个位置,都没能将方法插进去
    // 就调用 bad_cache 函数打印日志,说明这个缓存有问题
    cache_t::bad_cache(receiver, (SEL)sel, cls);
}

bucket_t

struct bucket_t {
#if __arm64__
    explicit_atomic<uintptr_t> _imp;
    explicit_atomic<SEL> _sel;
#else
    explicit_atomic<SEL> _sel;
    explicit_atomic<uintptr_t> _imp;
#endif
};

bucket_t 结构体中存储了键值对,其中 _imp 是一个函数指针,指向函数的具体实现,_sel 是方法名或者方法标识。也就说 _buckets 是一个哈希表,里面通过键值对的方式保存着调用过的方法。键为 SEL 类型,值为 IMP 类型。

SEL

typedef struct objc_selector *SEL;

从声明上看 SEL 是一个 objc_selector 结构体指针的别名;从实现中找,发现 SEL 是指向一个 char * 变量,也就是说其实它就是个映射到方法的 C 字符串,可以理解为是区分方法的 ID。

SEL 只与方法名有关:

  • 不同类中相同名字的方法所对应的方法选择器是相同的
  • 方法名相同而变量类型不同所对应的方法选择器也是相同的

IMP

#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

IMP 是一个函数指针,它指向函数的具体实现。

class_data_bits_t

bits 中保存着类的相关信息,它是一个 class_data_bits_t 类型的结构体,

struct class_data_bits_t {
    // Values are the FAST_ flags above.
    uintptr_t bits;
};

这个结构体中的成员和 isa_t 结构体相同,都是通过一个 64 位的 bits 储存信息

// class is a Swift class from the pre-stable Swift ABI
#define FAST_IS_SWIFT_LEGACY    (1UL<<0)
// class is a Swift class from the stable Swift ABI
#define FAST_IS_SWIFT_STABLE    (1UL<<1)
// class or superclass has default retain/release/autorelease/retainCount/
//   _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
#define FAST_HAS_DEFAULT_RR     (1UL<<2)
// data pointer
#define FAST_DATA_MASK          0x00007ffffffffff8UL

通过定义的宏可以知道这些位都代表了什么含义

  • FAST_IS_SWIFT_LEGACY 是否是来自预稳定 Swift ABI 的 Swift 类
  • FAST_IS_SWIFT_STABLE 是否是来自已稳定 Swift ABI 的 Swift 类
  • FAST_HAS_DEFAULT_RR 当前类或者父类含有默认的 retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference 方法
  • FAST_DATA_MASK 数据指针

搜索 FAST_DATA_MASK 的使用位置,可以找到一对取值/赋值方法

class_rw_t* data() const {
    return (class_rw_t *)(bits & FAST_DATA_MASK);
}
void setData(class_rw_t *newData)
{
    ASSERT(!data()  ||  (newData->flags & (RW_REALIZING | RW_FUTURE)));
    // Set during realization or construction only. No locking needed.
    // Use a store-release fence because there may be concurrent
    // readers of data and data's contents.
    uintptr_t newBits = (bits & ~FAST_DATA_MASK) | (uintptr_t)newData;
    atomic_thread_fence(memory_order_release);
    bits = newBits;
}

通过这两方法,可以知道数据指针是一个 class_rw_t 类型的指针

class_rw_t

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint16_t version;
    uint16_t witness;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;

结构体 class_rw_t 名称中的 rw 代表 readwrite,其中的成员 ro 是一个 class_ro_t 类型的指针,这里的 ro 代表 readonlyro 中存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。而 class_rw_t 提供了运行时对类拓展的能力,其中的 methodspropertiesprotocols 保存着通过 Category 在运行时添加的方法、属性及协议。

成员 methodspropertiesprotocols 对应的 method_array_tproperty_array_tprotocol_array_t 类型都是继承自 list_array_tt<Element, List>,该类型可以保存三种类型的值:

  1. 空值;
  2. 指向单个列表的指针;
  3. 指向列表的指针数组。

通过第 3 种类型也就是二维数组类型,可以实现数据的扩展。例如,method_array_t 是一个数组,其中保存的元素是 method_list_t,而 method_list_t 也是一个数组,其中保存的元素是 method_t

class_ro_t

相对的,class_ro_t 保存的就是在编译期确定的数据。

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
};

结构体中的成员 baseMethodListbasePropertiesbaseProtocolsivar_list_t 对应的 method_list_tproperty_list_tprotocol_list_tivar_list_t 类型都是继承自 entsize_list_tt,一个泛型的数组结构,没有扩展功能。

类的初始化

类在运行时第一次初始化时会调用 realizeClass... 系列方法

ro = (const class_ro_t *)cls->data();
if (ro->flags & RO_FUTURE) {
    // This was a future class. rw data is already allocated.
    rw = cls->data();
    ro = cls->data()->ro;
    cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
} else {
    // Normal class. Allocate writeable class data.
    rw = (class_rw_t *)calloc(sizeof(class_rw_t), 1);
    rw->ro = ro;
    rw->flags = RW_REALIZED|RW_REALIZING;
    cls->setData(rw);
}

在该方法的实现中,可以知道在编译期间类的结构中的 class_data_bits_t *data 指向的是一个 class_ro_t *。在运行时的时候调用该初始化方法时,首先为 class_rw_t * 申请内存空间,然后将 class_ro_t * 赋值给 rw->ro,接着设置 class_rw_t * 的标志位标识状态,最后将创建好的 class_rw_t * 赋值给类结构。

分类

Category 提供了在运行时动态的向已经存在的类中添加方法、协议和属性的功能

typedef struct category_t *Category;
struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;
};

加载分类

static void
attachCategories(Class cls, const locstamped_category_t *cats_list, uint32_t cats_count,
                 int flags)
{
    constexpr uint32_t ATTACH_BUFSIZ = 64;
    method_list_t   *mlists[ATTACH_BUFSIZ];

    uint32_t mcount = 0;
    bool fromBundle = NO;
    bool isMeta = (flags & ATTACH_METACLASS);
    auto rw = cls->data();

    for (uint32_t i = 0; i < cats_count; i++) {
        auto& entry = cats_list[i];

        method_list_t *mlist = entry.cat->methodsForMeta(isMeta);
        if (mlist) {
            if (mcount == ATTACH_BUFSIZ) {
                prepareMethodLists(cls, mlists, mcount, NO, fromBundle);
                rw->methods.attachLists(mlists, mcount);
                mcount = 0;
            }
            mlists[ATTACH_BUFSIZ - ++mcount] = mlist;
            fromBundle |= entry.hi->isBundle();
        }
    }

    if (mcount > 0) {
        prepareMethodLists(cls, mlists + ATTACH_BUFSIZ - mcount, mcount, NO, fromBundle);
        rw->methods.attachLists(mlists + ATTACH_BUFSIZ - mcount, mcount);
        if (flags & ATTACH_EXISTING) flushCaches(cls);
    }
}

原来的方法中包含了对分类中方法、代理和属性的处理,但原理相同,为了减少篇幅,只保留对方法的处理:

  • 声明一个大小为 64,元素类型为 method_list_t * 的二维数组类型的临时变量 mlists
  • 遍历分类数组,获取分类中的方法列表 mlist,从后向前的添加到 mlists
  • 如果 mlists 数组在遍历过程中存满,则合并到 rw->methods 中,否则等待遍历完合并

合并方法

void attachLists(List* const * addedLists, uint32_t addedCount) {
        if (addedCount == 0) return;

        if (hasArray()) {
            // many lists -> many lists
            uint32_t oldCount = array()->count;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
            array()->count = newCount;
            memmove(array()->lists + addedCount, array()->lists, 
                    oldCount * sizeof(array()->lists[0]));
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0]));
        }
        else if (!list  &&  addedCount == 1) {
            // 0 lists -> 1 list
            list = addedLists[0];
        } 
        else {
            // 1 list -> many lists
            List* oldList = list;
            uint32_t oldCount = oldList ? 1 : 0;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)malloc(array_t::byteSize(newCount)));
            array()->count = newCount;
            if (oldList) array()->lists[addedCount] = oldList;
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0]));
        }
    }

在合并时,大致有两种情况。一种是当前数组中为空,那就直接指向新添加的数组;另一种是当前数组中已经有数据:

  1. 先通过 realloc() 方法为原数组扩充空间
  2. 再将原数组的元素利用 memmove() 方法移动到新申请空间的后面
  3. 最后使用 memcpy() 方法把新数组复制到新空间的前面

方法覆盖

通过上面两段代码,可以发现两点:

  1. 分类中如果重写了方法,并不会覆盖原有方法
  2. 之所以在使用时出现“覆盖”原方法的现象,是因为在方法列表中分类中的方法被添加到了原方法的前面
  3. 如果某个类的多个分类都重写了同一个方法,那么,最后执行的是最后被遍历到的分类(也就是最后被添加到项目中的分类)中的方法