iOS - Tagged Pointer

1. 基本结构

objectivec 复制代码
// Tagged Pointer 的内存布局
union TaggedPointer {
    uintptr_t bits;  // 完整的指针值
    struct {
        uintptr_t data     : 60;  // 数据部分
        uintptr_t tag      : 4;   // 类型标记
    };
    
    // 扩展类型
    struct {
        uintptr_t extData  : 52;  // 扩展数据
        uintptr_t extTag   : 8;   // 扩展标记
        uintptr_t isExt    : 4;   // 是否是扩展类型
    };
};

2. 类型判断

objectivec 复制代码
// 判断是否是 Tagged Pointer
static inline bool 
isTaggedPointer(const void *ptr) {
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

// 获取类型标记
static inline uintptr_t 
getTaggedPointerTag(const void *ptr) {
    return ((uintptr_t)ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_MASK;
}

3. 支持的数据类型

3.1 基本类型

objectivec 复制代码
// NSNumber 的 Tagged Pointer 实现
+ (NSNumber *)numberWithInt:(int)value {
    // 如果值在 Tagged Pointer 范围内
    if (value >= MIN_TAGGED_INT && value <= MAX_TAGGED_INT) {
        uintptr_t tagged = ((uintptr_t)value << 4) | NSNumberTag;
        return (__bridge id)(void *)tagged;
    }
    // 否则创建普通对象
    return [[NSNumber alloc] initWithInt:value];
}

3.2 字符串类型

objectivec 复制代码
// NSString 的 Tagged Pointer 实现
+ (NSString *)stringWithSmallString:(const char *)str {
    size_t length = strlen(str);
    if (length <= 7) {  // 可以用 Tagged Pointer 存储
        uintptr_t tagged = 0;
        for (size_t i = 0; i < length; i++) {
            tagged |= ((uintptr_t)str[i] << (i * 8));
        }
        tagged |= (NSStringTag << 60);  // 添加标记
        return (__bridge id)(void *)tagged;
    }
    return [[NSString alloc] initWithUTF8String:str];
}

4. 内存管理

4.1 引用计数

objectivec 复制代码
// Tagged Pointer 不需要引用计数
id objc_retain(id obj) {
    if (isTaggedPointer(obj)) return obj;
    return obj->retain();
}

void objc_release(id obj) {
    if (isTaggedPointer(obj)) return;
    return obj->release();
}

4.2 内存优化

objectivec 复制代码
// 直接存储数据,无需额外内存分配
+ (instancetype)optimizedNumberWithInt:(int)value {
    if (canBeTaggedPointer(value)) {
        return makeTaggedPointer(value);
    }
    return [self newNumberWithInt:value];
}

5. 消息发送

objectivec 复制代码
id objc_msgSend_tagged(id self, SEL _cmd, ...) {
    // 1. 获取类型标记
    uintptr_t tag = getTaggedPointerTag(self);
    
    // 2. 获取对应的类
    Class cls = objc_getTaggedPointerClass(tag);
    
    // 3. 查找方法
    IMP imp = lookUpImpOrForward(cls, _cmd);
    
    // 4. 调用方法
    return imp(self, _cmd, ...);
}

6. 性能优化

6.1 空间优化

objectivec 复制代码
// 普通对象
struct NSNumber {
    Class isa;
    int value;      // 至少需要 16 字节
};

// Tagged Pointer
// 直接使用指针存储值,只需要 8 字节
uintptr_t taggedNumber = (value << 4) | tag;

6.2 时间优化

objectivec 复制代码
// 普通对象访问
int getValue(NSNumber *num) {
    // 1. 解引用 isa
    // 2. 解引用获取值
    return num->_value;
}

// Tagged Pointer 访问
int getTaggedValue(NSNumber *num) {
    // 直接从指针中提取值
    return (uintptr_t)num >> 4;
}

7. 限制和注意事项

7.1 大小限制

objectivec 复制代码
// 数据大小限制
#define TAGGED_POINTER_MASK  0xF000000000000000
#define TAGGED_POINTER_DATA  0x0FFFFFFFFFFFFFFF

bool canBeTagged(size_t size) {
    // 60位数据位的限制
    return size <= (sizeof(uintptr_t) * 8 - 4);
}

7.2 类型限制

objectivec 复制代码
// Tagged Pointer 支持的类型定义
static Class taggedPointerClasses[] = {
    [OBJC_TAG_NSAtom]            = NSAtom,              // 0
    [OBJC_TAG_NSString]          = NSString,            // 1
    [OBJC_TAG_NSNumber]          = NSNumber,            // 2
    [OBJC_TAG_NSIndexPath]       = NSIndexPath,         // 3
    [OBJC_TAG_NSManagedObjectID] = NSManagedObjectID,   // 4
    [OBJC_TAG_NSDate]            = NSDate,               // 5
    [OBJC_TAG_NSDateTS]          = NSDateTS,             // 6
    [OBJC_TAG_NSDecimalNumber]   = NSDecimalNumber       // 7
};

8. 实际应用

8.1 字符串优化

objectivec 复制代码
NSString *str1 = @"abc";     // 可能使用 Tagged Pointer
NSString *str2 = @"这是一个很长的字符串";  // 普通对象

Tagged Pointer 的优势:

  1. 减少内存分配
  2. 提高访问速度
  3. 减少引用计数操作
  4. 优化内存使用

这种优化对于小对象的处理特别有效,是一个重要的性能优化手段。

相关推荐
HarderCoder10 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
叽哥20 小时前
Flutter Riverpod上手指南
android·flutter·ios
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
权咚3 天前
阿权的开发经验小集
git·ios·xcode
用户093 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间3 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918413 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张3 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h3 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa