对象
当不确定一个对象的类型的时候,通常使用 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;
}
类
在获取一个对象所属的类时,返回值的类型是 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
代表 readonly
。ro
中存储了当前类在编译期就已经确定的属性、方法以及遵循的协议。而 class_rw_t
提供了运行时对类拓展的能力,其中的 methods
、properties
、protocols
保存着通过 Category 在运行时添加的方法、属性及协议。
成员 methods
、properties
、protocols
对应的 method_array_t
、property_array_t
、protocol_array_t
类型都是继承自 list_array_tt<Element, List>
,该类型可以保存三种类型的值:
- 空值;
- 指向单个列表的指针;
- 指向列表的指针数组。
通过第 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;
};
结构体中的成员 baseMethodList
、baseProperties
、baseProtocols
和 ivar_list_t
对应的 method_list_t
、property_list_t
、protocol_list_t
和 ivar_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]));
}
}
在合并时,大致有两种情况。一种是当前数组中为空,那就直接指向新添加的数组;另一种是当前数组中已经有数据:
- 先通过
realloc()
方法为原数组扩充空间 - 再将原数组的元素利用
memmove()
方法移动到新申请空间的后面 - 最后使用
memcpy()
方法把新数组复制到新空间的前面
方法覆盖
通过上面两段代码,可以发现两点:
- 分类中如果重写了方法,并不会覆盖原有方法
- 之所以在使用时出现“覆盖”原方法的现象,是因为在方法列表中分类中的方法被添加到了原方法的前面
- 如果某个类的多个分类都重写了同一个方法,那么,最后执行的是最后被遍历到的分类(也就是最后被添加到项目中的分类)中的方法