美文网首页Runtime
RetainCount - NONPOINTER_ISA

RetainCount - NONPOINTER_ISA

作者: ienos | 来源:发表于2021-08-12 21:26 被阅读0次

在 Objective-C 中,我们都知道对象的释放通过引用计数来控制。通过 Retain 和 Release 来进行引用计数 +1 和 -1。

那引用计数是存储在什么位置,又是在什么时候调用了 delloc 方法?

我们都知道 Objective-C 中的每个对象都是 objc_object 结构体,其中第一个成员变量就是 isa

isa 其实本质上是 union isa_t,下面为 arm64 下的 isa_t

union isa_t 
{
  Class cls;
  uintptr_t bits;
  struct {
    uintptr_t indexed      : 1;
    uintptr_t has_assoc     : 1;
    uintptr_t has_cxx_dtor   : 1;
    uintptr_t shiftcls     : 33; 
    uintptr_t magic       : 6;
    uintptr_t weakly_referenced : 1;
    uintptr_t deallocating   : 1;
    uintptr_t has_sidetable_rc : 1;
    uintptr_t extra_rc     : 19;
  };

补充: union 在 C++ 中是联合,在联合中的所有成员共享同一个内存,其中 Class 和 bits 和 struct 共享同一块内存也就是 64 bit;在 isa_t 的 struct,其形式称 位域;为什么会有位域这种形式,因为当如果一个结构不需要 8bit 空间大小,只需要 1bit 空间,那么就可以用位域来节约内存空间。在 struct 的 indexed 成员占 1 bit,shiftcls 占 33 bit,依次类推;从 indexed 到 extra_rc 从低到高依次排列

isa_t struct

补充: 字段说明

  • extra_rc: 64 位下优先保存引用计数的位置
  • has_sidetable_rc: 是否有试用 SideTable 保存引用计数
  • Indexed: isa 指针是否为 NONPOINTER_ISA

>> 在非 64 位操作系统中,是没有 struct 这个成员的;因为在 64 位系统中为了节约内存,所以引入了 NONPOINTER_ISA,这种 isa 除了指针的功能外还能存储数据。
NONPOINTER_ISA 其中的 extra_rc 就被用来存储引用计数;当 extra_rc 已经存满时, 就会被存在 SideTable 中,has_sidetable_rc 则标记是否存储在 SideTable 中。

64 位系统下的引用计数大致存储原理如下:

  • 每次对象调用 Retain 时,extra_rc++,当 extra_rc 正溢出时,抽调 extra_rc 最大值的一半也就是 RC_HALF 到 SideTable 中,此时 has_sidetable_rc 为 true
  • 每次对象调用 Release 时,extra_rc--,当 extra_rc 负溢出时,extra_rc 从 SideTable 中借最大值为 RC_HALF 的引用计数;如果 SideTable 中也没有那么 extra_rc 为 0,并调用 dealloc 方法

相关文章

网友评论

    本文标题:RetainCount - NONPOINTER_ISA

    本文链接:https://www.haomeiwen.com/subject/brthbltx.html