现代网站如 Google Docs 和 Gmail 执行的 JavaScript 太多,以至于引擎速度存在两个独立的瓶颈。Firefox 的 C++ 字节码解释器速度慢,且不收集类型信息,而 Baseline JIT 将每个函数编译为机器码;在重页面上,这意味着要编译数千个函数,因此时间花在编译上而非运行上。优化 Ion JIT 只有在 Baseline JIT 收集了类型数据后才能快速运行。

明显的修复各有代价:加速 C++ 解释器,但它仍然无法为优化器提供类型数据;延迟或移动 Baseline 编译,则冷路径或退出可能变得危险;在 JIT 代码中间恢复 Ion 的退出,则每个特性都需要额外的元数据和复杂的调试器及异常处理代码。Mozilla 转而添加了一个新层级,Baseline Interpreter,位于 C++ 解释器和 Baseline JIT 之间。

让这一做法廉价的关键不是从头编写解释器。Baseline JIT 是一个模板 JIT:每条字节码指令已映射到大致固定的机器码序列。Mozilla 将这些序列生成到线程化解释器循环中,共享一个模板代码生成器、相同的帧布局,以及一个包含内联缓存和性能数据的 JitScript 结构,两个层级都使用。

由于解释现在收集类型信息,Baseline JIT 的预热阈值可以从 10 提高到 100,从而大幅减少被编译的函数数量。Firefox Nightly 测得页面加载速度提升 2-8%,devtools 测试速度提升 2-10%,内存节省,代码更简洁:Ion 的退出在解释器中恢复,许多复杂的调试器和异常处理机制被删除。

从快速层级的同一代码生成器生成廉价层级,这样缓存和类型数据保持一致

复用 JIT 的代码生成器意味着,解释器行为与内联缓存与 JIT 在构造上一致,无需第二个实现来保持同步。

解释现在收集与 JIT 之前使用的相同的类型数据,因此优化层级无需等待编译即可获得其性能数据。

将 JIT 预热阈值提高十倍,大幅减少了 JS 密集型页面上被编译的函数数量。

退出、调试器支持和异常处理变得更简单,因为 Ion 在解释器中恢复,而不是在 JIT 代码中间,需要的元数据更少。

进入中间层级成本低:JitScript 分配至少比 Baseline JIT 编译快 10 倍。

不要在慢速和快速层级之间手写中间层级:从快速层级的模板生成它,这样缓存、帧和行为在构造上保持一致

Baseline Interpreter 于 2019 年 7 月在 Firefox Nightly 中落地,并计划于当年 10 月在 Firefox 70 中发布。Mozilla 的测量显示页面加载速度提升 2-8%,devtools 测试速度提升 2-10%,且内存节省。它带来的代码清理也加快了 Baseline JIT 编译,团队宣布的下一步是将该编译移出主线程。

从这里,追溯依据

参考来源

  1. The Baseline Interpreter: a faster JS interpreter in Firefox 70 hacks.mozilla.org
  2. Hacker News discussion: The Baseline Interpreter: a faster JS interpreter in Firefox 70 news.ycombinator.com