alloc原理(isa注解)

1,026 阅读2分钟

今天我们来继续分析白云大小姐的第三条“注入灵魂”。不过为了方便理解我们换一个例子。

至于啥例子,请看下图:

是不是突然就感兴趣了!!?

1 你都懂得那个过程 --- void initInstanceIsa(Class cls, bool hasCxxDtor)

上篇文章我们其实都在讲obj是咋来的,但是这个obj是莫得灵魂的。而注入灵魂原的源码就是:

obj->initInstanceIsa(cls, hasCxxDtor);

这里面cls就是obj要初始化成的Class,hasCxxDtor也是cls里面的参数后面会讲。这个函数本身也是调用了另一个函数:

 initIsa(cls, true, hasCxxDtor);
void initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{ 
    ........
        isa_t newisa(0);
        newisa.bits = ISA_MAGIC_VALUE;
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.shiftcls = (uintptr_t)cls >> 3;
        isa = newisa;
    ........
}

功能其实特别简单,初始化一个newisa,然后把参数赋值到这个newisa里,最后把这个newisa赋值给obj本身的isa

2 对象中的DNA --- isa

isa有两个版本,我们现在说的是新版(nonpointer)

就像人类的DNA是由46个染色体构成,isa也是由64个bit位组成。 下面给出的是arm64的isa组成

      uintptr_t nonpointer        : 1;                                       \
      uintptr_t has_assoc         : 1;                                       \
      uintptr_t has_cxx_dtor      : 1;                                       \
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
      uintptr_t magic             : 6;                                       \
      uintptr_t weakly_referenced : 1;                                       \
      uintptr_t deallocating      : 1;                                       \
      uintptr_t has_sidetable_rc  : 1;                                       \
      uintptr_t extra_rc          : 19

第1位 - nonpointer: 表示是否对 isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地址,isa 中包含了类信息、对象的引用计数等

第2位 - has_assoc: 关联对象标志位,0没有,1存在

第3位 - has_cxx_dtor: 该对象是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑, 如果没有,则可以更快的释放对象

cxx表示C++; dtor是destructor的缩写表示,表示析构器;ctor是constructor的缩写,表示构造器

第4-36位 - shiftcls: 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位用来存储类指针。

第37-42位 - magic: 用于调试器判断当前对象是真的对象还是没有初始化的空间

第43位 - weakly_referenced:对象是否被指向或者曾经指向一个 ARC 的弱变量, 没有弱引用的对象可以更快释放。

第44位 - deallocating:标志对象是否正在释放内存

第45位 - has_sidetable_rc:当对象引用技术大于 10 时,则需要借用该变量存储进位

第46-64位 - extra_rc:当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。