数据结构当不确定一个对象的类型的时候,通常使用 id 类型进行表示- (id)copy;id 代表一个对象,它是指向一个实例对象的指针typedef struct objc_object *id;实际
数据结构
当不确定一个对象的类型的时候,通常使用 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
实际上配置了结构体中成员 nonpointer
和 magic
的值。
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 bits ,64 位的数据中不单单只保存类对象的指针 |
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 objectClass 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 ISAClass rawISA();inline Classobjc_object::rawISA(){ ASSERT(!isTaggedPointer() && !isa.nonpointer); // 直接获取类对象指针 return (Class)isa.bits;}
getIsa
获取 tagged pointer 类型对象所属的类
// getIsa() allows this to be a tagged pointer objectClass 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_tobjc_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 voidobjc_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 的操作分为了三种情况:
- 没数据或者是 nonpointer 类型的原 isa,变为 nonpointer 类型的新 isa,操作就是用原 isa 的数据初始化新 isa,然后新 isa 保存新的类指针
- nonpointer 类型的原 isa 变为原始指针类型的新 isa,这种情况下,除了将新 isa 直接指向新的类指针外,还需要把原来保存在原 isa 中的引用计数复制到 SideTables 表中保存
- 原始指针类型的原 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 boolobjc_object::isClass(){ // 如果当前对象是 taggedPointer 类型,那就不是 if (isTaggedPointer()) return false; // 根据当前对象所属的类是否是元类进行判断 return ISA()->isMetaClass();}
hasAssociatedObjects
当前对象是否有关联对象
bool hasAssociatedObjects();inline boolobjc_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 voidobjc_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 boolobjc_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 voidobjc_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 boolobjc_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 overrideinline 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 voidobjc_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 voidobjc_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_tobjc_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 的逻辑,从中可以看到其策略为:
- 如果当前对象的 isa 不是 nonpointer 类型
- 直接将引用计数保存到 SideTables 表中
- 如果当前对象的 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 的逻辑看起来很长,但其实就三步:
- 先在 retry 中做 -1 操作
- 如果当前对象的 isa 不是 nonpointer 类型,直接去 SideTables 表中 -1
- 如果当前对象的 isa 是 nonpointer 类,就去 isa 的 extra_rc 标志位 -1
- 如果在 retry 中出现了下溢,就去 underflow 中把 SideTables 表中存储的引用计数拿出来存到 isa 的 extra_rc 标志位中,再跳回 retry 中做 -1 操作
- 如果发现 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_tobjc_object::rootRelease_underflow(bool performDealloc){ // 将处理下溢参数设置为 true return rootRelease(performDealloc, true);}
clearDeallocating_slow
清除 SideTables 表中保存当前对象弱引用和引用计数对应的数据
void clearDeallocating_slow();NEVER_INLINE voidobjc_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();idobjc_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_tobjc_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();boolobjc_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_tobjc_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();boolobjc_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;}
. 
- 0