-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
WebAssembly still has no support for jump instructions or funclets. All control flow between basic blocks has to be expressed via if/switch
and loop
constructs. This means that a CFG with arbitrary control flow can not be directly expressed in wasm. (I still haven't seen a good explanation for this design choice except that V8 supposedly would have a hard time supporting arbitrary control flow).
The advertised solution for this limitation is to use the Relooper algorithm to turn arbitrary control flow back into structured control flow. Unfortunately this approach is incompatible with unwinding and restoring the stack when switching goroutines. This is why Go is not using the Relooper but instead quite naively uses a jump variable and a jump table at the beginning of each function (a loop and a huge switch
). The performance overhead of this approach is quite bad.
In the long term, wasm stack switching might offer a solution that can avoid unwinding the stack. Until then, it has come to my attention that there is an intermediate solution called Asyncify. This is a post-processing pass on a wasm binary that adds stack unwinding but does so in a much more optimized way than the Go compiler currently does.
I propose using Asyncify within the Go compiler. This should give a very significant performance gain. As a consequence we would need to also implement the Relooper algorithm or some newer alternative called the Stackifier. A downside would be that it would add a compile time depencency to Binaryen's wasm-opt
command which implements Asyncify. This dependency would go away when wasm stack switching is available.
For more context see WebAssembly/design#796, especially WebAssembly/design#796 (comment).
Metadata
Metadata
Assignees
Labels
Type
Projects
Status