小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
之前我们探索了isa的源码以及isa位图,今天我们来继续探索isa
ISA_MASK
ISA_MASK:宏定义,不同的CPU架构下的值不一样。nonpointer类型isa,需要isa和ISA_MASK进行&运算,才能得到类对象地址
isa & ISA_MASK
在x86_64架构下,ISA_MASK定义为:
define ISA_MASK 0x00007ffffffffff8ULL
- ULL:表示unsigned long long 常量 打开main.m文件,写入以下代码:
int main(int argc, const char * argv[]) {
@autoreleasepool {
LGPerson *per= [LGPerson alloc];
}
return 0;
}
获取isa
x/4g per
-------------------------
0x10077b200: 0x011d80010000832d 0x0000000000000000
0x10077b210: 0x0000000000000000 0x0000000000000000
- isa:0x011d80010000832d 通过和ISA_MASK进行&运算,得到类对象地址
p/x 0x011d800100008335 & 0x00007ffffffffff8ULL
-------------------------
0x0000000100008330
和per.class打印结构一致
p/x per.class
-------------------------
0x0000000100008330 LGPerson
为什么会这样呢?这就要从ISA_MASK的本质说起
p/t 0x00007ffffffffff8ULL
-------------------------
0b0000000000000000011111111111111111111111111111111111111111111000
- 在x86_64结构下,ISA_MASK的高17位和低3位为0,中间44位为1.也就是说,只显示isa中的shiftcls部分,即:存储类指针的值 ISA_MASK也称之为类的面具,和ISA_MASK进行多次&,得到的结果相同
p/x 0x0000000100008330 & 0x00007ffffffffff8ULL
-------------------------
0x0000000100008330
- 其原理好比是戴面具,无论戴多少层,所漏出的位置都是一致的 同样,在x86_64架构中,通过isa位图可以知道shiftcls存储在3~47位,即是我们不知道ISA_MASK的存在,直接通过isa的位运算,同样可以得到类对象的地址
获取isa
x/4g per
-------------------------
0x10077b200: 0x011d80010000832d 0x0000000000000000
0x10077b210: 0x0000000000000000 0x0000000000000000
- isa:0x011d80010000832d 向右平移3位
p/x 0x011d800100008335 >> 3
-------------------------
0x0023b00020001066
向左平移20位
p/x 0x0023b00020001066 << 20
-------------------------
0x0002000106600000
向右平移17位,得到类对象地址
p/x 0x0002000106600000 >> 17
-------------------------
0x0000000100008330
和per.class打印结果一致
p/x per.class
-------------------------
0x0000000100008330 LGPerson
总结
isa关联类信息
- 使用
联合体 + 位域的方式存储,优化内存空间 - 类型分为
nonpointer和非nonpointer - 非
nonpointer只存储指针地址,nonpointer还存储类的其他信息ISA_MASK - 在
x86_64架构下,ISA_MASK的高17位和低3位为0,中间44位为1。目的,显示isa中的shiftcls nonpointer类型isa,使用isa & ISA_MASK,得到类对象地址isa的位运算- 向右平移
3位 - 向左平移
20位 - 向右平移
17位 - 得到类对象地址