用途:指导在 C/C++ 中实现高效字节码解释器与简单 JIT,涵盖分派策略、VM 架构选择与性能模式。
主要能力:
- VM 架构选型:基于栈(如 JVM、CPython、WebAssembly)、基于寄存器(Lua 5+、Dalvik)、直接线程化、续延传递式,并比较各自实现难度与指令数量。
- 分派循环:switch 分派(基准实现,单间接分支易误预测)、computed goto(GCC/Clang 扩展,用 &&label 与分派表,每个操作码独立间接分支以提升预测率,需 #ifdef GNUC 守卫并回退 switch)、直接线程化(字节码为处理函数指针数组)。
- 值表示:带标签指针(低比特存类型标签)与 NaN boxing(64 位,用于 V8、LuaJIT、JavaScriptCore)。
- 栈管理:stack/sp 指针与 PUSH、POP、TOP、PEEK、PUSH_SAFE 宏及溢出检查。
- 内联缓存(IC):缓存调用点接收者类型与方法指针,支持多态 IC(PIC,通常缓存 4 对)。
- 简单 JIT:x86-64 下用 mmap 分配可读写可执行内存并写入机器码,示例为 add 函数;macOS Apple Silicon 需用 pthread_jit_write_protect_np() 或 MAP_JIT,必要时用 mprotect。
- 性能建议:优先 computed goto、用 NaN boxing 或带标签指针、将栈指针放入被调用者保存寄存器、常用局部变量放 VM 寄存器、用 perf 采样、为常见类型组合生成特化处理函数、参考 LuaJIT 的 trace JIT。
适用场景:设计字节码 VM、优化解释器分派性能、为解释器加入基础 JIT。
限制:computed goto 为 GCC/Clang 扩展,非标准 C;JIT 涉及可执行内存,跨平台保护方式不同。资料未提供具体基准数据与各平台完整示例。