在isa中存储东西

Cod*_*aFi 9 objective-c objective-c-runtime

64位运行时消除了直接访问对象的isa字段的能力,这是CLANG工程师一直警告我们的事情.它们被一组相当具有创造性(且神奇)的ABI规则所取代,这些规则关于新命名的isa标题的哪些部分包含有关该对象的信息,甚至包含其他状态(在NSNumber/NSString的情况下).似乎存在一个漏洞,因为你可以选择退出新的"魔法"isa并使用你自己的一个(原始的isa),代价是通过某些运行时代码路径走慢路.

我的问题是双重的,然后:

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

isa标题中究竟是什么标记为让运行时将它与正常的isa区分开来?

Gab*_*lla 9

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

根据格雷格帕克的这篇文章

如果覆盖+allocWithZone:,则可以将对象的isa字段初始化为"raw"isa指针.如果你这样做,那个isa字段中不会存储额外的数据,你可能会遇到像retain/ 这样的代码慢速路径release.要启用这些优化,请将isa字段设置为零(如果尚未设置),然后调用object_setClass().

所以是的,您可以选择退出并手动设置原始isa指针.要通知运行时这个,你必须得到0的第一个LSB​​.isa(见下文)

此外,还有一个可以设置,命名的环境变量OBJC_DISABLE_NONPOINTER_ISA,这是非常不言自明的.


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

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

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

总是根据格雷格帕克的文章,这里是新的布局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)    
Run Code Online (Sandbox Code Playgroud)

isa标题中究竟是什么标记为让运行时将它与正常的isa区分开来?

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


为了将它包装起来,虽然看起来可以选择退出并开始搞乱64位架构上可用的额外位,但我个人不鼓励它.新的isa布局经过精心设计,以优化运行时性能,并且远远不能保证随着时间的推移保持不变.

Apple也可能决定在未来放弃与原始isa表示的复古兼容性,防止选择退出.任何假定isa为指针的代码都会破坏.


Cat*_*Man 1

您不能安全地执行此操作,因为如果(实际上)可用地址空间扩展到超过 33 位,则布局可能需要再次更改。但目前,isa 的底部位控制是否将其视为具有额外信息。