-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
all: WebAssembly ("wasm") support #18892
Comments
@cherrymui and I discussed the possibility of a wasm GC port at length in
the past few days:
Our current conclusion is that there is no efficient way to implement
setjmp/longjmp functionality currently, therefore it's not a viable target
of a gc port. We need to wait until it gets real stack unwinding and
exception handling support.
All the other aspects looked fine, and we even designed a Go ABI under wasm
(pass g and SP on wasm stack and everything else on emulated Go stack) and
a way to modify the current MIPS backend to support wasm by emulating MIPS
registers as wasm local variables.
Perhaps GopherJS can support wasm easier.
|
From gopherjs/gopherjs#432:
|
@minux The lack of threads or async i/o seems to be a bigger problem than the ABI workarounds we'd have to do because of wasm quirks. |
@minux, @cherrymui minimizing the amount of duplicated efforts and impedance mismatch between various components would be great. |
I highly recommend this as a strategic feature. Consider that in just a few years web programmers will flock in hordes to pick their language of choice to be compiled into web assembly. The sooner we join the race the better. Mozilla is pushing Rust hard as the web assembly language of choice... |
I second what @RaananHadar said. It would be a pity if the spec didn't suit Go's needs, especially given how Go's runtime can be unique. EDIT: Apologies for the MeToo nature of this comment :) Thanks for the pointer Brad. |
Reminder: https://golang.org/wiki/NoMeToo |
The WebAssembly stack machine context consists of linear memory and an operation stack. IIUC, saving the VM context can possibly be done by saving the:
To a global list of saved contexts in the VM context struct, if any. Thus, a setjump should simply restore these values, and continue with the interpreter loop as usual (This is similar to how the emacs bytecode VM implements signals: https://github.com/emacs-mirror/emacs/blob/master/src/bytecode.c#L785). An exception system can be implemented on the top of this, though I'm not sure how performant would this be. Further, the webassembly spec mentions that the stack height at any moment in the bytecode is statically known, making all stack operations equivalent to operations on registers unique to each position on the stack. This paper describes a way to achieve such a stack -> register mapping for converting stack machine code to native code, allowing us to use setjmp/longjmp as usual. Edit: What about using |
Yes, basically the discussion with @cherrymui resulted in similar findings.
The initial design with @cherrymui is this:
(this stage focus on getting $GOROOT/test/sieve.go to work, no async IO is
considered.)
we reuse the MIPS port, mapping the 31 MIPS registers as WASM local
variables and only use WASM stack
for intermediate results. We can't use WASM's function call mechanism for
most Go functions because
the lack of stack unwinding support.
change the mips objlink (cmd/internal/obj) to emulate each MIPS instruction
with respective WASM instructions.
This makes setjmp/longjmp (aka runtime.gogo) implementation trivial and
reuses a lot of existing effort.
Go already needs to implement its own stack, separate of the WASM stack,
because Go needs copyable
stack, stack pointer maps and stack unwinding support, which are not
available from WASM.
(This strategy also aligns with the LLVM port, we can't use LLVM stack for
almost the same reasons
(unless we add a custom backend pass to LLVM proper to encode stack pointer
maps).)
We will probably need to use a big switch to thread indirect jumps? This is
similar to NestedVM's approach.
http://nestedvm.ibex.org/
If we decide to implement a native WASM backend, then we can do this:
the Go ABI is:
all parameters (including results) on (emulated) Go stack,
at function entry, the following are on the WASM stack:
emulated SP, g.
The discussion happened more than one month ago, and I probably forgot some
details at this point.
|
IIUC, you can completely discard the WASM stack (according to the spec). An extendable and copyable go stack is still something that needs to be investigated. |
Yes, the initial design I mentioned only uses the WASM stack for
intermediates used in computation. All data is either on Go heap (linear
memory) or pseudo registers in WASM local variables.
I don't expect WASM spec to incorporate moving/segmented and copying stack.
It's rarely used by mainstream languages targeted by WASM.
|
if somebody will decide to implement wasm support I can offer my time for non-global tasks |
@SerkanSipahi, nobody is working on this. This bug is marked LongTerm. If something starts happening, you'll see updates here. |
A good roadmap ? We have DELVE and GDLV for debugging golang with a GUI. It works well too on all Desktops and Perf is excellent. Now, GDLV is based on NUCULAR which is shiny with some nice abstractions. SO i was thinking this would be a good basis to do what has already been done here: There are 5 WASM go libaries now too: |
NaCl is shut down - https://blog.chromium.org/2017/05/goodbye-pnacl-hello-webassembly.html |
I believe that NaCl is used by various parts of the Go ecosystem. That is, it's not used only by Chrome. And in any case that blog announcement is about PNaCl, which, although it provides functionality similar to NaCl, is actually a completely different product based on a different technology. So removing NaCl support from Go is premature at present. Any in any case whether or not we remove NaCl from Go has nothing to do with whether we add support for Web Assembly. |
I would say that PNaCl is just an extension over NaCl to provide platform independent code https://developer.chrome.com/native-client/nacl-and-pnacl I asked about NaCl deprecation here - https://groups.google.com/d/topic/native-client-discuss/wgN2ketXybQ/discussion If is possible to get list of those various parts of the Go ecosystem where NaCl is still used? |
You can say whatever you want, but it doesn't mean you are right. They are completely different ISAs, NaCL is just the target ISA (x86/arm) with some restrictions, while PNaCl is a completely different ISA for an abstract machine. Go has never supported PNaCL, and the Go NaCL port was never suitable for Chrome anyway. It had nothing to do with Chrome, it was not usable in the browser. Whether Chrome abandons NaCL or PNaCL has no relevance to Go whatsoever. Nada, nil, no relevance. How many more times this must be said? Of course, if NaCL is abandoned completely then Go will be forced at some point to abandon it too. WebAssembly support in Go has absolutely nothing to do with NaCL. Go might or might not get WebAssembly support. If, or when it might get such support has no relevance to the state of the NaCL port. |
Here is a very important part of the ecosystem where we use nacl: https://play.golang.org/p/MfJIq8wb5- (that runs server-side, not nacl-in-a-browser) |
And who will support sandbox loader and toolchain then? It is imported from Chrome project, which switched efforts to WebAssembly. Wouldn't it be wise to follow and see if Go playground can already be ported from NaCl sandbox to WebAssembly sandbox? It can also be run server-side. |
I think everybody is in favor of supporting WebAssembly. The time to discuss moving away from NaCl is after WebAssembly is fully working. There's no point to discussing it before then. |
@ianlancetaylor, can you clarify "after WebAssembly is fully working"? At a glance, it appears webassembly.org says "the initial version of WebAssembly has reached cross-browser consensus" and wasm is available in current or future browser versions from all browser vendors. |
@vine77 I mean after WebAssembly is fully working for Go programs, at least as well as NaCl works today. |
This commit adds support for JavaScript callbacks back into WebAssembly. This is experimental API, just like the rest of the syscall/js package. The time package now also uses this mechanism to properly support timers without resorting to a busy loop. JavaScript code can call into the same entry point multiple times. The new RUN register is used to keep track of the program's run state. Possible values are: starting, running, paused and exited. If no goroutine is ready any more, the scheduler can put the program into the "paused" state and the WebAssembly code will stop running. When a callback occurs, the JavaScript code puts the callback data into a queue and then calls into WebAssembly to allow the Go code to continue running. Updates #18892 Updates #25506 Change-Id: Ib8701cfa0536d10d69bd541c85b0e2a754eb54fb Reviewed-on: https://go-review.googlesource.com/114197 Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@neelance - Now that callbacks are in, I believe basic support is complete. Shall we close this bug or did you have something else in mind ? |
Yes, I think we can close this now. 🎉 |
Great work!!! @neelance |
This is awesome, great work @neelance! |
Change https://golang.org/cl/120057 mentions this issue: |
It's more common to specify GOOS/GOARCH values in that order, rather than the inverse. Fix the order. Updates #18892. Change-Id: I8551508599e019f6617dc007397b562c9926418d Reviewed-on: https://go-review.googlesource.com/120057 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Change https://golang.org/cl/120575 mentions this issue: |
After the std tests, most of the rest of the tests aren't applicable to js/wasm. (anything with -cpu=>1, cgo, etc) Skip them all for now. We can incrementally re-enable them over time as the js/wasm port is fleshed out. But let's get the builder column black again so we can enable trybots and keep it black. Updates #26014 Updates #26015 Updates #18892 Change-Id: I8992ed3888f598fa42273ce8646a32d62ce45b1d Reviewed-on: https://go-review.googlesource.com/120575 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Andrew Bonventre <andybons@golang.org>
Is it appropriate to open an issue on reducing the file size (if that is even possible)? Or is that being tracked elsewhere? |
Change https://golang.org/cl/120958 mentions this issue: |
Does the golang compiler have built-in control flow integrity(CFI)? I recently skimmed through the following to do with vulnerabilities in WASM prevented with CFI built-into the clang compiler: |
Just skimmed it, but it seems to me as if the post says "WebAssembly is not a high level language such as JavaScript, but a low level language, so certain classes of bugs may apply if the source language (C or Go) allows them." No surprise there. This means that if Go would have such issues, they would also apply to other architectures, not only WebAssembly. |
WebAssembly is mostly about defending the browser from nefarious WebAssembly code. It is not so much about providing guarantees within the WebAsssembly instance (although there is some of that). As @neelance said, it is up to the LanguageX->WebAssembly compilers to provide any required safety guarantees. |
@randall77 How does this affect plain |
The risk is the same regardless of architecture (with the exception that WebAssembly doesn't have threads yet, so it's actually zero for WebAssembly for the moment). Data races can be used to simulate |
Okay, so if your Go code has no data races, then it should be fine. Also, when running untrusted code with WebAssembly you can make sure that it can not escape the WebAssembly environment, even though it is able to have data races or simply use |
The more I examine this javascript usage from within golang, the more I perceive as an infection that will degrade the quality and the long-term maintenance of the golang code. Let me explain. Here is an example of a wonderful wasm golang app that does some impressive eye candy magic. https://github.com/stdiopt/gowasm-experiments/blob/master/bouncy/main.go The results are impressive. Delving furthing into the code that actually makes it happen though was disappointing because it require that every time you want to call something from the javascript side, it requires you to describe the name of the javascript function or the javascript value as a string AT EVERY TURN. As a result, there is no way for the golang compiler to check javascript correctness at compile time. It's "fly by prayer" at runtime. I would prefer to see golang functions/variables/types everywhere for long-term maintenance otherwise it defeats the purpose of using golang for wasm in my humble opinion. BTW I detest javascript and always have. It's too freestyle. Why is it that such a language has persisted in the web browsers? The answer escapes me. Thank you for listening. |
I agree that calling JS using strings isn't the better experience. Maybe we could generate Go interfaces from web platform specification IDL's. The downside is how to keep up with the spec, because depending on the browser it will run, the API's isn't available, while on the other side, new spec keep coming all the time as the web platform evolves. |
@omac777 I agree with you. That's why I hope that there will be nice Go libraries around the JS low levels so most users will never have to touch |
@omac777 For GopherJS, many people use high-level bindings for various browser APIs rather than the low-level For reference, see https://github.com/gopherjs/gopherjs/wiki/Bindings, https://dmitri.shuralyov.com/talks/2016/Go-in-the-browser/Go-in-the-browser.slide#11 (and the following 4 slides), and dominikh/go-js-dom#57. |
Also we should consider there is a bunch of stuff on the webassembly roadmap: https://webassembly.org/docs/future-features/ that will improve the
Anyways, thanks @neelance et. al. for implementing the initial version. So awesome! 🥇 |
What if there was a Go implementation of the DOM? Documents and scripts could be written and executed in Go, making use of the type system. Then, code could be generated from the Go DOM. |
@fractalbach: If the WebAssembly's host binding is confirmed and implemented by the work group, you can actually do DOM manipulation through WebAssembly. Then it would be reasonable to have high level libraries to abstract DOM, Documents and scripts. But before that, it is not quite as appealing to do. |
Go WebAssembly: Binding structures to JS references https://medium.com/@nlepage/go-webassembly-binding-structures-to-js-references-4eddd6fd4d23 The approach is appealing. The usage is similar to json marshallling/unmarshalling within structs. That makes it an easily transferable skill. The one thing missing is how to apply the same approach to duck-typing? I would prefer not to have the function declarations within the structure, but outside of it standalone in the same manner as duck-typing. If the service exists, it can use it. That way it is easily modifiable without affecting the core struct holding the different desired non-function values. Duck-typing rocks! Thank again @neelance for all your work. It's greatly appreciated. |
Hello everyone, this is a high traffic thread with a lot of people subscribed. Having a general discussion like this is not fruitful to those just concerned about the original issue - which is to have WebAssembly support for Go. Please feel free to continue the discussion in appropriate forums - golang-nuts/golang-dev. Or if you have something specific in mind, please open a new issue. Thank you. |
WebAssembly ("wasm") is similar to Native Client, but different notably in that other browsers plan to implement it.
http://webassembly.org/
This has been asked about a few times, so this is a tracking bug for it.
Whether we get it via cmd/compile, gccgo, or llvm-go, we can post updates here.
The text was updated successfully, but these errors were encountered: