【问题标题】:Why is this inline assembly calling release, retain, and autorelease in libobjc?为什么这个内联汇编在 libobjc 中调用 release、retain 和 autorelease?
【发布时间】:2014-05-07 19:44:00
【问题描述】:

下面的 sn-p 取自 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]"

【问题讨论】:

  • 这些似乎是对保留、释放和自动释放的显式调用,以规避编译器反对相同的愿望。至于他们为什么会出现,我不知道。
  • 这是在哪个文件中?
  • 我认为这是绕过 ARC,这将禁止通话。但我猜在这一点上。非常有趣的发现。
  • 欢迎再次编辑;我不是要改变你的问题,只是让它更清楚。请注意,标题中不需要标签,并且代码本身就在问题中,因此可以在搜索中找到。我建议严格的散文描述最适合标题。
  • @mojuba - 字符串只是方法的实际链接器可见名称。它在引号中,因为它包含非标准字符。

标签: objective-c assembly inline-assembly libobjc


【解决方案1】:

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

【讨论】:

  • 这很有意义,并解释了bypass_msgSend_。跳到那里,该死的! :D
猜你喜欢
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 2018-07-22
相关资源
最近更新 更多