8

下面的代码片段取自 Apple 的 ObjC 运行时 (libobjc) 源代码。我想知道这到底是什么意思。(不是很谷歌,抱歉)

// 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]"
4

1 回答 1

4

retain这是文件后面的 from 的实际实现:

__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 调用),这意味着您永远不会进入更昂贵的东西。

于 2014-05-07T21:11:41.780 回答