本文使用的测试环境是arm64架构真机
为了探究Tagged Pointer本质,可以查看runtime源码,主要看文件objc-internal.h。
宏定义
可以看到以下宏定义,只有在64位系统才支持Tagged Pointer。
1  | 
64-bit的mac,tag存储在LSB(Least Significant Bit 最低位)。其它情况比如64位的真机和模拟器,tag存储在MSB(Most Significant Bit 最高位)。
1  | 
  | 
接下来是一个枚举定义,定义了默认的使用Tagged Pointer的类。例如NSString、NSNumber、NSIndexPath、NSDate(OBJC_TAG_NSAtom、OBJC_TAG_1、OBJC_TAG_NSManagedObjectID不知道是啥意思,还请知道的同学告诉我)。
1  | enum objc_tag_index_t : uint16_t  | 
方法定义
判断是不是Tagged Pointer
1  | static inline bool  | 
生成一个Tagged Pointer,最高的4位是tagged,剩下的是数据
1  | static inline void * _Nonnull  | 
从Tagged Pointer中取出值
1  | static inline uintptr_t  | 
NSNumber应用举例
可以使用下面代码来验证NSNumber如何使用Tagged Pointer
1  | NSNumber *charNumber = [NSNumber numberWithChar:'1'];  | 
不难发现规律,都是以b(1011)开头
- 最高位是1,说明这个指针是一个
Tagged Pointer - 第61-63位是11(十进制是3),也就是
OBJC_TAG_NSNumber(查上面的枚举) - 第1-4位是NSNumber的类型:比如,char是0、short是1、int是2、float是4
 - 剩下的56位就是真正的值了
 
NSString应用举例
1  | NSString *str1 = [NSString stringWithFormat:@"a"];  | 
与NSNumber类似
- 最高位是1,说明这个指针是一个
Tagged Pointer - 第61-63位是11(十进制是2),也就是
OBJC_TAG_NSString - 第1-4位是字符串长度
 - 剩下的56位就是真正的值了
 
更多细节推荐这篇文章采用Tagged Pointer的字符串
参考文章