crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.45k stars 1.62k forks source link

Plans about WebAssembly #829

Closed sergei-kucher closed 2 years ago

sergei-kucher commented 9 years ago

Do you have any plans about WebAssembly support?

Svenskunganka commented 6 years ago

A design document from the Go core developers are available here: https://docs.google.com/document/d/131vjr4DH6JFnb-blm_uRdaC0_Nv3OUwjEY5qVCxCup4/edit

Looks like their implementation is under review and possibly being merged soon: https://go-review.googlesource.com/c/go/+/102835

Posting it in case anyone wants to take a bite at this in the future. It covers some of the questions already asked here.

RX14 commented 6 years ago

And as we can see from that document, go's port to wasm is a bunch of hacks to work around missing features in wasm. If someone wants to make a PR hacking those in, go for it, but until then I'll be waiting for proper GC and coroutine support.

osarrouy commented 6 years ago

Hi everyone,

I'm a big fan of crystal and also happen to be a blockchain developer so i'd just like to know if there is any news about this issue and if i could help in any way ... ?

Thanks!

rdp commented 6 years ago

I guess you could target "javascript" (not wasm) via emscriptem and go single threaded. Though that's not what the title of this issue is about :) I assume that's how mruby in the browser works [?] http://qiezi.me/projects/mruby-web-irb/mruby.html (just uses the javascript built-in GC I presume?). Watch also https://github.com/WebAssembly/gc/ (WIP gc proposal). Other options: Add a "new gc" option ("reference counting with cycle checking" https://github.com/JetBrains/kotlin-native/issues/1170#issuecomment-353328876 or the "double copy stack to the heap" trick RX14 mentions). Or manage stack manually if you want to keep fibers. Doesn't sound trivial...

sam0x17 commented 6 years ago

This provides some very useful and up-to-date high-level information on the web assembly feature set and roadmap:

https://hacks.mozilla.org/2018/10/webassemblys-post-mvp-future/

@straight-shoota @RX14

bew commented 6 years ago

Interesting read about threading implementation for wasm: https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html There might be some useful things for us ;)

parruda commented 5 years ago

I just stumbled upon this issue. I’ve been thinking about adding Opal support to FaaStRuby, and if we could compile Crystal to Wasm... Full stack Crystal development in a serverless platform. Think about the possibilities!

I wish I could contribute to this effort, but I don’t know enough about Wasm or LLVM. But you guys can be sure I would contribute to make it popular by pushing the support to the platform as soon as you guys release it!

Thanks for the hard work.

sam0x17 commented 5 years ago

Yeah, I imagine this is going to be one of the first big pushes after 1.0, and by then other languages will have figured out some of the do's and dont's of web assembly support, so it will be that much easier

catmando commented 5 years ago

FYI: I just put a discussion topic around this general topic: https://forum.crystal-lang.org/t/crystal-js-transpiler/903

theganyo commented 5 years ago

WASM will soon be very important on the server as Envoy is testing support for dynamic filters via WASM and Istio will be fully supporting that soon. That should surely add some heat to this discussion.

jan-zajic commented 5 years ago

LLVM WebAssembly target is production ready since LLVM 8.0.0. See http://releases.llvm.org/8.0.0/docs/ReleaseNotes.html#changes-to-the-webassembly-target .

jwoertink commented 4 years ago

Just keeping the talk going, this article was just released https://www.w3.org/blog/news/archives/8123. I think why this is important is because just like HTML, CSS, and JavaScript, WASM will be a web standard with the W3C backing it. I know with all the stuff this language still needs, this may be a little lower priority, but I think getting a "rough" start merged, that would allow us to really hash out how things should work. We could start with a preview or something like how the MT stuff is going, or just get some initial things like the windows support is doing.

Edit: Here's a spec link https://webassembly.github.io/spec/core/index.html

RX14 commented 4 years ago

A "Hello world" for this feature would be 90% of the work :)

Keep your expectations low, this is about as hard as asking for the compiler to compile to JS directly.

richardanaya commented 4 years ago

Any updates on this? A lot of these comments sound like people are hoping for too much to be done at once. Just figure out how to talk with imported and exported functions, don't worry about supporting a standard library, or figuring out magical ways to talk to the dom (libraries can figure this out).

jwoertink commented 4 years ago

I was able to get a "hello" world from crystal done. Though, not in the way you'd want it. I basically just hand wrote bytes 😂 I did come across this gist showing how to compile LLVM with wasm support. I tried to see if I could get crystal compiled this way, but my eyes glossed over. It's a bit beyond my knowledge. Maybe someone else here can point out some stuff? My assumption is that if you can compile crystal with the latest LLVM, and add the right flags, maybe it'll just work™

jwoertink commented 4 years ago

Here's what I did https://gist.github.com/jwoertink/b8fb8430ed819dd4041a56ff6ed3ef64 if anyone is interested in expanding on that, or whatever.

epipheus commented 3 years ago

@jwaldrip why?

Well heres one example, Crystal should be the language of choice for blockchain but isn't. The fastest way to build secure blockchain base anything right now is via Substrate/Polkadot and pretty much any language that can compile to wasm can easily leverage Substrate/Polkadot to get started. Among many things it's Wasm that allows Polkadot to have forkless upgrades -- that's significant. Instead of using Crystal, folks are just deciding to pick up Rust. Crystal would be far better.

That's one example.

pdpark commented 3 years ago

WASM will soon be very important on the server as Envoy is testing support for dynamic filters via WASM and Istio will be fully supporting that soon. That should surely add some heat to this discussion.

Another example of a great use-case - transforming data on streaming platforms: https://thenewstack.io/webassembly-brings-easy-inline-data-transformations-to-redpanda-kafka-streaming-platform/

<< Adding functionality to an existing system is exactly the kind of place where WebAssembly is going to be useful, the Cloud Native Computing Foundation‘s Chief Technology Officer Chris Aniszczyk agreed. “I think we’ll see any project that has an extension-type mechanism will probably take advantage of WASM to go about doing that.” >>

lbguilherme commented 3 years ago

Here is a summary of what needs to happen for a WebAssembly target:

There are some WebAssembly proposals that would help a lot here:

What Go managed to do is just impressive, but it has quite a few performance issues. I don't think it is viable for us to go the same route just yet.

jwoertink commented 3 years ago

Wow! That's some great information @lbguilherme. Thanks for putting that together. It's much easier to see where we're at and where we need to get to.

straight-shoota commented 3 years ago

There are plans for including a GC into WebAssembly. It would probably be better to use such a native GC instead of hacking bdwgc into WASM.

RX14 commented 3 years ago

There are plans for including a GC into WebAssembly. It would probably be better to use such a native GC instead of hacking bdwgc into WASM.

Whichever of stack walking or GC is available first would be good targets.

There are some WebAssembly proposals that would help a lot here

The "arbitrary labels and gotos" isn't important here, since LLVM takes care of relooping. Stack walking and stack switching are important to support fibers, but it'd be neat to support basic crystal without the stdlib before then.

straight-shoota commented 3 years ago

Basic basic Crystal (no stdlib, no exceptions) should already be feasible, right?

lbguilherme commented 3 years ago

Basic Crystal is indeed feasible.

https://github.com/crystal-lang/crystal/pull/10870

lbguilherme commented 3 years ago

After some research, I concluded there are viable ways to implement the missing features with the current WebAssembly spec thanks to Binaryen. In particular, it has a pass called "Asyncify" that will take WebAssembly as input and apply a series of static transformations to it, generating WebAssembly out. The transformations modify the control flow of each function so that they can unwind the stack by pushing every local to a heap array, together with some information about where exactly execution was. And it adds a "rewind" strategy as well, consuming data from this heap array and refilling the stack to go back to the same place as before. This method is similar to what Go implemented for itself.

Sources with a documentation comment: https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp A nice blog post about it: https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html

maxfierke commented 3 years ago

After some research, I concluded there are viable ways to implement the missing features with the current WebAssembly spec thanks to Binaryen. In particular, it has a pass called "Asyncify" that will take WebAssembly as input and apply a series of static transformations to it, generating WebAssembly out. The transformations modify the control flow of each function so that they can unwind the stack by pushing every local to a heap array, together with some information about where exactly execution was. And it adds a "rewind" strategy as well, consuming data from this heap array and refilling the stack to go back to the same place as before. This method is similar to what Go implemented for itself.

Sources with a documentation comment: https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp A nice blog post about it: https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html

* Fibers: This is exactly what we need for stack switching. Unwind the current stack and then rewind a previous stack, with each paused fiber keeping its own stack saved for later. This has a performance penalty since the switch isn't constant time like every other platform, instead, it depends on the stack size (that should be small anyway).

* GC: We can use bdwgc's `GC_set_on_collection_event` to notify us before each GC collect (`GC_EVENT_MARK_START`..`GC_EVENT_MARK_END`). We can unwind the current stack and let the GC run without anything at all on the stack currently. After it finishes marking we can rewind the same Fiber back in place.

* Stack trace (for exceptions): We can unwind the current stack and then rewind it again. Then read and interpret data from the heap array generated in this process. The exact format needs to be well understood for that, but it should provide enough information. Debug information about function names, files, and lines can be included as auxiliary data later on.

* Exceptions: Maybe we can unwind until a suitable begin..rescue..ensure..end is found? This part is still unclear.

I have a few WIP branches in various stages from my previous WASM porting attempts that may be of interest:

Most recent attempt: https://github.com/maxfierke/crystal/commits/mf-spike_wasm_take_two w/ full wasi-libc bindings for further diving, if anyone is interested.

Various notes here: https://github.com/maxfierke/crystal-wasm-tools

These have drifted from upstream a bit, but I think there might be some things still useful there for your work @lbguilherme. If #10870 gets merged, I would be happy to jump back in on WASM support given the good basis (much more organized than my spike branches 😅 )

pannous commented 2 years ago

Looks like https://github.com/crystal-lang/crystal/pull/10870 was merged, maybe WASM integration can proceed?

lbguilherme commented 2 years ago

I believe this issue is superseded by #12002. Keep in mind that progress on this will most likely move slowly until there is more community adoption/interest.