【问题标题】:Storing things in isa在 isa 中存储东西
【发布时间】:2013-09-25 06:04:01
【问题描述】:

64 位运行时取消了直接访问对象的 isa 字段的能力,这是 CLANG 工程师一段时间以来一直在警告我们的。它们已被一组相当有创意(和magic)的不断变化的 ABI 规则所取代,这些规则关于新命名的 isa 标头的哪些部分包含有关对象的信息,甚至是其他状态(在 NSNumber/NSString 的情况下)。似乎有一个漏洞,您可以选择退出新的“魔术”ISA,并使用您自己的一个(raw isa),但代价是通过某些运行时代码路径走慢路。

我的问题是双重的,那么:

如果可以选择退出并将object_setClass() 任意类放入+allocWithZone: 中的对象中,是否也可以将任何东西放在类的额外空间中,或者运行时会尝试阅读它快速路径?

在 isa 标头中究竟标记了什么以让运行时将其与普通 isa 区分开来?

【问题讨论】:

    标签: objective-c objective-c-runtime


    【解决方案1】:

    如果可以选择退出并 object_setClass() 将任意类放入+allocWithZone: 中的对象中

    根据this article by Greg Parker

    如果您覆盖+allocWithZone:,您可以将对象的 isa 字段初始化为“原始” isa 指针。如果这样做,则不会在该 isa 字段中存储任何额外的数据,并且您可能会遇到像retain/release 这样的代码的缓慢路径。要启用这些优化,请将 isa 字段设置为零(如果尚未设置),然后调用 object_setClass()。

    是的,您可以选择退出并手动设置原始isa 指针。要将此通知运行时,您必须将isa 的第一个 LSB 设置为 0。(见下文)

    此外,您还可以设置一个名为 OBJC_DISABLE_NONPOINTER_ISA 的环境变量,这非常不言自明。


    是否也可以在类的额外空间中放置任何内容,或者运行时是否会尝试通过快速路径读取它?

    没有浪费额外的空间。运行时使用它来获取有关对象的有用的就地信息,例如当前状态和 - 最重要的是 - 它的保留计数(这是一个很大的改进,因为它曾经每次都从外部哈希表中获取)。

    所以不,您不能将额外空间用于您自己的目的,除非您选择退出(如上所述)。在这种情况下,运行时将通过长路径,忽略包含在额外位中的信息。

    总是按照 Greg Parker 的文章,这是isa 的新布局(注意这很可能会随着时间的推移而改变,所以不要相信它)

    (LSB)        
    1 bit    |  indexed           | 0 is raw isa, 1 is non-pointer isa.
    1 bit    |  has_assoc         | Object has or once had an associated reference. Object with no associated references can deallocate faster.
    1 bit    |  has_cxx_dtor      | Object has a C++ or ARC destructor. Objects with no destructor can deallocate faster.
    30 bits  |  shiftcls          | Class pointer's non-zero bits.
    9 bits   |  magic             | Equals 0xd2. Used by the debugger to distinguish real objects from uninitialized junk.
    1 bit    |  weakly_referenced | Object is or once was pointed to by an ARC weak variable. Objects not weakly referenced can deallocate faster.
    1 bit    |  deallocating      | Object is currently deallocating.
    1 bit    |  has_sidetable_rc  | Object's retain count is too large to store inline.
    19 bits  |  extra_rc          | Object's retain count above 1. (For example, if extra_rc is 5 then the object's real retain count is 6.)
    (MSB)    
    

    在 isa 标头中究竟标记了什么以让运行时将其与普通 isa 区分开来?

    如上所述,您可以通过查看第一个 LSB 来区分原始 isa 和新富 isa


    总结一下,虽然选择退出并开始处理 64 位架构上可用的额外位看起来是可行的,但我个人不鼓励这样做。新的isa 布局经过精心设计,可优化运行时性能,但远不能保证随着时间的推移保持不变。

    Apple 还可能在未来决定放弃与原始 isa 表示的追溯兼容性,以防止选择退出。任何假设 isa 为指针的代码都会中断。

    【讨论】:

    • 这是好东西,但考虑到我在我的问题中链接到你的两个来源,我觉得我没有学到任何新东西。不过,这是一个很好的答案。
    • 我完全错过了您文章中的第二个链接。无论如何,我的个人考虑在最后。我不会搞砸 isa,即使您可以选择退出新标准(但我无法想象为什么要这样做)。
    【解决方案2】:

    你不能安全地这样做,因为如果(当,真的)可用地址空间扩展到超过 33 位时,布局可能需要再次更改。但目前,isa 的底部位控制是否将其视为具有额外信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 2011-06-19
      • 2015-06-06
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      相关资源
      最近更新 更多