在分析 retain
和 realese
之前我们先了解一下 nonPointerIsa
,nonPointerIsa
代表非指针,代表 isa
的结构,在相关位置处理上与 TaggedPointer
具有相似性,都涉及到位运算等,但是它们是完全不同的东西,TaggedPointer
是对相关对象类型的处理。
nonPointerIsa
的详细介绍大家可以看 iOS 对象探究三 这篇文章,下面是 x86 64位
系统下 isa
位域信息的介绍。
// nonpointer 表示是否对 isa 指针开启指针优化 0:纯isa 指针,1:不止是类对象地址,isa 中包含了类信息, 对象的引用计数等
// has_assoc 关联对象标志位,0:没有,1:存在
// has_cxx_dtor 该对象是否有 C++或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象。
// shiftcls 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位用来存类指针。
// magic:用于调试器判断当前对象是真的对象还是没有初始化的空间。
// weakly_referenced 表示对象是否被指向或者曾经指向一个 ARC 的弱变量,没有弱引用的对象可以更快释放。
// deallocating:标志对象是否正在释放内存
// unused 是否使用散列表
// has_sidetable_rc:当对象引用计数大于 10 时,则需要借用该变量存储进位
// extra_rc: 当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。
retain
retain
流程总结:
- 判断是否是
isTaggedPointer
类型- 判断是否是
nonpointer
2.1 不是的话就直接操作散列表,对引用计数加一
2.2 判断是否正在释放,在的话不往下处理
2.3 newisa.bits 左移 45 位加一
2.4 判断是否超出范围,超出的话对数组除 2,extra_rc 存一半的值,散列表存一半。这个地方这样做是为了效率问题考虑,如果都存到散列表的话减减的时候需要操作散列表,需要开表查表,比较消耗性能。
realese
realese
流程总结:
- 判断是否是
isTaggedPointer
类型- 判断是否是
nonpointer
2.1 不是的话就直接操作散列表,对引用计数减一
2.2 判断是否正在释放,在的话不往下处理
2.3 是nonpointer
的话就对extra_rc
的数值进行减减
2.4 判断减减是否超出范围,超出的话判断是否有散列表,有的话就取出散列表中值的一半赋值给extra_rc
,并对散列表的值进行更新。- 当
extra_rc
与散列表中的值都为 0,或者没有散列表的时候就对对象发送dealloc
消息,进行析构。
网友评论