Skip to content

Latest commit

 

History

History
48 lines (32 loc) · 2.2 KB

9、引用计数的存储.md

File metadata and controls

48 lines (32 loc) · 2.2 KB

指针存放地址

Tagged Pointer

从64bit开始,iOS引入了Tagged Pointer技术,使用NSNumber、NSDate、NSString等小对象的存储。在没有使用Tagged Pointer之前, NSNumber等对象需要动态分配内存、维护引用计数等,NSNumber指针存储的是堆中NSNumber对象的地址值。使用Tagged Pointer之后,NSNumber指针里面存储的数据变成了:Tag + Data,也就是将数据直接存储在了指针中 当指针不够存储数据时,才会使用动态分配内存的方式来存储数据

isa

arm64之后,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存放跟多的信息。

struct objc_object{
uintptr_t nonpointer        : 1;nonpointer:0,代表普通的指针,存储着Class、Meta-Class对象的内存地址;1,代表优化过,使用位域存储更多的信息
uintptr_t has_assoc         : 1;has_assoc:是否有设置过关联对象,如果没有,释放时会更快
uintptr_t has_cxx_dtor      : 1;has_cxx_dtor:是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
uintptr_t shiftcls          : 33;  shiftcls:存储着Class、Meta-Class对象的内存地址信息
uintptr_t magic             : 6;magic:用于在调试时分辨对象是否未完成初始化
uintptr_t weakly_referenced : 1;weakly_referenced:是否有被弱引用指向过,如果没有,释放时会更快
uintptr_t deallocating      : 1;deallocating:对象是否正在释放
uintptr_t has_sidetable_rc  : 1;extra_rc:里面存储的值是引用计数器
uintptr_t extra_rc          : 19;has_sidetable_rc:引用计数器是否过大无法存储在isa中;如果为1,那么引用计数会存储在一个叫SideTable的类的属性中
#       define RC_ONE   (1ULL<<45)
#       define RC_HALF  (1ULL<<18)
};

其中extra_rc 里面存储的值是引用计数器; 我们可以看到has_sidetable_rc 引用计数器是否过大无法存储在isa中;如果为1,那么引用计数会存储在一个叫SideTable的类的属性中

SideTable

struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;

}

RefcountMap refcnts; 引用计数的 hash 表