awesome-everything RU
↑ Back to the climb

Browser & Frontend Runtime

V8 internals: hunt a deopt and a megamorphic IC

Crux Hands-on project — drive a hot JS path into a megamorphic IC and a deopt-loop, diagnose it with d8 and --trace-deopt, then fix the shape and numeric type and prove the win with before/after numbers.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 240 min

Reading about megamorphic ICs and deopt-loops is not the same as pulling a hot path out of one. Build a small allocation-and-compute-heavy workload, deliberately drive it into V8 trouble, then use d8 and —trace-deopt to diagnose and fix it — with evidence at every step.

Goal

Turn the unit’s mental model into a reproducible loop: instrument tier and IC state, reproduce a megamorphic site and a deopt-loop, fix the shape and numeric type upstream, and verify the recovery with before/after measurements.

Project
0 of 7
Objective

Take a deliberately V8-hostile hot path (your own or the starter below) and bring its hot site back to a monomorphic IC and a stable TurboFan tier with zero deopt-loop — proving each step with d8 natives-syntax output and --trace-deopt, not by guessing.

Requirements
Acceptance criteria
  • A before/after table: IC slot state (mega → mono), optimisation tier (%GetOptimizationStatus), deopt count from --trace-deopt, and hot-loop throughput — all measured, not estimated.
  • %DebugPrintFeedback clearly shows the target slot moving from MegamorphicSentinel to a single hidden class after the fix.
  • --trace-deopt produces no deopt for the hot function under representative input after the numeric-type fix; the deopt-loop signature is gone.
  • A one-paragraph write-up naming, for each problem, which lever you used (constructor shape, drop delete, null-fill, | 0, or TypedArray) and why it beat tuning any flag.
Senior stretch
  • Add a parallel-TypedArray variant of the hot loop (Float32Array per field) and compare its throughput and per-frame GC against the fixed-object version — quantify the IC-bypass and zero-allocation win.
  • Add a perf-budget test that runs the hot path under representative inputs and asserts --trace-deopt is empty and %GetOptimizationStatus reports an optimised tier; fail CI on any regression.
  • Reproduce one of the unit's real-world failures in miniature (Discord-style polymorphic render IC, Slack-style periodic NaN deopt, or Maps-style optional-field megamorphism) and write the one-line root cause and the upstream fix.
  • Take a heap snapshot before and after a closure-leak variant (a per-frame closure captured by a long-lived callback) and show old-gen growth, then fix by hoisting the closure and re-snapshot to confirm.
Recap

This is the loop you run in every real V8 incident: instrument the tier and IC state with d8 natives syntax and —trace-deopt, reproduce the megamorphic site and the deopt-loop so you can see them, fix the shape and the numeric type upstream in the data model, and verify with before/after numbers under identical input. Doing it once on a toy script makes the production diagnosis — where the regression hides in a small refactor — muscle memory.

Continue the climb ↑What workers are and why they exist
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.