Learning Book

Архитектура 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)
ИнтерпретаторIgnitionBaselineLLInt
Mid-tierMaglevBaseline JIT
Opt. JITTurboFanIonMonkey → WarpDFG → 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Текст → ASTLazy parsing экономит время
IgnitionAST → байткодБыстрый стартСредняя
MaglevБайткод → машинный кодБыстрая компиляцияХорошая
TurboFanБайткод → оптимизированный машинный кодМедленная компиляцияМаксимальная