Boosting WebAssembly Performance with Speculative Optimizations and Deoptimization in V8

By
<h2 id="introduction">Introduction</h2> <p>In the latest release of Google Chrome (M137), V8 introduced two powerful optimizations for WebAssembly: speculative <code>call_indirect</code> inlining and deoptimization support. Together, these techniques allow the compiler to generate faster machine code by making educated guesses based on runtime behavior. The result is a significant speed boost, especially for WasmGC programs. For instance, Dart microbenchmarks show an average improvement of over 50%, while larger applications and real-world benchmarks see gains between 1% and 8%. Deoptimization also lays the groundwork for future enhancements.</p><figure style="margin:20px 0"><img src="https://v8.dev/_img/wasm-speculative-optimizations/speculative-inlining-overview.svg" alt="Boosting WebAssembly Performance with Speculative Optimizations and Deoptimization in V8" style="width:100%;height:auto;border-radius:8px" loading="lazy"><figcaption style="font-size:12px;color:#666;margin-top:5px">Source: v8.dev</figcaption></figure> <h2 id="background">The Role of Speculative Optimizations in JavaScript</h2> <p>Fast JavaScript execution has long relied on speculative optimizations. Just-in-time (JIT) compilers collect feedback during earlier runs and make assumptions when generating code. For example, for the expression <code>a + b</code>, if past feedback shows both operands are integers, the compiler can produce streamlined integer addition code instead of handling every possible type (strings, floats, objects) generically. When those assumptions later prove wrong, V8 performs a <strong>deoptimization</strong> (or <em>deopt</em>) — it discards the optimized code and reverts to slower, unoptimized execution, gathering more data for a future tier-up.</p> <h2 id="why-not-wasm">Why WebAssembly Previously Didn’t Need Speculative Optimizations</h2> <p>WebAssembly has historically required less speculation. Its programs are statically typed — functions, instructions, and variables all have fixed types known at compile time. Moreover, WebAssembly binaries often come from C, C++, or Rust, languages that are easier to analyze statically. Ahead-of-time optimization tools like Emscripten (built on LLVM) or Binaryen already produce well-optimized binaries. For the original WebAssembly 1.0 (2017), this combination made speculative optimizations unnecessary.</p> <h2 id="wasmgc-impact">The Game-Changer: WasmGC</h2> <p>The introduction of <strong>WasmGC</strong> (the WebAssembly Garbage Collection proposal) changes the landscape. WasmGC supports compiling managed languages — such as Java, Kotlin, or Dart — to WebAssembly. Its bytecode is more high-level than Wasm 1.0, featuring rich types like structs and arrays, subtyping, and operations on these types. This complexity means that static optimization alone is less effective; speculative techniques can make a much bigger difference in the generated machine code.</p> <h2 id="optimizations">Two Key Optimizations: Speculative Inlining and Deoptimization</h2> <h3 id="speculative-inlining">Speculative <code>call_indirect</code> Inlining</h3> <p>Function inlining is a classic optimization that replaces a call site with the body of the called function, saving call overhead and enabling further local optimizations. In WebAssembly, indirect calls (through function tables) are common in object-oriented and functional patterns. Speculative inlining uses runtime feedback to guess which function will be called most often, and inlines that target. If the guess is correct, execution is fast; if not, the code must fall back to the original indirect call.</p> <h3 id="deoptimization-support">Deoptimization Support</h3> <p>To handle mispredictions, V8 now supports deoptimization for WebAssembly. When an assumption made during speculative inlining fails, the engine can <strong>deopt</strong>: it stops executing the optimized code, reverts to unoptimized code, and continues safely. This is the same mechanism used for JavaScript, adapted for WebAssembly. Without deoptimization, speculative inlining would be too risky – any wrong guess could crash the program or produce incorrect results. With deopt, the compiler can be aggressive and still maintain correctness.</p> <h2 id="performance">Performance Gains and Future Potential</h2> <p>Initial benchmarks are promising. For Dart microbenchmarks, combining both optimizations yields an average speedup of more than 50%. Larger, realistic applications see more modest but still valuable gains (1–8%). Beyond immediate performance, deoptimization is a building block for future speculative optimizations — for example, type feedback based on runtime profiles, or adaptive inlining decisions.</p> <p>As WebAssembly continues to evolve, especially with WasmGC, speculative optimizations will become increasingly important. V8’s work on speculative <code>call_indirect</code> inlining and deoptimization marks a step toward making WebAssembly execution as fast and dynamic as JavaScript’s, while preserving the security and portability that make WebAssembly attractive. Developers can expect their WasmGC applications to run faster with Chrome M137 and to benefit from further advances in the pipeline.</p>

Related Articles