下面的代码段取自Apple的ObjC运行时(libobjc)源代码。我想知道这究竟意味着什么。 (不是google-able,抱歉)
// HACK -- the use of these functions must be after the @implementation
id bypass_msgSend_retain(NSObject *obj) asm("-[NSObject retain]");
void bypass_msgSend_release(NSObject *obj) asm("-[NSObject release]");
id bypass_msgSend_autorelease(NSObject *obj) asm("-[NSObject autorelease]");
更新
以下是对bypass_msgSend_release()的调用:
movl -4(%ebp), %eax
movl %eax, (%esp)
calll "-[NSObject release]"
答案 0 :(得分:4)
以下是文件中稍后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调用),这意味着你永远不会进入更昂贵的东西。