iOS - 引用计数(ARC)

1. 基本数据结构

objectivec 复制代码
// 对象结构
struct objc_object {
    isa_t isa;  // isa 指针,包含引用计数信息
};

// isa 的位域结构
union isa_t {
    uintptr_t bits;
    struct {
        uintptr_t nonpointer        : 1;  // 是否启用优化的 isa 指针
        uintptr_t has_assoc         : 1;  // 是否有关联对象
        uintptr_t has_cxx_dtor      : 1;  // 是否有 C++ 析构函数
        uintptr_t shiftcls          : 33; // 类的指针
        uintptr_t magic             : 6;  // 用于调试
        uintptr_t weakly_referenced : 1;  // 是否有弱引用
        uintptr_t deallocating      : 1;  // 是否正在释放
        uintptr_t has_sidetable_rc  : 1;  // 引用计数是否在 SideTable 中
        uintptr_t extra_rc          : 19; // 额外的引用计数值
    };
}

2. 引用计数存储位置

2.1 isa 优化

objectivec 复制代码
inline bool 
objc_object::hasNonpointerIsa() {
    return isa.nonpointer;  // 判断是否使用优化的 isa
}

// 引用计数存储在 isa 的情况
if (isa.nonpointer) {
    // 引用计数存储在 isa.extra_rc 中
    // 最多可存储 2^19 - 1 个引用
}

2.2 SideTable 存储

objectivec 复制代码
struct SideTable {
    spinlock_t slock;
    RefcountMap refcnts;  // 引用计数哈希表
    weak_table_t weak_table;  // 弱引用表
};

// 当 isa 中的引用计数溢出时
if (isa.has_sidetable_rc) {
    // 引用计数存储在 SideTable 的 refcnts 中
}

3. 引用计数操作

3.1 retain 操作

objectivec 复制代码
id objc_retain(id obj) {
    if (!obj) return obj;
    if (obj->isTaggedPointer()) return obj;
    return obj->retain();
}

inline id 
objc_object::retain() {
    if (isTaggedPointer()) return this;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            addExtraRC_nolock();
        } else {
            sidetable_retain();
        }
    }
    return this;
}

3.2 release 操作

objectivec 复制代码
void objc_release(id obj) {
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    obj->release();
}

inline bool 
objc_object::release() {
    if (isTaggedPointer()) return false;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            return sidetable_release(true);
        }
        return sidetable_release(false);
    }
    return false;
}

4. 引用计数溢出处理

objectivec 复制代码
void objc_object::sidetable_addExtraRC_nolock(size_t delta_rc) {
    // 当 isa.extra_rc 即将溢出时
    if (isa.extra_rc + delta_rc > RC_MASK) {
        // 将引用计数迁移到 SideTable
        isa.has_sidetable_rc = true;
        auto &table = SideTables()[this];
        size_t& refcnt = table.refcnts[this];
        refcnt += delta_rc;
    } else {
        // 继续使用 isa 存储
        isa.extra_rc += delta_rc;
    }
}

5. 弱引用处理

5.1 弱引用表结构

objectivec 复制代码
struct weak_table_t {
    weak_entry_t *weak_entries;  // 弱引用数组
    size_t    num_entries;       // 条目数
    uintptr_t mask;             // 容量掩码
    uintptr_t max_hash_displacement;  // 最大哈希偏移
};

5.2 弱引用操作

objectivec 复制代码
id objc_loadWeakRetained(id *location) {
    id obj = *location;
    if (!obj) return nil;
    if (obj->isTaggedPointer()) return obj;
    return obj->rootRetain();
}

void objc_storeWeak(id *location, id obj) {
    _objc_weak_store(location, obj);
}

6. 自动释放池相关

objectivec 复制代码
void *objc_autoreleasePoolPush(void) {
    return AutoreleasePoolPage::push();
}

void objc_autoreleasePoolPop(void *ctxt) {
    AutoreleasePoolPage::pop(ctxt);
}

id objc_autorelease(id obj) {
    if (!obj) return obj;
    if (obj->isTaggedPointer()) return obj;
    return obj->autorelease();
}

7. 优化机制

7.1 Tagged Pointer

objectivec 复制代码
bool isTaggedPointer() {
    return ((uintptr_t)this & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

// Tagged Pointer 对象不参与引用计数
if (obj->isTaggedPointer()) {
    return obj;  // 直接返回,不进行引用计数操作
}

7.2 散列表优化

objectivec 复制代码
// SideTable 的哈希表实现
struct RefcountMap : public objc::DenseMap<DisguisedPtr<objc_object>,size_t,true> {
    // 使用 DenseMap 提高查找效率
};

8. 内存管理策略

8.1 dealloc 流程

objectivec 复制代码
inline void 
objc_object::rootDealloc() {
    if (isTaggedPointer()) return;
    
    if (fastpath(isa.hasNonpointerIsa())) {
        // 快速释放路径
        if (fastpath(!isa.weakly_referenced && !isa.has_assoc)) {
            free(this);
            return;
        }
    }
    object_dispose((id)this);
}

8.2 引用计数检查

objectivec 复制代码
bool objc_object::rootTryRetain() {
    if (isTaggedPointer()) return true;
    
    if (fastpath(!ISA()->hasCustomRR())) {
        if (fastpath(isa.hasNonpointerIsa())) {
            // 尝试增加引用计数
            return sidetable_tryRetain();
        }
    }
    return false;
}

这个引用计数系统的设计考虑了:

  1. 性能优化(isa 优化、Tagged Pointer)
  2. 内存效率(分散存储策略)
  3. 线程安全(自旋锁、原子操作)
  4. 扩展性(支持自定义引用计数)
相关推荐
大熊猫侯佩21 小时前
桃花岛 Xcode 构建秘籍:Swift 中的 “Feature Flags” 心法
app·xcode·swift
悄然林静1 天前
Mac终端执行`brew doctor`报`openssl@1.1`警告
mac·xcode·apple
用户091 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan1 天前
iOS26适配指南之UIColor
ios·swift
权咚2 天前
阿权的开发经验小集
git·ios·xcode
用户092 天前
TipKit与CloudKit同步完全指南
ios·swift
小溪彼岸2 天前
macOS自带截图命令ScreenCapture
macos
法的空间2 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918412 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
TESmart碲视2 天前
Mac 真正多显示器支持:TESmart USB-C KVM(搭载 DisplayLink 技术)如何实现
macos·计算机外设·电脑