如果可以选择退出并且 object_setClass() 将任意类放入对象中+allocWithZone:
根据格雷格帕克的这篇文章
如果您覆盖+allocWithZone:
,您可以将对象的 isa 字段初始化为“原始” isa 指针。如果这样做,则不会在该 isa 字段中存储任何额外的数据,并且您可能会遭受通过retain
/之类的代码的缓慢路径release
。要启用这些优化,请将 isa 字段设置为零(如果尚未设置),然后调用 object_setClass()。
所以是的,您可以选择退出并手动设置原始isa
指针。要通知运行时,您必须将第一个 LSBisa
设为 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
是指针的代码都会中断。