92 comments

[ 3.0 ms ] story [ 143 ms ] thread
Has anyone benchmarked 64bit memory on the current implementations? There's the potential for performance regressions there because they could exploit the larger address space of 64bit hosts to completely elide bounds checks when running 32bit WASM code, but that doesn't work if the WASM address space is also 64bit.
This looks like a great release! Lots of stuff people have wanted for a long time in here.
> Garbage collection. In addition to expanding the capabilities of raw linear memories, Wasm also adds support for a new (and separate) form of storage that is automatically managed by the Wasm runtime via a garbage collector. Staying true to the spirit of Wasm as a low-level language, Wasm GC is low-level as well: a compiler targeting Wasm can declare the memory layout of its runtime data structures in terms of struct and array types, plus unboxed tagged integers, whose allocation and lifetime is then handled by Wasm. But that’s it.

Wow!

It's very refreshing and good to see WASM is embracing GC in addition to non-GC support. This approach is similar to D language where both non-GC and GC are supported with fast compilation and execution.

By the way now you can generate WASM via Dlang compiler LDC [1].

[1] Generating WebAssembly with LDC:

https://wiki.dlang.org/Generating_WebAssembly_with_LDC

That sounds like WASM is going into the Java direction. Is that really a good thing?
Java approach: create the JVM to support one language, so it has rich high-level concepts that are unfortunately skewed toward certain assumptions about language design, and it can be reused only for other languages that are similar enough.

WASM approach: start very low-level so C is definitely supported. Thus everything is supported, although every language has to roll its own high-level constructs. But over time more patterns can be standardised so languages can be interoperable within a polyglot WASM app.

This seems less than ideal to me.

1. Different languages have totally different allocation requirements, and only the compiler knows what type of allocator works best (e.g. generational bump allocator for functional languages, classic malloc style allocator for C-style languages).

2. This perhaps makes wasm less suitable for usage on embedded targets.

The best argument I can make for this is that they're trying to emulate the way that libc is usually available and provides a default malloc() impl, but honestly that feels quite weak.

I'm not familiar with WASM. Can someone explain why this is a good thing? How does this work with languages that do not have a garbage collector, like Rust?
> GC and Exception handling

This was not necessary.. what a mistake, specially EH..

Does anyone know whether the exception handling implementation supports restartable exceptions like Common Lisp's and Scheme's?
No, that functionality would fall under the stack-switching proposal, which builds on the tags of Wasm exception handling.
Scheme doesn't have restarts as a core concept like Common Lisp, but it does have continuations. For the Scheme implementation I worked on [0], the exception system is built on top of the continuation system. In other words, Scheme exceptions are not Wasm exceptions. However, we did find a use for Wasm exceptions in the implementation of the runtime. We realized it would be useful to mark the entry point into Scheme with a Wasm 'try' block for re-entrancy reasons. Programs might call from Scheme to JS back to Scheme and on and on. When we suspend the current continuation we throw a Wasm exception and find the correct entry point for doing our stack tomfoolery, re-throwing until we find it. I don't know if my explanation makes any sense but that's how we're using Wasm exceptions.

[0] https://spritely.institute/hoot/

I'm definitely excited to see 64 bit as a default part of the spec. A lot of web apps have been heavily restricted by this, in particular any online video editors. We see a bunch of restrictions due to the 32 bit cap today here at Figma. One thing I'm curious though is whether mobile devices will keep their addressable per-tab memory cap the same. It's often OS defined rather than tied to the 32 bit space.
Webapps limited by 4GiB memory?

Sounds about right. Guess 512 GiB menory is the minimum to read email nowadays.

I guess I’m just a crusty ol’ greybeard C++ developer, but it seems like a video editor is out of place in a document browser. There’s a perfectly good native operating system that nobody uses any more.

If we think we need a more thoroughly virtualized machine than traditional operating system processes give us (which I think is obvious), then we should be honest and build a virtualization abstraction that is actually what we want, rather than converting a document reader into a video editor…

The browser has become the operating system for a while now because native OS things were too fragmented and too slow to keep pace with what people wanted.
I feel way safer using apps inside web browser than installing / executing them directly on my PC.
I'm a fan of the browser becoming a sandbox for much more than "documents". It has the most developed, flexible, and powerful UI system ever, it established numerous standards that pervade modern software development, and it's already available as one of the most cross-platform standard utilities.

If the browser sandbox is a reliable cross-platform sandbox, the potential to develop and distribute software is huge. Progressive Web Apps are awesome because you can visit the website and use it normally, and then click a button to "install" the website to your device. If designed correctly, the website can work offline. By doing this, you get free distribution, automatic updates, no app stores, an excellent platform to develop an app on top of (the browser), etc.

I think PWAs are the future, but the web platform still has some ways to go. There are numerous amazing examples of what you can accomplish with PWAs in their current state, though.

I'm excited by the GC, ref types and JS string API! Been a while J, how are you going?
Is there a technical reason for the web limit to be 16 GB specifically? Or is it just a round number picked so that the limit could be standardized? Also, has the limit on JS heap size (and ArrayBuffer size) also been relaxed to 16 GB or is it still lower?
On gc:

> Wasm GC is low-level as well: a compiler targeting Wasm can declare the memory layout of its runtime data structures in terms of struct and array types, plus unboxed tagged integers, whose allocation and lifetime is then handled by Wasm.

There's already a lot misunderstandings about wasm, and I fear that people will just go "It supports GC, so we can just export python/java/c#/go etc."

This is not a silver bullet. Cpp, or rust are probably still going to be the way to go.

Relying on the GC features of WASM will require writing code centered around the abstractions for the compiler that generates WASM.

The two main benefits of wasm GC are that compilers can avoid implementing or compiling a full GC but also that the guest and the host can share structured data types
Does WASM still have 64 KiB pages? I get why for desktops, but there are use-cases for running WASM on microcontrollers where that's either inconvenient or outright impossible.

The one in particular I have in mind would be to put WASM on graphical calculators, in order to have a more secure alternative to the ASM programs (it's possible nowadays to write in higher-level languages, but the term stuck) that could work across manufacturers. Mid-range has RAM on the order of 256 KiB, but a 32-bit core clocked at more than 200 MHz, so there's plenty of CPU throughput but not a lot of memory to work with.

Sadly, the closest thing there is for that is MicroPython. It's good for what it does, but its performance and capabilities are nowhere near native.

Since it hasn't been mentioned here yet: I wonder if the multiple-memories feature will somehow allow to avoid the extra copy that's currently needed when mapping a WebGPU resource. This mapping is available in a separate ArrayBuffer object which isn't accessible from WASM without calling into JS and then copying from the ArrayBuffer into the WASM heap and back.

Multiple WASM memories and Clang's/LLVM's address space feature sound like they should be able to solve that problem, but I'm not sure if it is as trivial as it sounds...

Still no mention of DOM.

<sets alarm for three years from now>

See you all for WASM 4.0.

Wasm doesn't specify any I/O facilities at all. DOM is no different. There's a strict host/guest boundary and anything interacting with the outside world enters Wasm through an import granted by the host. On the web, the host is the JS runtime.
If you give WASM access to everything, you've defeated the main reason it exists. Ambient authority is the reason we need WASM in the first place.
Wasm 3.0, with its GC and exception support, contains everything you need. The rest is up to the source language to deal with. For example, in Scala.js [1], which is mentioned in the article, you can use the full extent of JavaScript interop to call DOM methods right from inside your Scala code. The compiler does the rest, transparently bridging what needs to be.

[1] https://www.scala-js.org/doc/project/webassembly.html

End-users DON'T want developers' apps running in the browser to have freedom to access everything on the end-users' machines. Not having direct dom access is a security feature, as much as an MMU is. Please don't ask for this.
64-bit addr space and deterministic profiles ftw!

Really nice new set of features.

Oh no, right after I started writing a binary decoder for 2.0. Does anybody know how much this changes things as far as a decoder is concerned?
There's a joke in Brazil saying "Brazil is the country of the future and will always be that. It will never be the country of the present".

WASM is and will always be the greatest technology of the future. It will never be the greatest technology of the present.

This looks like a huge release for C# and Java I guess. Half of the features are useful elements they no longer have to polyfill.
I don't think the GC in this version has the features required to enable a C# runtime on top of it yet: https://github.com/WebAssembly/gc/issues/77

I wonder what language this GC can actually be used for at this stage?

I'm not familiar with all the implementation details of objects in C#, but the list of issues mixes runtime implementation details (object layouts) that should be fairly low effort to work around with actual language/runtime features (references, finalization).

In general though most regular C# code written today _doesn't directly_ use many of the features mentioned apart from references. Libraries and bindings however do so a lot since f.ex. p/invoke isn't half as braindead as JNI was, but targeting the web should really not bring along all these libraries anyhow.

So, making a MSIL runtime that handles most common C# code would map pretty much 1-1 with Wasm-GC, some features like ref's might need some extra shims to emulate behaviour (or compiler specializations to avoid too bad performance penalties by extra object creation).

Regardless of what penalties,etc goes in, the generated code should be able to be far smaller and far less costly compared to the situation today since they won't have to ship both their own GC and implement everything around that.

I'm a simple man who has simple needs. I want a better and faster way to pass Go structs in and out of the runtime that doesn't mean I have to do a sword dance on a parquet floor wearing thick knit wool socks and use some fragile grafted on solution.

If there can be a solution that works for more languages: great. I mostly want this for Go. If it means there will be some _reasonable_ limitations, that's also fine.

That would be more of a library than a WASM spec thing, no? I wrote a code generator that does this well for some internal use-cases.
You're doing native code, this the solution is the same as in native code: your languages agree on a representation, normally C's, or you serialize and deserialize. Mixing language runtimes is just not a nice situation to deal with without the languages having first class support for it, and it should be obvious why.
I am not sure what you actually want but it sounds like something where the component model (the backbone of WASI) might help.

It defines a framework to allow modules to communicate with structured data types by allowing each module to decide how to map it to and from its linear memory (and in future the runtime GC heap)

In your case you could be able to define WIT interfaces for your go types and have your compiler of choice use it to generate all the relevant glue code

This is the truth, and it's not really much better in non-GCed languages either. (In reality my impression is the GCed wasm side runtimes are even worse).

Some of the least fun JavaScript I have ever written involved manually cleaning up pointers that in C++ would be caught by destructors triggering when the variable falls out of scope. It was enough that my recollections of JNI were more tolerable. (Including for go, on Android, curiously).

Then once you get through it you discover there is some serious per-call overhead, so those structs start growing and growing to avoid as many calls as possible.

I too want wasm to be decent, but to date it is just annoying.

This is exactly why I say WebGL/WebGPU are much better for perfomance code on the browser than dealing with WebAssembly tooling.
One bright point here is that the WASM changes may force v8 to improve its IPC by having a feature that Bun gets from JSC, which is passing strings across isolate boundaries.

IPC overhead is so bad in NodeJS that most people don’t talk about it because the workarounds are just impossibly high maintenance. We reach straight for RPC instead, and downplay the stupidity of the entire situation. Kind of reminiscent of the Ruby community, which is perhaps not surprising given the pedigree of so many important node modules (written by ex Rails devs).

(comment deleted)
steve job's ghost will prevent wasm adoption.
I haven't really been following WASM development in the last year and didn't realize that WASM had moved to a versioned release model. I've been aware of the various features in development[1] and had thought many of the newer features were going to remain optional but I guess now that implementations are expected to support all the features to be able to claim compatibility with e.g. "WASM 3.0"?

It'll be interesting to see what the second non-browser-based WASM runtime to fully support 3.0 will be (I'm guessing wasmtime will be first; I'm not counting Deno since it builds on v8). Garbage collection seems like a pretty tricky feature in particular.

Does anyone know how this 3.0 release fits into the previously announced "evergreen" release model?[2]

> With the advent of 2.0, the Working Group is switching to a so-called “evergreen” model for future releases. That means that the Candidate Recommendation will be updated in place when we create new versions of the language, without ever technically moving it to the final Recommendation state. For all intents and purposes, the latest Candidate Recommendation Draft[3] is considered to be the current standard, representing the consensus of the Community Group and Working Group.

[1] https://webassembly.org/features/

[2] https://webassembly.org/news/2025-03-20-wasm-2.0/

[3] https://www.w3.org/TR/wasm-core-2/

Wizard supports all of Wasm 3.0, but as a research tool, it only has an interpreter and baseline compiler tier (no opt compiler), so it doesn't run as fast as, say, V8 or wasmtime.
I suspect the versioning is going to replicate the JavaScript version system where versions are just sets of features that a runtime can support or not, I am not sure how feature discovery works in wasm though
> It'll be interesting to see what the second non-browser-based WASM runtime to fully support 3.0 will be (I'm guessing wasmtime will be first; ...)

Wasmtime already supports every major feature in the Wasm 3.0 release, I believe. Of the big ones: garbage collection was implemented by my colleague Nick Fitzgerald a few years ago; tail calls by Jamey Sharp and Trevor Elliott last year (with full generality, any signature to any signature, no trampolines required!); and I built our exceptions support which merged last month and is about to go out in Wasmtime 37 in 3 days.

The "3.0" release of the Wasm spec is meant to show progress and provide a shorthand for a level of features, I think, but the individual proposals have been in progress for a long time so all the engine maintainers have known about them, given their feedback, and built their implementations for the most part already.

(Obligatory: I'm a core maintainer of Wasmtime and its compiler Cranelift)

Having wasm 3.0 and a project named wasm3 which doesn't seem to support wasm 3.0 is sure going to get confusing!