OBJC_PRINT_VTABLE_IMAGES 和 OBJC_PRINT_VTABLE_SETUP 不显示任何输出

OBJC_PRINT_VTABLE_IMAGES and OBJC_PRINT_VTABLE_SETUP does not show any output

我尝试在 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 是否已弃用?

在这种情况下,答案非常简单 - vtable 调度在 objective-c 运行时不再优化,一开始可能是个坏主意。

基于 vtable 的调度是在 objective-c 运行时加速频繁调用的首次尝试之一,但请注意,它早于当前的方法缓存解决方案。在 vtable 解决方案中使用一组固定的选择器的问题不仅意味着在运行时 中 每个 class 增加内存,而且还意味着如果你正在使用一种不会导致 isEqualToString: 被频繁调用的体系结构,例如,您现在在运行时有一个完全浪费的指针 EVERY class 覆盖了一个那些选择器。哎呀

此外,请注意 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 调度的残余片段。对代码库的快速 grep 显示 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:

中找到
ENTRY _objc_msgSend_fixup
int3
END_ENTRY _objc_msgSend_fixup

其中 int3 是 SIGTRAP 指令,如果未附加调试器(通常)会导致崩溃。

因此,虽然 vtable dispatch 在 objective-c 的历史上是一个有趣的记录,但在我们还不太熟悉优化通用方法的最佳方法时,它应该只是一个实验而已来电。