首先 arm64位架构后的 isa指针 是个(union)共用体 储存了更多的信息
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
struct {
// 0,代表普通的指针,存储着Class、Meta-Class对象的内存地址 1,代表优化过,使用位域存储更多的信息
uintptr_t nonpointer : 1;
//是否有设置过关联对象,如果没有,释放时会更快
uintptr_t has_assoc : 1;
// 是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
uintptr_t has_cxx_dtor : 1;
// 存储着Class、Meta-Class对象的内存地址信息
uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/
// 用于在调试时分辨对象是否未完成初始化
uintptr_t magic : 6;
// 是否有被弱引用指向过,如果没有,释放时会更快
uintptr_t weakly_referenced : 1;
// 对象是否正在释放
uintptr_t deallocating : 1;
// 引用计数器是否过大无法存储在isa中 如果为1,那么引用计数会存储在一个叫SideTable的类的属性中
uintptr_t has_sidetable_rc : 1;
// 里面存储的值是引用计数器减1
uintptr_t extra_rc : 19;
};
};
arm64后 isa 需要进行一次位运算才能算出真实地址 &ISA_MASK
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_MASK 0x0000000ffffffff8ULL (中间的33位)
如果含有C++析构函数 或者是关联属性 被weak修饰的属性 释放的时候都需要判断
/***********************************************************************
* objc_destructInstance
* Destroys an instance without freeing memory.
* Calls C++ destructors.
* Calls ARC ivar cleanup.
* Removes associative references.
* Returns `obj`. Does nothing if `obj` is nil.
**********************************************************************/
void *objc_destructInstance(id obj)
{
if (obj) {
// Read all of the flags at once for performance.
bool cxx = obj->hasCxxDtor();
bool assoc = obj->hasAssociatedObjects();
// This order is important.
// 判断是否含有C++析构函数
if (cxx) object_cxxDestruct(obj);
// 判断是否是关联属性
if (assoc) _object_remove_assocations(obj);
obj->clearDeallocating();
}
return obj;
}