1、对象调用retain函数会增加引用计数
// Replaced by ObjectAlloc
- (id)retain {
return ((id)self)->rootRetain();
}
2、rootRetain函数
ALWAYS_INLINE id
objc_object::rootRetain()
{
return rootRetain(false, false);
}
ALWAYS_INLINE id
objc_object::rootRetain(bool tryRetain, bool handleOverflow)
{
if (isTaggedPointer()) return (id)this;
bool sideTableLocked = false;
//标记是否把引用计数存到SideTable引用计数表中,默认false,因为对象的引用引用计数首先保存到isa的extra_rc中,如果extra_rc存满了,再保存到SideTable引用计数表中
bool transcribeToSideTable = false;
isa_t oldisa;
isa_t newisa;
do {
transcribeToSideTable = false;
oldisa = LoadExclusive(&isa.bits);//获取isa的值
newisa = oldisa;
if (slowpath(!newisa.nonpointer)) {//如果是tagpointer类型的对象走这里,因为tagpointer类型的对象没有isa指针
ClearExclusive(&isa.bits);
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
if (slowpath(tryRetain && newisa.deallocating)) {
ClearExclusive(&isa.bits);
if (!tryRetain && sideTableLocked) sidetable_unlock();
return nil;
}
uintptr_t carry;
//先在isa的extra_rc上加1保存引用计数,如果extra_rc存满了,通过carry标记,判断是否在SideTable引用计数表保存
newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry); // extra_rc++
if (slowpath(carry)) {
// newisa.extra_rc++ overflowed
//如果extra_rc存满了,就存到SideTable引用计数表
if (!handleOverflow) {
ClearExclusive(&isa.bits);
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;//标记为存到SideTable引用计数表中
newisa.extra_rc = RC_HALF;//标记为已经满了
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.
sidetable_addExtraRC_nolock(RC_HALF);
}
if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
return (id)this;
}
3、addc这个方法把isa中保存的引用计数进行加1
static ALWAYS_INLINE uintptr_t
addc(uintptr_t lhs, uintptr_t rhs, uintptr_t carryin, uintptr_t *carryout)
{
return __builtin_addcl(lhs, rhs, carryin, carryout);
}
4、sidetable_retain函数把引用计数表上的加1
//把对象的引用计数加1
id
objc_object::sidetable_retain()
{
#if SUPPORT_NONPOINTER_ISA
assert(!isa.nonpointer);
#endif
//根据对象的地址获取所对应的SideTable引用计数表
SideTable& table = SideTables()[this];
table.lock();
//再根据对象的地址经过哈希运算之后获取对象的的引用计数大小
size_t& refcntStorage = table.refcnts[this];
if (! (refcntStorage & SIDE_TABLE_RC_PINNED)) {
refcntStorage += SIDE_TABLE_RC_ONE;//在这里进行加1
}
table.unlock();
return (id)this;
}