V8 — JavaScript 引擎内核
Chrome 和 Node.js 的 JavaScript 引擎——Ignition 解释器 + TurboFan JIT + Orinoco GC + libuv 事件循环。
概念
V8 是 Google 开发的高性能 JavaScript 引擎,用 C++ 编写。它的”内核”从不直接执行 JS 源码——而是先编译为字节码 (Ignition),再将热点路径编译为机器码 (TurboFan)。V8 内核对”动态类型语言如何接近静态语言性能”这个问题给出了产业级答案。
核心组件
| 组件 | 职责 | 关键概念 |
|---|---|---|
| Ignition | 字节码解释器, 生成并执行 V8 字节码 | accumulator register |
| TurboFan | 优化 JIT 编译器, 字节码 → 机器码 | sea-of-nodes IR |
| 隐藏类 (Hidden Classes) | 对象形状的动态优化 | Map 对象, 转换链 |
| Orinoco GC | 并行标记 + 增量清除 + 压缩 | 分代 + 并发 |
| Isolate | V8 虚拟机实例 (独立堆) | 线程安全隔离 |
| libuv 事件循环 | 提供异步 I/O, 定时器, 信号 | epoll/kqueue/IOCP |
Ignition 字节码解释器
// JS 源码
function add(a, b) {
return a + b;
}
add(3, 4);
// 内部编译为 Ignition 字节码 (简化表示)
// function add:
// LdaUndefined // accumulator = undefined (预检查)
// Ldar a1 // accumulator = a1
// Add a2, [0] // accumulator += a2, 反馈槽 0
// Return // 返回 accumulator
//
// 调用:
// LdaSmi [3] // accumulator = 3
// Star r0 // r0 = accumulator
// LdaSmi [4] // accumulator = 4
// Star r1 // r1 = accumulator
// LdaGlobal [add] // accumulator = add
// Call1 r0, r1 // 调用 add(r0, r1)隐藏类 (Hidden Classes)
// 与 C++ vtable 类似但动态创建
var o = {}; // o.Map = M0 (空对象形状)
o.x = 5; // o.Map = M1 (拥有 int x) [M0 --(.x)--> M1]
o.y = "hello"; // o.Map = M2 (拥有 x, y) [M1 --(.y)--> M2]
var p = {}; // p.Map = M0 (复用!)
p.x = 10; // p.Map = M1 (复用!)
p.y = "world"; // p.Map = M2 (复用!)
// 如果两个对象有相同的隐藏类 (Map), 说明它们属性名、顺序、类型一致
// TurboFan 就可以像访问 C 结构体一样在固定偏移量处读写属性
// 这就是 V8 为何快: 把动态对象当静态结构体优化
TurboFan JIT 编译
Ignition 收集类型反馈 (Type Feedback):
add(3, 4) → 两个参数都是 Smi (小整数)
add(3.2, 4.1) → 两个参数都是 Float64
当调用 add 足够多次 (热点):
TurboFan 基于类型反馈生成优化后的机器码:
IF 两个参数都是 Smi:
result = a + b (整数加法, 一条 CPU 指令)
CHECK overflow
RETURN result
ELSE:
DEOPTIMIZE → 退回到 Ignition (去优化)
去优化 (Deoptimization):
当假设被打破时 (例如 add 收到了字符串参数)
TurboFan 生成的代码检测到类型不匹配
丢弃编译的机器码, 从 Ignition 字节码重新继续执行
Orinoco GC
| 阶段 | 算法 | 是否并发 |
|---|---|---|
| 标记 (Mark) | 从 roots 出发追踪可达对象 | 并发 + 并行 |
| 清除 (Sweep) | 释放不可达对象 | 增量 (与 mutator 交替) |
| 压缩 (Compact) | 移动存活对象消除碎片 | STW (极短) |
| 新生代 (Young Gen) | Scavenge (Cheney 算法) | 并行 |