WebAssembly architecture for Go(docs.google.com) |
WebAssembly architecture for Go(docs.google.com) |
Web Assembly GC is not a performance optimization; it's necessary for correctness.
I’m looking forward to the results of this work!
https://github.com/gopherjs/gopherjs
...and already has a reasonable js interop story, whereas my understanding is that calling the dom api from wasm is not the simplest thing.
Is that right? Close? An oversimplification. Way off?
I don't think it's hard to imagine reading the GC proposal. The JS collector that might be reused could be off thread, something WASM can't (yet) do.
> Most file system operations are mapped to Node.js’ “fs” module. In the browser, file system operations are currently not available.
Please please abstract this. As a maintainer of a non-JS WASM backend, I'd love to use Go too.
> Especially a “goto” operation in WebAssembly would be very helpful.
I didn't look into the Go use case enough, but curious how much better this would be than the current labeled block and labeled break approach in WASM. WASM has fairly strict stack/frame rules/types, so arbitrary gotos wouldn't work.
Wasm exists because it's small and incremental; there's lots of stuff that's needed, but not in the initial spec. As long as it can be added in the future, that's what matters.
Or in other words, the “stack machine” is basically just a compact encoding of an AST.
(Note that the native “stack” is an entirely separate thing which does exist at runtime.)
[1] Actually, there can be multiple possible instructions from, e.g., inside the ‘if’ and ‘else’ sides of a prior if-block (which can push values that stay on the stack after the end of the block). But since both sides have to push the same number of values, this is still tractable; it turns into a phi node in SSA representation.
No off-the-shelf GC will ever be perfect for all languages, thus I think WASM would be far better off doing whatever it could to facilitate runtimes implementing their own.
(!) Example from the lazy world: lazy closures when evaluated and updated often results in an indirection. We rely on GC to shortcut these. Sometimes we even have GC perform trivial constant-time evaluations when we know the result is smaller than the suspended evaluation.
Example from the Lisp world: cdr-coded cons cells can cut size in half, but no generic GC would be able to do this.
[1] https://docs.google.com/document/d/131vjr4DH6JFnb-blm_uRdaC0...
Say you have the code C=A+B in your program.
The generated assembly for a real machine looks something like this: (R* denote registers and A-C are memory addresses) load A->R1 load B->R2 add R1+R2->R3 store R3->C
WASM looks more like this: push A push B add pop C
This alone makes the approach to code generation and optimization quite different.
WASM does lack some features that you would find in real CPUs, most notably the ability for execution to jump to arbitrary memory locations. They had to work around this to maintain the behavior of goroutines. Functions also live in their own address spaces which necessitates a change to how the program counter works.
It's more that Go _requires_ a runtime to support certain features which require Garbage Collection. The requirement of a runtime in turn dictates a different architecture to run on WebAssembly.
The link does talk about GC support. It looks like wasm will have one, but go’s will most likely perform better since it is tailored to go. (edit for clarification)
I assume a lot of the planning for this was in the GitHub and mailing list discussions dedicated to go’s wasm support. I’m on mobile but I can link those later.
There is no way around porting the runtime as well.
Go needs multiple stacks and a way to switch to executing a different stack. Web assembly could provide this in a high-level way.
On languages where the algorithm is an implementation detail, one can make use of reference counting with a cycle collector, which are just a few hundred lines.
Implementing one is pretty simple, making it perform well is another matter.
You can still do it, of course and performance isn't even that bad. See Fabrice Bellard's x86 emulator using asm.js.
You can, of course, compile your GC in today, and it will work. Wasm's integrated support will mean re-using the existing GC, which means smaller code size.
Side note: most people thought this would be a precursor to DOM support, but the new "host bindings" proposal opens up DOM support without needing GC support, and many people believe that now the former will land before the latter.
Can Go simply run with the WASM GC or does it need some specific type of GC?
See https://github.com/WebAssembly/gc for the current proposal.
To go the extra mile in GC performance, the compiler and GC implementation have to collaborate, taking advantage of language specific features.
But one day, when there are implementations, can every language run with the WASM GC?
One could use WASM for reconfigurable on-edge computing, all the way down to microcontrollers.