数据结构
当不确定一个对象的类型的时候,通常使用 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 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 的操作分为了三种情况:
- 没数据或者是 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 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 的逻辑,从中可以看到其策略为:
- 如果当前对象的 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_t objc_object::rootRelease_underflow(bool performDealloc) {
// 将处理下溢参数设置为 true
return rootRelease(performDealloc, true);
}
clearDeallocating_slow
清除 SideTables 表中保存当前对象弱引用和引用计数对应的数据
void clearDeallocating_slow();
NEVER_INLINE void
objc_object::clearDeallocating_slow()
{
ASSERT(isa.nonpointer && (isa.weakly_referenced || isa.has_sidetable_rc));
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表加锁
table.lock();
// 如果当前对象有被弱引用
if (isa.weakly_referenced) {
// 调用 weak_clear_no_lock 函数将保存在 SideTable 表中,所有弱引用当前对象的指针置 nil,并将当前对象从表中移除
weak_clear_no_lock(&table.weak_table, (id)this);
}
// 如果当前对象引用计数上溢
if (isa.has_sidetable_rc) {
// 清除当前对象保存在 SideTable 表中的引用计数
table.refcnts.erase(this);
}
// 为 SideTable 表解锁
table.unlock();
}
sidetable_lock
为 SideTable 表加锁
void sidetable_lock();
void
objc_object::sidetable_lock()
{
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表加锁
table.lock();
}
sidetable_unlock
为 SideTable 表解锁
void sidetable_unlock();
void
objc_object::sidetable_unlock()
{
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表解锁
table.unlock();
}
sidetable_moveExtraRC_nolock
将引用计数和弱引用数据保存到 SideTable 表中,该函数用于将 isa 从 nonpointer 类型转为原指针类型时使用
void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);
void
objc_object::sidetable_moveExtraRC_nolock(size_t extra_rc,
bool isDeallocating,
bool weaklyReferenced)
{
ASSERT(!isa.nonpointer); // should already be changed to raw pointer
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 获取当前对象的引用计数表
size_t& refcntStorage = table.refcnts[this];
size_t oldRefcnt = refcntStorage;
// not deallocating - that was in the isa
ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
// 创建临时变量标识是否上溢
uintptr_t carry;
// 将传入的引用计数的数量条件到表中保存
size_t refcnt = addc(oldRefcnt, extra_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
// 如果发生了上溢,设置标识为已满
if (carry) refcnt = SIDE_TABLE_RC_PINNED;
// 如果正在销毁对象,设置标识为正在销毁
if (isDeallocating) refcnt |= SIDE_TABLE_DEALLOCATING;
// 如果被弱引用了,设置标识为被弱引用
if (weaklyReferenced) refcnt |= SIDE_TABLE_WEAKLY_REFERENCED;
// 更新数据
refcntStorage = refcnt;
}
sidetable_addExtraRC_nolock
将一部分引用计数从 isa 的 extra_rc 标志位移动到 SideTable 表中
bool sidetable_addExtraRC_nolock(size_t delta_rc);
bool objc_object::sidetable_addExtraRC_nolock(size_t delta_rc) {
ASSERT(isa.nonpointer);
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 获取当前对象的引用计数表
size_t& refcntStorage = table.refcnts[this];
size_t oldRefcnt = refcntStorage;
// isa-side bits should not be set here
ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
// 如果当前表中已满就直接返回,不作处理
if (oldRefcnt & SIDE_TABLE_RC_PINNED) return true;
// 创建临时变量标识是否上溢
uintptr_t carry;
// 将传入的引用计数的数量条件到表中保存
size_t newRefcnt =
addc(oldRefcnt, delta_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
if (carry) {
// 如果发生了上溢,直接设置为最大值,并标识已满
refcntStorage =
SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
return true;
}
else {
// 否则,更新数据
refcntStorage = newRefcnt;
return false;
}
}
sidetable_subExtraRC_nolock
将一部分引用计数从 SideTable 表中移动到 isa 的 extra_rc 标志位
size_t sidetable_subExtraRC_nolock(size_t delta_rc);
size_t
objc_object::sidetable_subExtraRC_nolock(size_t delta_rc)
{
ASSERT(isa.nonpointer);
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果引用计数表为空,直接返回 0
if (it == table.refcnts.end() || it->second == 0) {
// Side table retain count is zero. Can't borrow.
return 0;
}
size_t oldRefcnt = it->second;
// isa-side bits should not be set here
ASSERT((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
ASSERT((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
// 从表中移除传入的引用计数的数量
size_t newRefcnt = oldRefcnt - (delta_rc << SIDE_TABLE_RC_SHIFT);
ASSERT(oldRefcnt > newRefcnt); // shouldn't underflow
// 更新数据
it->second = newRefcnt;
// 返回实际从表中获取的数量
return delta_rc;
}
sidetable_getExtraRC_nolock
获取 SideTable 表中保存的引用计数数量
size_t sidetable_getExtraRC_nolock();
size_t objc_object::sidetable_getExtraRC_nolock() {
ASSERT(isa.nonpointer);
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
RefcountMap::iterator it = table.refcnts.find(this);
// 如果引用计数表为空,直接返回 0
if (it == table.refcnts.end()) return 0;
// 否则返回表中保存的引用计数数量
else return it->second >> SIDE_TABLE_RC_SHIFT;
}
sidetable_isDeallocating
获取 SideTable 表中保存的当前对象是否正在销毁的状态
bool sidetable_isDeallocating();
bool
objc_object::sidetable_isDeallocating()
{
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// NO SPINLOCK HERE
// _objc_rootIsDeallocating() is called exclusively by _objc_storeWeak(),
// which already acquired the lock on our behalf.
// fixme can't do this efficiently with os_lock_handoff_s
// if (table.slock == 0) {
// _objc_fatal("Do not call -_isDeallocating.");
// }
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果表不为空,并且 SIDE_TABLE_DEALLOCATING 标志位有数据,就返回 true,否则返回 false
return (it != table.refcnts.end()) && (it->second & SIDE_TABLE_DEALLOCATING);
}
sidetable_clearDeallocating
清除 isa 是原始指针类型对象的 SideTable 表
void sidetable_clearDeallocating();
void
objc_object::sidetable_clearDeallocating()
{
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果表不为空
if (it != table.refcnts.end()) {
// 如果被弱指针引用过,就将所有弱引用当前对象的指针置 nil,并将当前对象从表中移除
if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
weak_clear_no_lock(&table.weak_table, (id)this);
}
// 清除引用计数数据
table.refcnts.erase(it);
}
// 为 SideTable 表解锁
table.unlock();
}
sidetable_isWeaklyReferenced
获取 SideTable 表中保存的当前对象是否被弱指针引用过
bool sidetable_isWeaklyReferenced();
bool objc_object::sidetable_isWeaklyReferenced() {
bool result = false;
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果表不为空
if (it != table.refcnts.end()) {
// 获取表中 SIDE_TABLE_WEAKLY_REFERENCED 标志位的数据
result = it->second & SIDE_TABLE_WEAKLY_REFERENCED;
}
// 为 SideTable 表解锁
table.unlock();
// 返回结果
return result;
}
sidetable_setWeaklyReferenced_nolock
将当前对象的弱引用状态保存到 SideTable 表中
void sidetable_setWeaklyReferenced_nolock();
void objc_object::sidetable_setWeaklyReferenced_nolock() {
#if SUPPORT_NONPOINTER_ISA
ASSERT(!isa.nonpointer);
#endif
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 设置表中 SIDE_TABLE_WEAKLY_REFERENCED 标志位的数据
table.refcnts[this] |= SIDE_TABLE_WEAKLY_REFERENCED;
}
sidetable_retain
将 SideTable 表中的引用计数 +1,用于 isa 为原始指针的情况
id sidetable_retain();
id
objc_object::sidetable_retain()
{
#if SUPPORT_NONPOINTER_ISA
ASSERT(!isa.nonpointer);
#endif
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的引用计数表
size_t& refcntStorage = table.refcnts[this];
// 如果引用计数表没有满
if (! (refcntStorage & SIDE_TABLE_RC_PINNED)) {
// 为引用计数 +1
refcntStorage += SIDE_TABLE_RC_ONE;
}
// 为 SideTable 表解锁
table.unlock();
return (id)this;
}
sidetable_retain_slow
未找到实现
id sidetable_retain_slow(SideTable& table);
sidetable_release
将 SideTable 表中的引用计数 -1,用于 isa 为原始指针的情况
uintptr_t sidetable_release(bool performDealloc = true);
uintptr_t
objc_object::sidetable_release(bool performDealloc)
{
#if SUPPORT_NONPOINTER_ISA
ASSERT(!isa.nonpointer);
#endif
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 创建临时变量标识是否执行销毁方法
bool do_dealloc = false;
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的销毁状态
auto it = table.refcnts.try_emplace(this, SIDE_TABLE_DEALLOCATING);
auto &refcnt = it.first->second;
if (it.second) {
// 如果无数据,不做处理
do_dealloc = true;
} else if (refcnt < SIDE_TABLE_DEALLOCATING) {
// SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
// 如果当前对象正在销毁,不做处理
do_dealloc = true;
refcnt |= SIDE_TABLE_DEALLOCATING;
} else if (! (refcnt & SIDE_TABLE_RC_PINNED)) {
// 如果表没满,执行 -1 操作
refcnt -= SIDE_TABLE_RC_ONE;
}
// 为 SideTable 表解锁
table.unlock();
// 如果需要销毁,并且传参标识要执行销毁方法
if (do_dealloc && performDealloc) {
// 通过发消息的方式调用 dealloc 方法
((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));
}
// 返回是否要执行销毁方法
return do_dealloc;
}
sidetable_release_slow
未找到实现
uintptr_t sidetable_release_slow(SideTable& table, bool performDealloc = true);
sidetable_tryRetain
尝试将 SideTable 表中的引用计数 +1,用于 isa 为原始指针的情况
bool sidetable_tryRetain();
bool objc_object::sidetable_tryRetain() {
#if SUPPORT_NONPOINTER_ISA
ASSERT(!isa.nonpointer);
#endif
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// NO SPINLOCK HERE
// _objc_rootTryRetain() is called exclusively by _objc_loadWeak(),
// which already acquired the lock on our behalf.
// fixme can't do this efficiently with os_lock_handoff_s
// if (table.slock == 0) {
// _objc_fatal("Do not call -_tryRetain.");
// }
// 创建临时变量标识是否 +1 成功
bool result = true;
auto it = table.refcnts.try_emplace(this, SIDE_TABLE_RC_ONE);
auto &refcnt = it.first->second;
if (it.second) {
// there was no entry
// 如果无数据,不做处理
} else if (refcnt & SIDE_TABLE_DEALLOCATING) {
// 如果正在销毁,不做处理
result = false;
} else if (! (refcnt & SIDE_TABLE_RC_PINNED)) {
// 如果表没满,执行 +1 操作
refcnt += SIDE_TABLE_RC_ONE;
}
// 返回执行结果
return result;
}
sidetable_retainCount
获取 SideTable 表中保存的引用计数的数量,用于 isa 为原始指针的情况
uintptr_t sidetable_retainCount();
uintptr_t
objc_object::sidetable_retainCount()
{
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 创建临时变量保存数量
size_t refcnt_result = 1;
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果表不为空
if (it != table.refcnts.end()) {
// this is valid for SIDE_TABLE_RC_PINNED too
// 获取表中保存的数量
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;
}
// 为 SideTable 表解锁
table.unlock();
// 返回结果
return refcnt_result;
}
sidetable_present
用于调试时,断言 SideTable 表中未保存该对象
bool sidetable_present();
bool
objc_object::sidetable_present()
{
// 创建变量标识表中未保存该对象
bool result = false;
// 获取当前对象的 SideTable 表
SideTable& table = SideTables()[this];
// 为 SideTable 表加锁
table.lock();
// 获取当前对象的引用计数表
RefcountMap::iterator it = table.refcnts.find(this);
// 如果当前对象没数据,返回 true
if (it != table.refcnts.end()) result = true;
// 如果弱引用表中没数据,返回 true
if (weak_is_registered_no_lock(&table.weak_table, (id)this)) result = true;
// 为 SideTable 表解锁
table.unlock();
// 返回结果
return result;
}
今天的文章Objective-C 之 Runtime 对象分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19370.html