Objective c 为什么这个内联程序集在libobjc中调用release、retain和autorelease?
下面的代码片段取自苹果公司的ObjC运行时(libobjc)源代码。我不知道这到底是什么意思。(抱歉,谷歌搜索能力不强) 更新: 下面是调用bypass_msgSend_release()生成的结果:Objective c 为什么这个内联程序集在libobjc中调用release、retain和autorelease?,objective-c,assembly,inline-assembly,libobjc,Objective C,Assembly,Inline Assembly,Libobjc,下面的代码片段取自苹果公司的ObjC运行时(libobjc)源代码。我不知道这到底是什么意思。(抱歉,谷歌搜索能力不强) 更新: 下面是调用bypass_msgSend_release()生成的结果: movl -4(%ebp), %eax movl %eax, (%esp) calll "-[NSObject release]" 以下是文件后面部分的retain的实际实现: __attribute__((aligned(16))) id objc_retain(id obj)
movl -4(%ebp), %eax
movl %eax, (%esp)
calll "-[NSObject release]"
以下是文件后面部分的
retain
的实际实现:
__attribute__((aligned(16)))
id
objc_retain(id obj)
{
if (!obj || OBJC_IS_TAGGED_PTR(obj)) {
goto out_slow;
}
#if __OBJC2__
if (((class_t *)obj->isa)->hasCustomRR()) {
return [obj retain];
}
return bypass_msgSend_retain(obj);
#else
return [obj retain];
#endif
out_slow:
// clang really wants to reorder the "mov %rdi, %rax" early
// force better code gen with a data barrier
asm volatile("");
return obj;
}
因此,如果它是一个标记指针,则什么也不做。公平地说,这意味着它实际上与堆上的任何内容都没有关系,也没有保留计数
否则在过去,他们只会向对象发送消息retain
。现在,如果注意到对象包含自定义的retain
(毫无疑问,这不是旧运行时将记录的内容,因此需要进行版本检查),则它们会向对象发送消息retain
,否则它们会使用旁路方法
旁路似乎直接调用[NSObject retain]
的已知地址
那我猜呢?这是一种速度优化。如果您可以确定没有自定义保留,并且实际上直接跳到
IMP
,那么您就节省了动态调度的成本。考虑到编译器现在在ARC下自动抛出C调用(尤其不是Objective-C调用),这意味着您永远不会去做更昂贵的事情。这些似乎是对retain、release和autorelease的显式调用,以避免编译器反对相同的调用。至于他们为什么出现,我一点线索都没有。这是哪个文件?我想这是为了绕过ARC,这会禁止呼叫。但我猜在这一点上。非常有趣的发现。请随意再次编辑它;我不是想改变你的问题,只是说得更清楚些。请注意,在标题中不需要标记,代码本身也在问题中,因此可以在搜索中找到。我建议对标题进行严格的散文式描述。@mojuba-字符串只是方法的实际链接器可见名称。它用引号括起来,因为它包含非标准字符。这很有意义,并解释了绕过\u msgSend\u
。跳过去,该死D
__attribute__((aligned(16)))
id
objc_retain(id obj)
{
if (!obj || OBJC_IS_TAGGED_PTR(obj)) {
goto out_slow;
}
#if __OBJC2__
if (((class_t *)obj->isa)->hasCustomRR()) {
return [obj retain];
}
return bypass_msgSend_retain(obj);
#else
return [obj retain];
#endif
out_slow:
// clang really wants to reorder the "mov %rdi, %rax" early
// force better code gen with a data barrier
asm volatile("");
return obj;
}