RC RANDOM CHAOS

WATaBoy: a Game Boy emulator that JITs to WebAssembly — and outruns a native interpreter

· via Hacker News

Original source

WATaBoy: JIT-Ing Game Boy Instructions to WASM Beats a Native Interpreter

Hacker News →

Apple bans runtime JIT compilation on iOS, which is why heavyweight emulators like Dolphin can’t ship there. But there’s a loophole: web browsers are exempt, because engines like WebKit’s JavaScriptCore JIT-compile hot JavaScript and WebAssembly to native code. WATaBoy exploits this by generating Wasm bytecode at runtime instead of native machine code, then letting the browser’s own engine recompile that bytecode down to the metal — effectively borrowing a JIT you’re not allowed to write yourself. The author built it as an undergraduate final-year project, first as a plain interpreter and then as a JIT-to-Wasm, to benchmark the two approaches head to head.

The result is the project’s headline claim: emitting Wasm and leaning on the browser’s compiler beats running an interpreter natively. Game Boy hardware is an awkward target for JIT because it has to stay cycle-accurate, so WATaBoy borrows techniques from GameRoy — predicting when interrupts will fire, falling back to the interpreter whenever a compiled block could be interrupted, and lazily evaluating non-CPU components reached through memory-mapped I/O. The author concedes a Game Boy gains less from JIT than a sixth-generation console would, but it fit the scope of the project while still proving the technique.

The write-up’s most reusable contribution is the plumbing: generating and late-linking Wasm from Rust without wasm-bindgen or wasm-pack. It uses the wasm-encoder crate to emit modules directly and crosses the Rust–JS boundary through the C ABI with raw pointers and lengths. Because Wasm is a Harvard architecture, freshly generated bytecode can’t just be executed — the embedder (JavaScript) must compile and instantiate it, add the new function to the module’s indirect function table, and dispatch through call_indirect. A pending jit-interface proposal with a func.new instruction could one day remove that round-trip to JavaScript entirely.

Read the full article

Continue reading at Hacker News →

This is an AI-generated summary. Read the original for the full story.