I have since improved dynamic binding support in wasi-kernel, which allows to bind to JS functions as well without needing the C stub to cross the border between OCaml and C. That is, the stub exists, but it is part of wasi-kernel and is introduced on demand.
This is how this mechanism was used in waCoq.
These glue binders are generated by this script: https://github.com/corwin-of-amber/wasi-kernel/blob/master/scripts/autogen-delegation.js.
It is unfortunately not very impressive. Loading objects (i.e. Dynlink’ing .cmas) is much faster, whereas executing the code itself is pretty much on par; sometimes faster, sometimes slower. The V8 JIT is extremely good with tight loops, and the WASM runtime is not there yet, so if you have such loops in your code, you can expect the interpreted version to be slower.
In my experience, Firefox tends to be slower. It will be interesting to benchmark at some point. The lightweight JS’s have no JIT so you can expect them to be the slowest. Android browsers are also weak on that front because of the memory consumption overhead that JIT incurs.