我尝试在Objective-C可执行文件上使用OBJC_PRINT_VTABLE_IMAGES和OBJC_PRINT_VTABLE_SETUP环境变量,以了解Objective-C对象中的vtable机制。遗憾的是,尽管运行时确认变量已设置:
,但上述环境变量对控制台输出没有影响» OBJC_PRINT_OPTIONS=1 OBJC_PRINT_VTABLE_IMAGES=YES /Applications/TextEdit.app/Contents/MacOS/TextEdit
objc[41098]: OBJC_PRINT_OPTIONS is set
objc[41098]: OBJC_PRINT_VTABLE_IMAGES is set
我试图在系统(TextEdit)和我自己提供的可执行文件中使用这两个变量。没有效果。
Objective-C对象中的整个vtable机制是模糊的。在Apple页面上很难找到有关此机制的信息。其他来源有一些信息,但没有官方文档: http://www.sealiesoftware.com/blog/archive/2011/06/17/objc_explain_objc_msgSend_vtable.html http://cocoasamurai.blogspot.com/2010/01/understanding-objective-c-runtime.html
为什么这些变量不起作用?当前版本的Objective-C中的vtable是否已被弃用?
答案 0 :(得分:4)
在这种情况下,答案非常简单 - vtable dispatch不再在objective-c运行时进行优化,并且首先可能是一个坏主意。
基于vtable的调度是在Objective-c运行时加速频繁调用的第一次尝试之一,但请注意它早于当前方法缓存解决方案。在vtable解决方案中使用一组固定的选择器的问题不仅意味着运行时中每个类的内存增加,而且还意味着如果您使用的结构不是结果例如,在isEqualToString:
被频繁调用时,您现在在运行时中有一个完全浪费的 EVERY 类指针,它会覆盖其中一个选择器。糟糕。
另外,请注意,Vtable调度设计无法在32位架构上运行,这意味着一旦iOS SDK发布,32位再次成为objective-c的合理目标,那么优化根本无法工作
我可以找到的相关文档位于objc-abi.h
:
#if TARGET_OS_OSX && defined(__x86_64__) // objc_msgSend_fixup() is used for vtable-dispatchable call sites. OBJC_EXPORT void objc_msgSend_fixup(void) __OSX_DEPRECATED(10.5, 10.8, "fixup dispatch is no longer optimized") __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
如今,运行时中没有很多vtable dispatch的残留碎片。快速查看代码库会显示objc-runtime-new.mm
中的几个位置:
#if SUPPORT_FIXUP // Fix up old objc_msgSend_fixup call sites for (EACH_HEADER) { message_ref_t *refs = _getObjc2MessageRefs(hi, &count); if (count == 0) continue; if (PrintVtables) { _objc_inform("VTABLES: repairing %zu unsupported vtable dispatch " "call sites in %s", count, hi->fname()); } for (i = 0; i < count; i++) { fixupMessageRef(refs+i); } } ts.log("IMAGE TIMES: fix up objc_msgSend_fixup"); #endif
和
********************************************************************* * fixupMessageRef * Repairs an old vtable dispatch call site. * vtable dispatch itself is not supported. **********************************************************************/ static void fixupMessageRef(message_ref_t *msg)
这清楚地表明它不受支持。
另请参阅,objc-msg-x86_64.s
中找到的方法存根(如果没有编译器生成的调用站点)(<1}}:
ENTRY _objc_msgSend_fixup int3 END_ENTRY _objc_msgSend_fixup
其中int3
是SIGTRAP指令,如果未附加调试器(通常)会导致崩溃。
所以,虽然vtable dispatch在objective-c的历史中是一个有趣的注释,但是当我们不太熟悉优化常见方法调用的最佳方法时,它应该被视为一个实验。