搞不懂现在为毛还问这种面试题,难怪还能开启mrc手动管理内存不成么
看看源码就好了下载OBJC源码,搜索retainCount
- (NSUInteger)retainCount {
return _objc_rootRetainCount(self);
}
然后到
uintptr_t
_objc_rootRetainCount(id obj)
{
ASSERT(obj);
return obj->rootRetainCount();
}
然后找到真正的实现地方
inline uintptr_t
objc_object::rootRetainCount()
{
if (isTaggedPointer()) return (uintptr_t)this;
sidetable_lock();
isa_t bits = LoadExclusive(&isa.bits);
ClearExclusive(&isa.bits);
if (bits.nonpointer) {
uintptr_t rc = 1 + bits.extra_rc;
if (bits.has_sidetable_rc) {
rc += sidetable_getExtraRC_nolock();
}
sidetable_unlock();
return rc;
}
sidetable_unlock();
return sidetable_retainCount();
}
这就是源码了解析下,
1.首先如果是taggedPointer就直接返回,因为taggedPointer的内容就是直接存储在指针里面
2.上锁,防止多个线程访问同一个对象
3.获取isa的位域信息
4.如果isa的nonpointer第一个值是1就返回rc这个,rc也是isa位域里面的值,也就是说如果nonpointer = 1,那么引用计数是存储在isa指针位域的extra_rc里面,而位域只有0,1那么最终返回的结果最大为2
5.如果isa位域的nonpointer是0就直接返回另一个函数sidetable_retainCount()的值
uintptr_t
objc_object::sidetable_retainCount()
{
SideTable& table = SideTables()[this];
size_t refcnt_result = 1;
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;
}
table.unlock();
return refcnt_result;
}
6.这个函数也搜索到了,主要是操作SideTable结构体里面的refcnts而通过位移取值,这个属性无疑是个散列表
struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;
SideTable() {
memset(&weak_table, 0, sizeof(weak_table));
}
~SideTable() {
_objc_fatal("Do not delete SideTable.");
}
void lock() { slock.lock(); }
void unlock() { slock.unlock(); }
void forceReset() { slock.forceReset(); }
// Address-ordered lock discipline for a pair of side tables.
template<HaveOld, HaveNew>
static void lockTwo(SideTable *lock1, SideTable *lock2);
template<HaveOld, HaveNew>
static void unlockTwo(SideTable *lock1, SideTable *lock2);
};
然后可以得出结论,isa是共用体情况下,是存储在位域里面,最大值是2,如果isa是一个正常的指针,引用计数存储在sideTable里面
附isa指针内部结构
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
};
共用体结构为
# 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