iOS之isa的底层探索二

669 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

之前我们探索了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的位运算,同样可以得到类对象的地址

image-3.png 获取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位
  • 得到类对象地址