voltar aos artigosadvanced topics
$cd~/artigos/javascript-engines-v8-motor-por-tras-do-codigo
Advanced Topics
série 33 Conceitos JS·parte 30 de 38

JavaScript Engines: O Motor Por Trás do Código

24 minVanderlei José Alamino

"Todo código JavaScript que você escreve é apenas uma sugestão para o motor. O motor decide como transformar suas ideias em instruções que o processador entende." — adaptado de Vyacheslav Egorov (engenheiro do V8)

Um motor JavaScript executa seu código — convertendo texto fonte em instruções que a CPU entende. O V8 alimenta Chrome, Node.js, Deno e Electron.

snippetJavaScript
function add(a, b) {  return a + b;}add(1, 2);  // 3 — mas o que acontece entre o texto e o resultado?

Neste guia da série 33 Conceitos JS — projeto open source criado por Leonardo Maldonado — você inicia a trilha Advanced Topics entendendo parsing, JIT, otimizações internas e GC.

Pré-requisitos: Call Stack e Event Loop — o motor e a fila assíncrona trabalham juntos.

javascript-engines-v8-motor-por-tras-do-codigo.meta.jsonjson

// metadados do artigo

{
  "tag": "advanced topics",
  "readTime": "24 min",
  "author": "Vanderlei José Alamino",
  "source": "33jsconcepts.com",
  "series": "33 Conceitos JS",
  "part": {
    "current": 30,
    "total": 38
  }
}
abrir fonte original
javascript-engines-v8-motor-por-tras-do-codigo.mdmarkdown

Fonte de referência

Conteúdo adaptado a partir do guia original em inglês.

33jsconcepts.com
01

seção

Analogia: A Fábrica V8

snippettext
Código fonte → Parser (tokens + AST) → Ignition (bytecode, rápido)              → TurboFan (código quente → máquina otimizada)              → Resultado

Trabalhadores manuais (Ignition) começam na hora; robôs (TurboFan) demoram a instalar mas são muito mais rápidos em tarefas repetidas.

02

seção

Motores JavaScript

Navegador / runtimeMotor
Chrome, Node, Deno, EdgeV8
FirefoxSpiderMonkey
SafariJavaScriptCore (Bun também)

Todos implementam ECMAScript — por isso JS se comporta igual no Chrome, Firefox ou Node. Foco aqui no V8, o mais implantado.

03

seção

Etapa 1: Parsing

Tokenização: código vira tokens (function, add, (, a, +, …).

AST (Abstract Syntax Tree): estrutura que captura o significado:

snippettext
FunctionDeclaration "add"  params: [a, b]  body: ReturnStatement    BinaryExpression: a + b

Explore ASTs em AST Explorer.

04

seção

Etapa 2: Ignition (Interpretador)

Ignition (V8 5.9+, 2017) gera bytecode compacto e executa imediatamente — sem esperar compilação.

snippettext
Ldar a1    // carrega aAdd a2     // soma bReturn

Enquanto roda, coleta profiling: funções quentes, tipos observados, ramos de if tomados.

05

seção

Etapa 3: TurboFan (Otimizador)

Funções quentes (muitas chamadas) vão ao TurboFan, que gera código de máquina assumindo tipos observados:

snippetJavaScript
function add(a, b) { return a + b; } add(1, 2);add(3, 4);// TurboFan: "sempre números" → código nativo rápido

Benefícios: sem interpretar bytecode a cada vez; menos checagens de tipo; inlining e dead code elimination.

06

seção

Desotimização

Suposições erradas → deopt — descarta código otimizado, volta ao Ignition:

snippetJavaScript
add(1, 2);       // otimizado para númerosadd("a", "b");   // strings! deopt

Gatilhos: mudança de tipo, hidden class diferente, call site megamórfico.

snippettext
Parse → Ignition ⇄ TurboFan → Executar         (profile)   (deopt se errado)
07

seção

Compilação JIT

AbordagemStartupExecução
Interpretação puraRápidoLenta
AOT (C++)LentoMuito rápida
JIT (V8)Rápido (Ignition)Rápida (TurboFan no quente)

JS é dinâmico — tipos desconhecidos em compile time. JIT observa runtime, otimiza o que vê, desfaz se errar.

Warm-up: primeira execução mais lenta; após muitas chamadas, código fica mais rápido — benchmarks incluem fase de aquecimento.

08

seção

Hidden Classes (Maps)

V8 rastreia formas de objetos internamente. Mesmas propriedades na mesma ordem → mesma hidden class:

snippetJavaScript
const p1 = { x: 1, y: 2 };const p2 = { x: 5, y: 10 };// mesma hidden class → x no offset 0, y no offset 1 const a = { x: 1, y: 2 };const b = { y: 2, x: 1 };  // hidden class DIFERENTE!

Cadeia de transição: {} → {x} → {x,y}. Prefira literais { x, y } a {} + atribuições sequenciais quando possível.

09

seção

Inline Caching (IC)

V8 cacheia onde achou uma propriedade para uma hidden class:

snippetJavaScript
function getX(obj) { return obj.x; } getX({ x: 1, y: 2 });  // miss → cacheia offsetgetX({ x: 3, y: 4 });  // hit — mesma forma
EstadoSignificadoPerformance
Monomórfico1 hidden classExcelente
Polimórfico2–4 formasBom
MegamórficoMuitas formasLookup completo

Factories com forma consistente mantêm IC monomórfico:

snippetJavaScript
function createPoint(x, y) { return { x, y }; }
10

seção

Garbage Collection (Orinoco)

Hipótese geracional: a maioria dos objetos morre jovem.

snippettext
Geração jovem (Scavenger, rápido, frequente)    ↓ sobreviventesGeração velha (Mark-Compact, completo, raro)

GC moderno: paralelo, incremental e concorrente — pausas raras na prática.

Veja também memória em Primitive Types e Primitives vs Objects.

11

seção

Código Amigável ao Motor

  1. Formas consistentes — mesma ordem de propriedades (createUser(name, age)).
  1. Tipos estáveis — evite count = 0 depois count = "none".
  1. Arrays densos — sem buracos; tipos homogêneos quando possível.
  1. Evite delete — muda hidden class; prefira undefined ou Map.
  1. Monomorfismo — mesma forma de objeto nas funções quentes (classes/factories).
  1. Evite eval() — impede otimizações do parser.
12

seção

Perguntas Clássicas de Entrevista

13

seção

Teste Seu Conhecimento

$ summary --quick

Resumo rápido

  • V8 — Chrome, Node, Deno; motor mais implantado
  • Pipeline — Parse → AST → Ignition → TurboFan
  • Ignition — bytecode imediato + profiling
  • TurboFan — otimiza código quente; deopt se suposição falhar
  • JIT — startup rápido + execução rápida no quente
  • Hidden classes — mesma ordem de props = mesma forma
  • Inline cache — monomórfico > polimórfico > megamórfico
  • GC geracional — Orinoco; jovens coletados frequentemente
  • Código previsível — tipos e formas estáveis ajudam o motor
  • Anti-padrões — delete, arrays esparsos, eval, tipos mutáveis

Créditos da série

Este artigo faz parte de uma série de estudos inspirada no projeto 33 Conceitos JS, criado por Leonardo Maldonado. Todo o conteúdo original está disponível em 33jsconcepts.com.