0C底层-isa探索

2020-09-13  本文已影响0人  含笑州

前言

最近看了最新的objc781源码,发现ios对isa做了一些优化,采用了联合体位域,提高了一些性能。

探索

1.1结构体

结构体(struct)中所有变量是“共存”的——优点是“有容乃⼤”,

全⾯;缺点是struct内存空间的分配是粗放的,不管⽤不⽤,全分配。

1.2联合体

联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”; 

但优点是内存使⽤更为精细灵活,也节省了内存空间。

1.3初识isa

对象的本质是 结构体,这很好理解,因为OC 是 C 与 C++ 的超集。一个对象可以有多种不同数据类型的属性,那可以容纳不同数据类型的复杂结构,当然是结构体了。我们通过查看苹果的源码也可以佐证这一说法:

我们发现无论是实例化的对象还是还是类对象本质都是结构体,而且他们的内部都有一个isa,那么这个这个isa都是指向什么呢,如下图:

isa流程图

1.4isa优化

我们主要探索的是arm64中的关键代码如下:

isa_t 是一个联合体,这里所占空间为 8字节,共64位 ,内存布局从低位到高位情况如下图:

解释一下各存储内容的含义:

nonpointer(存储在第0字节) : 是否为优化isa标志。0代表是优化前的isa,一个纯指向类或元类的指针;1表示优化后的isa,不止是一个指针,isa中包含类信息、对象的引用计数等。现在基本上都是优化后的isa。

has_assoc (存储在第1个字节): 关联对象标志位。对象含有或者曾经含有关联引用,0表示没有,1表示有,没有关联引用的可以更快地释放内存(dealloc的底层代码有体现)。

has_cxx_dtor(存储在第2个字节): 析构函数标志位,如果有析构函数,则需进行析构逻辑,如果没有,则可以更快速地释放对象(dealloc的底层代码有体现)。

shiftcls :(存储在第3-35字节)存储类的指针,其实就是优化之前 isa 指向的内容。在arm64架构中有33位用来存储类指针。x86_64架构有44位。

magic(存储在第36-41字节):判断对象是否初始化完成, 是调试器判断当前对象是真的对象还是没有初始化的空间。

weakly_referenced(存储在第42字节):对象被指向或者曾经指向一个 ARC 的弱变量,没有弱引用的对象可以更快释放(dealloc的底层代码有体现)。

deallocating(存储在第43字节):标志对象是否正在释放内存。

has_sidetable_rc(存储在第44字节):判断该对象的引用计数是否过大,如果过大则需要其他散列表来进行存储。

extra_rc(存储在第45-63字节。):存放该对象的引用计数值减1后的结果。对象的引用计数超过 1,会存在这个里面,如果引用计数为 10,extra_rc 的值就为 9。

如上,优化之后的 isa,保留了优化之前类的指针(shiftcls),所以依然可以通过isa找到对应的类,在类中通过super_class找到父类,这对于 isa 的指向图的部分是一样子。同时还包含了更多其他的内容,这个设计和 taggedpointer 有些类似,把内存用到极致。

上一篇 下一篇

猜你喜欢

热点阅读