moj*_*uba 8 assembly objective-c inline-assembly libobjc
下面的代码段取自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]");
Run Code Online (Sandbox Code Playgroud)
更新:
以下是对bypass_msgSend_release()的调用:
movl -4(%ebp), %eax
movl %eax, (%esp)
calll "-[NSObject release]"
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
因此,如果它是标记指针,则不执行任何操作。公平地说,这意味着它实际上与堆上的任何内容都不相关,并且没有保留计数。
否则在过去他们只会retain向对象发送消息。现在,retain如果已注意到该对象包含自定义内容retain(毫无疑问不是旧运行时会记录的内容,因此会进行版本检查),他们会向该对象发送消息,否则他们将使用旁路方法。
绕过似乎直接调用 的已知地址[NSObject retain]。
那么我的猜测是?这是速度优化。如果您知道没有自定义保留,并且实际上直接跳转到,IMP那么您可以节省动态调度的成本。鉴于编译器现在会在 ARC 下自动抛出 C 调用(特别是不是 Objective-C 调用),这意味着您永远不会进入更昂贵的东西。