Turboshaft: Steering Away from the Sea of Nodes in V8’s Compiler

By

V8’s top-tier optimizing compiler, Turbofan, has long been known for its use of the Sea of Nodes (SoN) intermediate representation—a rarity in production compilers. However, three years ago, the V8 team began transitioning away from SoN toward a traditional Control-Flow Graph (CFG) intermediate representation called Turboshaft. Today, the entire JavaScript backend of Turbofan runs on Turboshaft, and WebAssembly uses it throughout its pipeline. Only two parts of Turbofan still rely on SoN: the builtin pipeline (being gradually replaced by Turboshaft) and the JavaScript frontend (being replaced by Maglev, another CFG-based IR). This Q&A explores the motivations behind this major architectural shift.

What is the Sea of Nodes, and why did V8 originally adopt it?

The Sea of Nodes (SoN) is a graph-based intermediate representation that eliminates the distinction between control flow and data flow, allowing operations to be reordered freely. V8 adopted SoN for Turbofan to overcome limitations in its previous compiler, Crankshaft. Crankshaft used a rigid CFG that could not introduce new control flow during lowering—a major drawback for optimizations. SoN promised more flexibility by representing control dependencies implicitly, enabling aggressive reordering and elimination of redundant checks. It also aimed to reduce performance cliffs by allowing more speculative optimizations. At the time, SoN appeared to be the best way to handle JavaScript’s dynamic nature and to support complex features like try-catch, which Crankshaft could not handle. However, as Turbofan matured, the team discovered that SoN introduced its own complexities in implementation and debugging, leading to maintenance difficulties and missed optimization opportunities.

Turboshaft: Steering Away from the Sea of Nodes in V8’s Compiler
Source: v8.dev

What were the biggest problems with Crankshaft?

Crankshaft, V8’s first optimizing compiler, suffered from several critical issues. First, it required manual assembly code for every new IR operator across four architectures (x64, ia32, arm, arm64), creating heavy maintenance overhead. Second, it struggled to optimize asm.js efficiently—a major concern when asm.js was seen as a path to high-performance JavaScript. Third, and most limiting, Crankshaft could not introduce new control flow during lowering; control flow was fixed at graph-building time. For example, lowering a generic JSAdd(x, y) to handle string concatenation required branching logic, but Crankshaft could not generate such branches late in compilation. Fourth, try-catch constructs were unsupported despite months of engineering effort. Fifth, the compiler exhibited severe performance cliffs—using certain features could cause a 100x slowdown, making performance unpredictable for developers. Finally, deoptimization loops were common: Crankshaft would re-optimize with the same faulty assumptions, repeatedly degrading performance.

Why is V8 moving away from the Sea of Nodes?

While the Sea of Nodes solved some Crankshaft problems, it introduced new challenges over time. The graph representation made it hard to reason about control flow ordering, especially for complex optimizations like register allocation and instruction scheduling. The V8 team found that many optimizations required precise control-flow information, which SoN obscured. Additionally, debugging and tuning SoN-based code became increasingly difficult as Turbofan grew. The team also realized that a well-designed CFG IR could achieve similar flexibility without the overhead. Turboshaft, the new CFG-based IR, provides explicit control flow while still allowing late lowering and speculative optimizations. It simplifies code generation, reduces maintenance costs, and enables better performance for modern JavaScript and WebAssembly workloads. The shift is also driven by the desire to unify the compiler pipeline: Turboshaft can be used across both JavaScript and WebAssembly, reducing duplication of effort.

What is Turboshaft and how does it differ from the Sea of Nodes?

Turboshaft is a new intermediate representation built on a traditional Control-Flow Graph (CFG). Unlike the Sea of Nodes, where control and data dependencies are mixed in a single graph, Turboshaft separates basic blocks (control flow) from operations (data flow) within each block. This makes it easier to reason about the order of execution and simplifies passes like register allocation and scheduling. Turboshaft retains the ability to lower high-level operations into multiple low-level steps using lowering passes that introduce new blocks when needed—something Crankshaft could not do but which SoN supported awkwardly. The design also reduces the complexity of maintaining optimizations across different architectures. By using a CFG, Turboshaft aligns with most modern compilers, making it easier to port optimizations from other projects. The result is a more maintainable and predictable compiler that can achieve high performance without the hidden costs of SoN.

What parts of Turbofan still use Sea of Nodes today?

As of now, two components of Turbofan continue to use the Sea of Nodes. The first is the builtin pipeline, which compiles V8’s built-in JavaScript functions. This pipeline is being gradually rewritten to use Turboshaft, but the transition is not yet complete. The second is the frontend of the JavaScript pipeline, which converts JavaScript into an initial IR. That frontend is being replaced by Maglev, a new CFG-based intermediate representation designed specifically for high-throughput compilation. For the JavaScript backend and the entire WebAssembly pipeline, Turboshaft has already fully replaced Sea of Nodes. The V8 team expects that once Maglev and Turboshaft cover all use cases, Sea of Nodes will be entirely removed from the codebase, simplifying the compiler architecture and reducing maintenance burden.

How does Turboshaft improve performance and developer experience?

Turboshaft improves performance in several ways. By using a CFG, it enables more precise register allocation and instruction scheduling, leading to tighter generated code. It also reduces the number of compiler crashes and miscompilations because control flow is explicit and easier to verify. For V8 developers, Turboshaft is easier to debug and extend: optimizations can be written as straightforward passes over basic blocks rather than as complex graph transformations. The IR also supports better integration with WebAssembly, allowing the same backends to be shared. For JavaScript developers, Turboshaft eliminates many performance cliffs that existed in Turbofan’s Sea of Nodes era—code now behaves more predictably. Additionally, the move to CFG aligns V8 with other modern compilers, making it easier to adopt new research and optimizations from the broader compiler community.

What is the current status of the migration from Sea of Nodes to Turboshaft?

The migration to Turboshaft is well advanced. The JavaScript backend of Turbofan already uses Turboshaft exclusively, and the WebAssembly pipeline is fully on Turboshaft. The two remaining areas—the builtin pipeline and the JavaScript frontend—are under active development. For the builtin pipeline, the team is incrementally porting each built-in function to use Turboshaft. For the frontend, Maglev (a CFG-based IR) is being developed to replace the Sea of Nodes frontend. Meanwhile, the original Turbofan code with Sea of Nodes is still maintained for compatibility but receives fewer optimizations. The V8 team estimates that within the next year, the Sea of Nodes will be completely phased out, leaving a cleaner, more maintainable compiler architecture that can more easily adapt to future JavaScript and WebAssembly features.

Related Articles

Recommended

Discover More

The Step-by-Step Process of How Mangroves Filter Billions in Nitrogen Pollution7 Key Insights into GRASP: Making Long-Horizon Planning with World Models PracticalEvaluating Your Website's AI Agent Compatibility: A New Standard for the WebBreaking: VS Code Custom Snippets Let Developers Slash Repetitive CodingCritical Security Patches Roll Out Across Major Linux Distributions