今天我们来继续分析白云大小姐的第三条“注入灵魂”。不过为了方便理解我们换一个例子。
至于啥例子,请看下图:
是不是突然就感兴趣了!!?
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。