过去一年,作者致力于提高 SpiderMonkey JavaScript 引擎在编译为 WebAssembly 模块时的性能。对于使用 WebAssembly 及其“系统”层 WASI 作为软件分发和沙箱技术的服务器端应用,这是一项重要的使能技术。
在 WebAssembly 模块内部运行整个 JavaScript 引擎看似奇怪,但有实际用例,如某些平台出于安全原因接受 WebAssembly 沙箱化代码,此时 JavaScript 代码需自带引擎。这种方法可确保沙箱安全且有其他好处,如能与其他编译为 Wasm 的语言交互等。
现代 JavaScript 引擎通过在程序执行时收集信息并动态生成专门针对程序实际行为的机器码来提高性能,这需要平台支持运行时代码生成(JIT 编译)。但在 Wasm 模块中无法进行 JIT 编译,于是引入了内联缓存(ICs)来实现性能提升。
SpiderMonkey 引擎有三个利用 ICs 的 JIT 层:基线解释器解释 JS 函数体的操作码并通过 ICs 加速单个操作;基线编译器将 JS 函数体编译为机器码并通过 ICs 调度;优化编译器 WarpMonkey 内联 ICs 和 JS 字节码进行专门化编译。
在 WASI 程序中使用 ICs 存在问题,因为 IC 存根只能作为编译代码运行,且 SpiderMonkey 的基线解释器也是 JIT 编译的,这与 WASI 环境不兼容。于是引入了便携式基线解释器(PBL),它不依赖运行时代码生成,通过实现新的解释器循环和 CacheIR 解释器来替代原生基线解释器,在实现过程中面临了模拟栈、展开和模拟 VM 退出等挑战,并通过优化避免函数调用开销和开发混合 ICs 来提高性能。
结果显示,PBL 在实际应用中能显著降低 CPU 时间,在 Octane 基准测试中也有 1.26 倍的加速。未来计划将 PBL 上游到 SpiderMonkey 树中,并进一步开发将 JS 提前编译为高性能代码的技术,如利用 weval 工具生成带有专门函数的 Wasm 模块,通过部分评估实现类似 WarpMonkey 的优化,有望达到与 SpiderMonkey 原生基线编译器相当的性能。
许多人对该工作提供了帮助和反馈,作者对此表示感谢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。