首页 / 文章 / 让你的JIT编译代码被系统感知:方法一览
← 返回
AI技术

让你的JIT编译代码被系统感知:方法一览

✍️ zhirenhun 📅 2026/7/3 👁 81 阅读 ⏱ 7 分钟
让你的JIT编译代码被系统感知:方法一览

让你的JIT编译代码被系统感知:方法一览

作者:Timo Paulssen | 2026年3月10日 | 阅读时间约12分钟

原文标题:Making your JITted Code known: Let me count the ways


AOT编译器与元数据

长期以来,编译器产生的机器码都会附带元数据,供目标系统的各个部分使用——这是再正常不过的事情。这些元数据包括函数的符号名称、带有行号标注的调试数据,以及异常处理表(exception handling tables)。

对于像 C++ 这样支持异常(exceptions)的语言,编译器中存在专门的表,记录了运行时所需的全部信息:当异常被抛出时,栈上的每一帧(frame)应当如何处理。这一过程被称为"栈展开"(stack unwinding)——即移除栈帧,就好像代码已经从这些函数中返回了一样。


MoarVM 与 longjmp 问题

MoarVM 是 Raku 编程语言的运行时,使用 C 语言编写。它采用 longjmp 来实现异常处理。当一个操作码(opcode)遇到问题时,它会调用 MVM_exception_throw_adhoc,从 C 栈的任意深度直接跳回解释器循环(interpreter loop)。

Windows 上 MSVC 的一个变动导致 longjmp 总是逐帧完全展开整个栈。对于纯 C 代码来说,这通常是不必要的,因为 C 本身没有每函数级(per-function)的清理操作。但问题在于,MoarVM 拥有一个 JIT 编译器。在 longjmp 发生时,JIT 编译的代码可能已经在栈上留有帧,而 JIT 编译器并没有提供任何数据让 Microsoft 的 longjmp 正确处理这些帧,从而导致崩溃。

修复方案涉及为 JIT 编译的代码生成展开信息(unwind information),并在 Windows 上通过 RtlAddFunctionTable 注册这些信息——或者采用 Patrick Böker 发现的更简便方法。


让 JIT 编译代码被系统感知的几种方法

又快又简单:Perf Map

最简单的方法。编写一个文本文件,每行对应一个 JIT 函数:地址、长度、名称。MoarVM 从 2018 年 9 月起就支持此功能。它可以与 Linux 的 perf 工具配合使用,但 perf 无法显示这些函数的汇编代码。

详尽完备:完整的可加载共享对象

创建一个完整的 ELF/DLL/dylib 文件,写入磁盘,然后通过 dlopen 加载。这种方法可以与所有外部工具配合使用,但需要保留文件在磁盘上,并且需要手写正确的 ELF 结构。

JIT编译器示意图

RtlAddFunctionTable 与 _U_dyn_register

RtlAddFunctionTable(Windows)和 libunwind 的 _U_dyn_register 允许你提供展开信息(unwind info)。它们可以为函数赋予名称并提供展开指令,但并非总能完美运行。

JITDUMP 格式

专为 Linux 的 perf 工具设计。提供函数名称、展开表(unwind table)以及行号标注。需要额外进行后处理步骤。

GDB 的 JIT 调试信息读取器

允许你向 GDB 提供任意信息,但操作非常繁琐,全部需要手动完成。


为什么这很重要

当 JIT 编译器在运行时生成机器码时,操作系统和调试器并不会自动知道这些代码的存在。如果没有正确的注册机制,栈展开(stack unwinding)将会失败,性能分析工具(profiler)无法将 CPU 时间归因到特定的 JIT 函数,调试器无法设置断点,崩溃报告中也只会显示无意义的地址而非函数名称。

对于任何带有 JIT 编译器的语言运行时来说,向系统注册 JIT 代码对于可调试性(debuggability)、性能分析(profiling)和可靠性(reliability)都是至关重要的。具体选择哪种方法,取决于目标平台、工具链需求以及性能约束。

原文出处:https://wakelift.de/2026/03/09/making-your-jitted-code-known-let-me-count-the-ways/

🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

JIT 编译器 MoarVM Raku 调试
← 上一篇
LMDB 1.0:闪电内存映射数据库管理器
下一篇 →
牵绳式AI编程法:如何写出超越Fable的高质量代码

📌 相关推荐

结构化输出 vs 工具使用 vs 预填充:2026年从Claude获取JSON
2026/7/11
在AWS Bedrock上构建生产级AI代理——值得关注的架构与代码决策
2026/7/11
如何为你的AI代理构建评估框架(确保其在生产环境中不崩溃)
2026/7/11
← 返回文章列表