runtime - isa 位域
01 — 源码解读
以前学习半路出家,只知道runtime是运行时,具体怎么用?底层原理是什么样子?为什么这样写?等都一无所知,当前趁着深挖底层,学习底层的机会,加深一下对runtime底层的理解,以便应对复杂多变的互联网环境。
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; \
uintptr_t has_assoc : 1; \
uintptr_t has_cxx_dtor : 1; \
uintptr_t shiftcls : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
uintptr_t magic : 6; \
uintptr_t weakly_referenced : 1; \
uintptr_t deallocating : 1; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 19
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
# define ISA_BITFIELD \
uintptr_t nonpointer : 1; \
uintptr_t has_assoc : 1; \
uintptr_t has_cxx_dtor : 1; \
uintptr_t shiftcls : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
uintptr_t magic : 6; \
uintptr_t weakly_referenced : 1; \
uintptr_t deallocating : 1; \
uintptr_t has_sidetable_rc : 1; \
uintptr_t extra_rc : 8
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
# else
# error unknown architecture for packed isa
# endif
苹果官方分别针对真机与模拟器做了不同的架构支持,arm64是跑在真机上的,x86_64则是运行在模拟器上的。由于我们开发出来的软件,基本应用于手机,故我们这里主要讨论arm64架构下的isa。
图来自:小马哥
02 — 关联对象样例分析
包含关联对象代码片段:
先看下上图箭头所指之处,占用一位,含义是是否设置过关联对象。举个例子验证下:
取出上图中的isa地址:0x000001a102991533
借助编程器我们可以看到:从0(64位第一位)开始,从右向左第二位既是
has_assoc,我们可以看到数值是1
注释掉关联对象代码片段后:
接下来我们把添加关联对象的代码片段注释,再看一下打印结果:
取出上图中的isa地址:0x000001a100341529
此时我们再看,从右向左第二位的值已经变成0了,表明此时已经没有关联对象。
03 — 弱引用指向过样例分析
这个例子主要是举证:weakly_referenced
给对象添加弱引用:
取出弱引用后的isa指针地址:0x000005a1043bd541
借助编程器可以看到:
此时我们根据图:
对照上图编程器中箭头所指既是此 weakly_referenced 所对应的位置,我们可以看到是 1
把对象弱引用代码片段注释一下:
取出其中isa指向的新的地址:0x000001a100161529
借助编程器我们可以看到如图:
此时我们再看,weakly_referenced 所对应的位置 已经变成 0 了,表明此时已经没有对象已经没有被弱引用了。
关于上面这两个存储位:
has_assoc:
是否有设置过关联对象,如果没有,释放时会更快
weakly_referenced:
是否有被弱引用指向过,如果没有,释放时会更快
那么如何去证明:
如果没有设置过关联对象的话,释放会变快呢?
如果对象没有被弱引用指向过,释放也会变快呢?
关于这些,在runtime的底层源码中也有说明:
/***********************************************************************
* 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.
//是否包含cpp析构函数
bool cxx = obj->hasCxxDtor();
//是否包含关联对象
bool assoc = obj->hasAssociatedObjects();
// This order is important.
//如果包含析构函数则进行进行销毁
if (cxx) object_cxxDestruct(obj);
//如果包含关联对象则先移除
if (assoc) _object_remove_assocations(obj);
obj->clearDeallocating();
}
return obj;
}
欢迎路过的知友进行交流,面试题及相关视频资料可私信聊。谢谢!
上一篇: 举例简单介绍PostgreSQL中的数组