V8 通过解析生成AST、Ignition编译为带类型反馈的字节码、TurboFan对热点函数优化编译为机器码,并在类型变化时去优化回退,实现高效动态执行。

解析阶段:生成抽象语法树(AST)
JavaScript 是动态弱类型语言,V8 不会直接编译源码为机器码,而是先做词法分析和语法分析。源代码被切分成 token(如 const、function、括号、标识符等),再按语法规则组装成抽象语法树(AST)。这棵树不包含执行细节,只表达结构关系——比如 add(1, 2) 会生成一个 CallExpression 节点,子节点分别是 Identifier 和两个 NumericLiteral。
解释执行与字节码:Ignition 引擎的作用
V8 在 2017 年引入 Ignition,取代了早期纯解释器。它把 AST 编译成轻量、平台无关的字节码(Bytecode),例如 Ldar(加载寄存器)、Star(存入寄存器)、CallRuntime(调用运行时函数)。字节码体积小、生成快,适合快速启动;同时自带类型反馈(Feedback Vector),记录某次 a + b 中 a 和 b 的实际类型(如都是 number),为后续优化提供依据。
热点代码识别与 TurboFan 优化编译
Ignition 执行过程中持续监控函数调用次数和循环执行次数。当某个函数被调用超过阈值(通常约 100 次),就标记为“热点函数”,触发 TurboFan 编译器介入。TurboFan 基于字节码 + 类型反馈,执行多轮优化:
- 内联小函数(如
Math.max的简单分支) - 去虚拟化(将
obj.method()根据反馈确定为固定函数,消除查表开销) - 类型特化(假设
x总是 int32,则跳过类型检查,直接用整数加法指令) - 死代码消除、常量传播、循环展开等通用优化
最终输出高度优化的、特定 CPU 架构的机器码(如 x64 或 ARM64 指令),并替换掉原来的字节码版本。这个过程叫 “on-stack replacement”(OSR),正在执行的循环也能无缝切换到新版本。
去优化与重编译:应对类型不稳定
优化依赖类型反馈,但 JS 允许运行时改变类型。比如某函数前 99 次接收 number,第 100 次突然传入 string,已生成的优化代码就会失效。此时 V8 触发去优化(deoptimization):暂停执行、恢复到字节码状态、清空该函数的优化代码,并降级回 Ignition 解释执行。若后续再次成为热点且类型稳定,会重新触发 TurboFan 编译——可能生成另一版适配新类型的机器码。

















