IT评测·应用市场-qidao123.com技术社区

标题: iOS - 引用计数(ARC) [打印本页]

作者: 万有斥力    时间: 2025-1-7 05:11
标题: iOS - 引用计数(ARC)
1. 根本数据布局

  1. // 对象结构
  2. struct objc_object {
  3.     isa_t isa;  // isa 指针,包含引用计数信息
  4. };
  5. // isa 的位域结构
  6. union isa_t {
  7.     uintptr_t bits;
  8.     struct {
  9.         uintptr_t nonpointer        : 1;  // 是否启用优化的 isa 指针
  10.         uintptr_t has_assoc         : 1;  // 是否有关联对象
  11.         uintptr_t has_cxx_dtor      : 1;  // 是否有 C++ 析构函数
  12.         uintptr_t shiftcls          : 33; // 类的指针
  13.         uintptr_t magic             : 6;  // 用于调试
  14.         uintptr_t weakly_referenced : 1;  // 是否有弱引用
  15.         uintptr_t deallocating      : 1;  // 是否正在释放
  16.         uintptr_t has_sidetable_rc  : 1;  // 引用计数是否在 SideTable 中
  17.         uintptr_t extra_rc          : 19; // 额外的引用计数值
  18.     };
  19. }
复制代码
2. 引用计数存储位置

2.1 isa 优化

  1. inline bool
  2. objc_object::hasNonpointerIsa() {
  3.     return isa.nonpointer;  // 判断是否使用优化的 isa
  4. }
  5. // 引用计数存储在 isa 的情况
  6. if (isa.nonpointer) {
  7.     // 引用计数存储在 isa.extra_rc 中
  8.     // 最多可存储 2^19 - 1 个引用
  9. }
复制代码
2.2 SideTable 存储

  1. struct SideTable {
  2.     spinlock_t slock;
  3.     RefcountMap refcnts;  // 引用计数哈希表
  4.     weak_table_t weak_table;  // 弱引用表
  5. };
  6. // 当 isa 中的引用计数溢出时
  7. if (isa.has_sidetable_rc) {
  8.     // 引用计数存储在 SideTable 的 refcnts 中
  9. }
复制代码
3. 引用计数操纵

3.1 retain 操纵

  1. id objc_retain(id obj) {
  2.     if (!obj) return obj;
  3.     if (obj->isTaggedPointer()) return obj;
  4.     return obj->retain();
  5. }
  6. inline id
  7. objc_object::retain() {
  8.     if (isTaggedPointer()) return this;
  9.    
  10.     if (fastpath(!ISA()->hasCustomRR())) {
  11.         if (fastpath(isa.hasNonpointerIsa())) {
  12.             addExtraRC_nolock();
  13.         } else {
  14.             sidetable_retain();
  15.         }
  16.     }
  17.     return this;
  18. }
复制代码
3.2 release 操纵

  1. void objc_release(id obj) {
  2.     if (!obj) return;
  3.     if (obj->isTaggedPointer()) return;
  4.     obj->release();
  5. }
  6. inline bool
  7. objc_object::release() {
  8.     if (isTaggedPointer()) return false;
  9.    
  10.     if (fastpath(!ISA()->hasCustomRR())) {
  11.         if (fastpath(isa.hasNonpointerIsa())) {
  12.             return sidetable_release(true);
  13.         }
  14.         return sidetable_release(false);
  15.     }
  16.     return false;
  17. }
复制代码
4. 引用计数溢出处理

  1. void objc_object::sidetable_addExtraRC_nolock(size_t delta_rc) {
  2.     // 当 isa.extra_rc 即将溢出时
  3.     if (isa.extra_rc + delta_rc > RC_MASK) {
  4.         // 将引用计数迁移到 SideTable
  5.         isa.has_sidetable_rc = true;
  6.         auto &table = SideTables()[this];
  7.         size_t& refcnt = table.refcnts[this];
  8.         refcnt += delta_rc;
  9.     } else {
  10.         // 继续使用 isa 存储
  11.         isa.extra_rc += delta_rc;
  12.     }
  13. }
复制代码
5. 弱引用处理

5.1 弱引用表布局

  1. struct weak_table_t {
  2.     weak_entry_t *weak_entries;  // 弱引用数组
  3.     size_t    num_entries;       // 条目数
  4.     uintptr_t mask;             // 容量掩码
  5.     uintptr_t max_hash_displacement;  // 最大哈希偏移
  6. };
复制代码
5.2 弱引用操纵

  1. id objc_loadWeakRetained(id *location) {
  2.     id obj = *location;
  3.     if (!obj) return nil;
  4.     if (obj->isTaggedPointer()) return obj;
  5.     return obj->rootRetain();
  6. }
  7. void objc_storeWeak(id *location, id obj) {
  8.     _objc_weak_store(location, obj);
  9. }
复制代码
6. 自动释放池相干

  1. void *objc_autoreleasePoolPush(void) {
  2.     return AutoreleasePoolPage::push();
  3. }
  4. void objc_autoreleasePoolPop(void *ctxt) {
  5.     AutoreleasePoolPage::pop(ctxt);
  6. }
  7. id objc_autorelease(id obj) {
  8.     if (!obj) return obj;
  9.     if (obj->isTaggedPointer()) return obj;
  10.     return obj->autorelease();
  11. }
复制代码
7. 优化机制

7.1 Tagged Pointer

  1. bool isTaggedPointer() {
  2.     return ((uintptr_t)this & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
  3. }
  4. // Tagged Pointer 对象不参与引用计数
  5. if (obj->isTaggedPointer()) {
  6.     return obj;  // 直接返回,不进行引用计数操作
  7. }
复制代码
7.2 散列表优化

  1. // SideTable 的哈希表实现
  2. struct RefcountMap : public objc::DenseMap<DisguisedPtr<objc_object>,size_t,true> {
  3.     // 使用 DenseMap 提高查找效率
  4. };
复制代码
8. 内存管理计谋

8.1 dealloc 流程

  1. inline void
  2. objc_object::rootDealloc() {
  3.     if (isTaggedPointer()) return;
  4.    
  5.     if (fastpath(isa.hasNonpointerIsa())) {
  6.         // 快速释放路径
  7.         if (fastpath(!isa.weakly_referenced && !isa.has_assoc)) {
  8.             free(this);
  9.             return;
  10.         }
  11.     }
  12.     object_dispose((id)this);
  13. }
复制代码
8.2 引用计数检查

  1. bool objc_object::rootTryRetain() {
  2.     if (isTaggedPointer()) return true;
  3.    
  4.     if (fastpath(!ISA()->hasCustomRR())) {
  5.         if (fastpath(isa.hasNonpointerIsa())) {
  6.             // 尝试增加引用计数
  7.             return sidetable_tryRetain();
  8.         }
  9.     }
  10.     return false;
  11. }
复制代码
这个引用计数体系的设计考虑了:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4