Spring is over us and several months have passed since we last shared an update on WebAssembly compilation.
Introduction
wasm_of_ocaml
is a compiler from OCaml bytecode to WebAssembly, similar to js_of_ocaml
from which it was forked. wasm_of_ocaml
offers a functional, almost drop-in replacement for js_of_ocaml
- with better performance.
For now, the compiler targets a JavaScript-hosted WebAssembly engine. The produced code furthermore requires the following Wasm extensions to run:
- the GC extension, including functional references and 31-bit integers
- the tail-call extension
- the exception handling extension
Platform support
- Node 22 now supports the WasmGC extension, meaning that it can run
wasm_of_ocaml
output out of the box! - CloudFlare uses V8 12.0 since Dec 4, 2023. This corresponds to Chrome 120, and thus includes the WasmGC extension, effectively enabling OCaml development on CloudFlare! For more details see the WebAssembly CloudFlare docs
- The upcoming 0.14.0 release of the WasmEdge WebAssembly engine adds WasmGC support too. Along with the just merged exception support, this paves the way for running
wasm_of_ocaml
output…
wasm_of_ocaml
news
Since the last update in December
- Jérôme gave a talk about
wasm_of_ocaml
at the INRIA Cambium seminar - slides available here - Olivier Nicole joined the
wasm_of_ocaml
effort - Jérôme and Olivier visited Jane Street to help them adopt
wasm_of_ocaml
Notable features
- Sourcemap support was added ocaml-wasm/wasm_of_ocaml#27
- This required adding sourcemap support to the
wasm-metadce
andwasm-merge
binaryen tools WebAssembly/binaryen#6372
- This required adding sourcemap support to the
- A first implementation of separate compilation was completed ocaml-wasm/wasm_of_ocaml#36
- One can compile cmo and cma files, producing intermediate archive files
- Then the files can be linked together: relevant Wasm modules are put in a directory, and JavaScript code is generated to load them and link them together
- Store long-lived toplevel values into globals ocaml-wasm/wasm_of_ocaml#30
- The initialization code produced by
wasm_of_ocaml
can be large and contain a large number of variables. This is challenging to both binaryen tools and the Wasm engines. The problem can be alleviated by storing long-lived toplevel values into global variables. As an side benefit, many closures can be statically allocated (since their free variables are now stored in globals), which again can provide performance improvements in the remaining parts of the code.
- The initialization code produced by
- Tuple syntax changes ocaml-wasm/wasm_of_ocaml#31
- Prepared the switch to the new version of binaryen, which has small syntax changes
- Use the JS String Builtins proposal for string conversions when available ocaml-wasm/wasm_of_ocaml#33
- Improve the WAT (Wasm text format) output to be more readable ocaml-wasm/wasm_of_ocaml#34
- Name local variables (they were just numbered) and use shorter names (the names used to be systematically suffixed to ensure they were unique).
Other features and fixes
- Fixed file descriptor management so that it works with large file descriptors ocaml-wasm/wasm_of_ocaml#18
- PR: Update Firefox version information in README (no longer beta) ocaml-wasm/wasm_of_ocaml#19
- PR: Fix pin branch in installation instructions ocaml-wasm/wasm_of_ocaml#20
- PR: Add
Stdlib.String.fold_{left,right}
to build on OCaml < 4.13 ocaml-wasm/wasm_of_ocaml#21 - PR translating stubs of
integers_js_stubs
to Wasm o1-labs/integers_stubs_js#10- Tracked a bug in a test on the repo o1-labs/integers_stubs_js#9
- PR: Generate valid Wasm code ocaml-wasm/wasm_of_ocaml#22
- PR: Avoid using
eval
for statically known strings ocaml-wasm/wasm_of_ocaml#24 - PR: Have physical equality inspect Javascript objects ocaml-wasm/wasm_of_ocaml#25
- PR: Tune optimization profiles ocaml-wasm/wasm_of_ocaml#26
- PR: Correction and precision about Binaryen version ocaml-wasm/wasm_of_ocaml#29
Binaryen fixes
- PR: wasm-merge: check that the types of imports and exports match. WebAssembly/binaryen#6437
- Improved binaryen’s linker to check that the types of imports and exports match. Found a type mismatch in the wasm_of_ocaml runtime this way.
- PR: Fixes regarding explicit names WebAssembly/binaryen#6466
- The name of some module components were lost during module linking
- PR: Fix writing of data segment names in name section WebAssembly/binaryen#6462
- Binaryen could actually generate a malformed name section