objc4源码基于779.1版本。文章纯属个人学习见解,谬误之处,望指正。
retain
方法调用栈
-
- (id)retain
- _objc_rootRetain(id obj)
- objc_object::rootRetain()
- objc_object::rootRetain(bool tryRetain, bool handleOverflow)
- objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)
- objc_object::rootRetain(bool tryRetain, bool handleOverflow)
- objc_object::rootRetain()
- _objc_rootRetain(id obj)
- (id)retain
源码详注
NSObject.mm
- line:2254
- (id)retain {
return _objc_rootRetain(self);
}
NSObject.mm
- line:1679
NEVER_INLINE id
_objc_rootRetain(id obj)
{
ASSERT(obj);
return obj->rootRetain();
}
3.objc-object.h
- line:477
ALWAYS_INLINE id
objc_object::rootRetain()
{
return rootRetain(false, false);
}
objc-object.h
- line: 489
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;
do {
transcribeToSideTable = false;
// 获取isa
oldisa = LoadExclusive(&isa.bits);
// 新指针指向
newisa = oldisa;
if (slowpath(!newisa.nonpointer)) { // 是否为普通指针,直接操作sidetable
ClearExclusive(&isa.bits);
// 是元类直接返回
if (rawISA()->isMetaClass()) return (id)this;
// 是否需要解锁
if (!tryRetain && sideTableLocked) sidetable_unlock();
if (tryRetain) return sidetable_tryRetain() ? (id)this : nil;
else return sidetable_retain();
}
// don't check newisa.fast_rr; we already called any RR overrides
// 当前对象的 isa 正在销毁
if (slowpath(tryRetain && newisa.deallocating)) {
ClearExclusive(&isa.bits);
if (!tryRetain && sideTableLocked) sidetable_unlock();
return nil;
}
uintptr_t carry;
// 引用计数+1
newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); // extra_rc++
if (slowpath(carry)) {
// newisa.extra_rc++ overflowed
// 引用计数 extra_rc 溢出
if (!handleOverflow) {
// 处理溢出
ClearExclusive(&isa.bits);
// 重新调用了当前方法rootRetain,handleOverflow = true
return rootRetain_overflow(tryRetain);
}
// Leave half of the retain counts inline and
// prepare to copy the other half to the side table.
if (!tryRetain && !sideTableLocked) sidetable_lock();
sideTableLocked = true;
transcribeToSideTable = true;
// 保留一半的计数,准备复制一半到side table
// 2^7 = 128
newisa.extra_rc = RC_HALF;
// 标记有side table存储
newisa.has_sidetable_rc = true;
}
} while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits))); // 原子交换函数
if (slowpath(transcribeToSideTable)) {
// Copy the other half of the retain counts to the side table.
// 将另一半存在 side table
sidetable_addExtraRC_nolock(RC_HALF);
}
if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
return (id)this;
}
NSObject.mm
- line:1329
bool
objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)
{
ASSERT(isa.nonpointer);
// 获取side table
SideTable& table = SideTables()[this];
// 获取引用计数的size
size_t& refcntStorage = table.refcnts[this];
// 赋值给oldRefcnt
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 设置成最大值
refcntStorage =
SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
return true;
}
else {
refcntStorage = newRefcnt;
return false;
}
}