Архитектура V8
Что такое JS-движок
JavaScript — интерпретируемый язык. Но «интерпретируемый» не значит «медленный». Современные движки используют JIT-компиляцию (Just-In-Time), превращая горячий код в машинные инструкции прямо во время выполнения.
V8 — движок JavaScript от Google. Используется в Chrome, Node.js, Deno и Electron. Написан на C++, открытый исходный код.
Другие движки:
- SpiderMonkey — Firefox (Mozilla)
- JavaScriptCore (JSC) — Safari (Apple)
Все три реализуют стандарт ECMAScript, но внутренние оптимизации различаются.
Pipeline V8
Путь JS-кода от текста до исполнения:
Source Code → Parser → AST → Ignition (байткод) → [Maglev] → TurboFan (машинный код)
1. Parser
Парсер разбирает исходный код в AST (Abstract Syntax Tree):
function add(a, b) { return a + b }
AST для этого кода — дерево, где корень = FunctionDeclaration, дочерние узлы = Identifier(add), Params(a, b), ReturnStatement(BinaryExpression(+)).
V8 использует два парсера:
- Pre-parser — быстрый, откладывает парсинг тел функций до первого вызова (lazy parsing)
- Full parser — полный парсинг, когда функция вызывается
Lazy parsing экономит время: если функция не вызвана, её тело не разбирается.
2. Ignition — интерпретатор
Ignition компилирует AST в байткод — компактные инструкции для виртуальной машины:
LdaSmi [1] // Загрузить число 1 в аккумулятор
Star r0 // Сохранить в регистр r0
Ldar a0 // Загрузить параметр a
Add r0, [0] // Сложить аккумулятор с r0
Return // Вернуть результат
Ignition выполняет байткод построчно и одновременно собирает type feedback — информацию о типах, которые встречаются в каждой операции. Эта информация нужна следующему этапу.
3. TurboFan — оптимизирующий компилятор
Когда функция вызывается достаточно часто (становится «горячей»), TurboFan компилирует её в оптимизированный машинный код:
function add(a, b) { return a + b }
// Первые 100 вызовов: Ignition (байткод)
// Вызов 101+: TurboFan увидел, что a и b всегда числа
// → генерирует машинный код для сложения двух int32
TurboFan использует type feedback от Ignition для спекулятивных оптимизаций — предполагает, что типы не изменятся, и генерирует специализированный код.
4. Maglev — промежуточный tier
Maglev — компилятор между Ignition и TurboFan. Он генерирует код быстрее, чем TurboFan, но менее оптимизированный:
Ignition (быстрый старт) → Maglev (быстрая компиляция) → TurboFan (максимальная оптимизация)
Это позволяет быстрее получить скомпилированный код, не дожидаясь полной оптимизации TurboFan.
Сравнение с другими движками
| V8 (Chrome) | SpiderMonkey (Firefox) | JSC (Safari) | |
|---|---|---|---|
| Интерпретатор | Ignition | Baseline | LLInt |
| Mid-tier | Maglev | — | Baseline JIT |
| Opt. JIT | TurboFan | IonMonkey → Warp | DFG → FTL |
| Lazy parsing | Да | Да | Да |
Архитектура похожа: все используют многоуровневую компиляцию. Различия — в деталях оптимизаций и стратегиях tier-up.
WebAssembly pipeline в V8
WebAssembly (Wasm) проходит отдельный pipeline:
.wasm → Liftoff (быстрая компиляция) → TurboFan (оптимизация)
Liftoff — одноходовой компилятор Wasm. Генерирует код за один проход по байткоду, без создания графа. Это даёт мгновенный старт, а TurboFan оптимизирует горячие функции в фоне (streaming compilation).
V8 также поддерживает Wasm GC — сборку мусора для Wasm-объектов, что позволяет языкам с GC (Kotlin, Dart) компилироваться в Wasm без собственного GC.
Итого
| Этап | Роль | Скорость запуска | Скорость исполнения |
|---|---|---|---|
| Parser | Текст → AST | Lazy parsing экономит время | — |
| Ignition | AST → байткод | Быстрый старт | Средняя |
| Maglev | Байткод → машинный код | Быстрая компиляция | Хорошая |
| TurboFan | Байткод → оптимизированный машинный код | Медленная компиляция | Максимальная |