之前的博客留了一个64位CPU中isa指针的坑,今天来填个坑。
isa 的本质
回顾OC对象的本质,每个OC对象都含有一个isa指针,arm64
之前,isa仅仅是一个指针,保存着对象或类对象内存地址,在 arm64
架构之后,apple对isa进行了优化,变成了一个共用体 union
结构,同时使用位域来存储更多的信息。OC对象的isa指针斌不是直接指向类对象或者是元类对象的,而是需要 &ISA_MASK
通过位运算才能取到相应的地址,但是为什么要这样做。
objc_object
1 | struct objc_object { |
isa_t
isa
指针其实是一个 isa_t
类型的共用体,我们看下 isa_t
内部查看其结构。
1 | union isa_t { |
上述源码中 isa_t
是 union
类型,union
表示共用体。可以看到共用体中有一个结构体,结构体内部分别定义了一些变量,变量后面的值代表的是该变量占用多少个字节,也就是位域。
位域
位域声明 位域名 : 位域长度
- 如果一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
- 位域的长度不能大于数据类型本身的长度,比如int类型就不能超过32位二进位。
- 位域可以无位域名,这时它只用来作填充或调整位置,无名的位域是不能使用的。
ISA_BITFIELD
1 |
|
上面的代码描述了再64位下 arm64
架构和 x86_64
架构中的 isa
的占用空间布局。
isa中存储的信息及作用
- nonpointer:0代表一个普通指针,储存着Class、Meta-Class对象的内存地址。1代表优化后的使用位域储存更多的信息的结构体。
- has_assoc:表示是否有设置过关联的对象,如果没有,释放时候会更快。
- has_cxx_dtor:表示是否有声明C++析构函数,如果没有释放会更快。
- shiftcls:这里存储着Class、Meta-Class对象的内存地址信息。
- magic:用于在调试时分辨对象是否未完成初始化。
- weakly_referenced:表示是否有被弱引用指向过。
- deallocating:表示对象是否正在释放。
- has_sidetable_rc:引用计数器是否过大无法存储在isa中,如果为1,那么引用计数会存储在一个叫SideTable的属性中。
- extra_rc:里面存储的值是引用计数器减1。