Hacker News new | ask | show | jobs
GC and Exceptions in Wasmtime (bytecodealliance.org)
155 points by phickey 11 days ago
6 comments

It seems like a bit of a shame that wasm got support for exceptions but doesn't support effects which are a generalisation of the same concept. https://wasmfx.dev/

I'm guessing this may be because exceptions exclusively require stack unwinding where as effects require full stack switching.

Seems like there is still progress on that though which gives hope https://github.com/WebAssembly/stack-switching/blob/main/pro...

Thanks for that link! There goes my Saturday morning.

After a bunch of middle clicking I landed here [0]. So if I understand correctly, the current stack switching proposal depended on exception handling to be implemented first for resume.throw, so that bit was blocked until now.

But it's also further along than you might assume [1], i.e. you can already invoke Wasmtime with `-W stack-switching` and hit the boundaries where the experimental implementation breaks.

Sadly though, like many ambitious Wasm things that don't have revenue directly attached to them, it now seems partly a case of finding someone willing to sponsor or finish the remaining work [2].

I also found the list of open stack-switching issues[3] useful.

(also, minor nit - Wasm != Wasmtime)

[0]: https://github.com/bytecodealliance/wasmtime/issues/10248

[1]: https://github.com/bytecodealliance/wasmtime/issues/12941

[2]: https://github.com/bytecodealliance/wasmtime/issues/12941#is...

[3]: https://github.com/bytecodealliance/wasmtime/issues?q=state%...

Looking at the link, it was quite an eye-opener moment (atleast for me) to see so many language-differentiating features - exceptions, async/await, continuations, generators - can all just be abstracted into one concept called "typed continuations". I'm still wrapping my head around this.

On one hand, I'd assume a "focused" feature, like exceptions, would always be easier to fine-tune and optimize the language, runtime and workflow – rather than generalizing it.

But at the same time, the prospect of saying all those are just special forms of a stacked "yield" (just for my mental model) is quite tantalizing.

PL theory seems to be in an infinite loop between arbitrary control flow like call/cc and then realizing it's hard to reason about and restricting it.

I do wish we could land on a standard model for implementing non local control flow. Like growable stacks.

I was never a huge fan of exceptions and their "come from" / "spooky behaviour at a distance" semantics, and now I see a group of other language features I never thought highly of all belong to a group of implementation / semantically similar behaviour.

"He has all the virtues I dislike and none of the vices I admire." -- Churchill

You might enjoy digging into the world of effect handlers: it's a very neat model for expressing these features and boils down to continuations in the implementation.
> Seems like there is still progress

Oh I already know that about WASM now. All is in progress ... perpetual progress.

I'll look again in the next decade.

I would suggest you look at it a little more often than that - to improve the quality of discussion here, if for nothing else.
Just checked and out of the 3 major non-JS GC languages, Go and .NET aren't planning to support WASM GC due to non-matching semantics. There's an implementation for Java - TeaVM, which is an AOT Java compiler, that does have production grade support, but isn't aiming for full Java compatibility (not sure what this means in practical terms).

Native interop with JS objects on the JS GC heap isn't supported as well.

Links to discussions about why WASM GC in its current state is not suitable for .NET: https://github.com/WebAssembly/gc/issues/77

What should be improved: https://github.com/dotnet/runtime/issues/94420

I'm not familiar with the current spec and those posts are from 6/3 years ago, respectively. Do you happen to know if anything has changed since?
> Native interop with JS objects on the JS GC heap isn't supported as well.

Isn't that what the i31 type is for, that extra bit is a tag for...something, native GC'd object perhaps? Not so clear on that myself as Java's object model (minus synchronized) slots in perfectly so my Java 1.0 -> wasm compiler doesn't need it but that's my limited understanding of what it's for.

I'm not sure what they mean by "native" here but (ref extern) is for host references, JS or otherwise. The i31 type is for "immediate" values, things that can fit in 31 bits and thus don't need to be allocated on the heap.
This is another good example that not all GCs are born alike, even though its is common to place them on the same basket.

WASM GC is a MVP, only usable by languages whose GC requirements overlap with JavaScript's GC.

Java has it easier than either Go or C#, because the Java and JVM specification is actually silent on how GC should be implemented, hence why there are so many implementations to chose from across JVMs.

Outside the browser there is hardly any value, just use JVM or CLR directly.

Wait, what does this mean?

> We reuse WebAssembly linear memories under the covers to implement and sandbox the GC heap. A reference to a GC object is not a native pointer, it is a 32-bit index into the GC heap’s underlying linear memory [..] As far as being fast goes, it lets us use virtual-memory guard pages to elide explicit bounds checks, just like we do for linear memories

Array loads and stores still need an explicit bounds check, don't they? And struct loads and stores don't have one anyhow. Are there other bounds checks that Wasmtime is removing? I can't figure out what they mean here.

When WASM people say "linear memory", they mean the whole address space that the guest program uses resides contiguously in a relatively small chunk of the 64-bit address space. In typical native programs, each heap allocation gets an essentially-random 64-bit address, and the can spread over a much larger chunk of the address space, with no guarantees on where a pointer can point.

With the 4 GiB linear memory trick, WASM's 32-bit pointers can't point outside of the range of virtual memory they allocate for the guest, so from the point of view of host, the guest is unable to have an out-of-bounds reference.

The program running inside the WASM virtual machine can still corrupt its internal state, but that doesn't matter for the WASM engine's security model: the program can be assumed to be directly hostile.

They're saying they used a similar design for WasmGC -- concretely, they're 32-bit indexes to a second span of virtual memory, but opaque and with more rules about how they can be used. They're unforgeable by design, but even if you find a bug in the WASM engine, it's still only a 32-bit index.

The quote extends that 4 GiB thinking to the GC design: Even with a bug in the WASM engine, every index is "safe" to access at any time, eliding bounds checks (the explosion is instant, predictable, and contained).

Does it support interior pointers?
No.
I'm personally excited for a better thread story (not web-workers) and JIT
WASM will be ready when GNU Hurd succeeds in running the desktop linux of the year. Already 10 years since WASM ... HTML, CSS and JavaScript all had a huge influence. WAS simply has not done so yet.
Ready for what?

WASM is already running in production at a whole bunch of financial services orgs and government infra.

The thing is, it's not running anywhere near HTML, CSS or JavaScript. It's running serverside, mostly on Wasmtime - which, as it happens, is what this post is all about.

> it's not running anywhere near HTML, CSS or JavaScript

There’s plenty of usage in the browser environment as well, plenty of client-side SDKs for things like e.g. video editing, barcode scanning, etc. use it.

why.... why would financial services orgs and government infra run anything on wasm serverside?
It's lightweight, capability-secured, services start up way faster, smaller overhead than VMs, better isolation than containers, faster replication, etc.

The original Wasmtime 1.0 blog post explains it all really well: https://bytecodealliance.org/articles/wasmtime-1-0-fast-safe...

I'm not sure why people are claiming wasm isn't ready. It's just a compiler target like asm.js was. And that's been in use pretty much from the start when they got Unreal Engine, Unity, ffmpeg ported to it. Personally I've run Python + Sympy, Xcas/Giac and Maxima in the browser through this amazing tech.
Yeah, WASM has been a disappointment, and I guess there's a good reason for that. If WASM would've worked as advertised, allowing fully fledged apps to run easily and natively in the browser with no fuss and 90% native perf, then basically all app stores would've been dead.

Native Client, which ran native x86 (but statically verified) code in the browser, basically fit all the criteria, except it wasn't platform agnostic. I'm not married to their approach, but I refuse to believe that this can't be done in a safe and peformant manner.

I guess WASM turned out to be a sandbagging rather than sandboxing technology.

But I eagearly await the arrival of concern trolls who can explain why WASM is slower than JS, and why native threading support is impossible to do securely without imposing limitations, that made sites like itch turn it off, so it might as well not exist.

There's a big gap between WASM has issues/limitations, and WASM "might as well not exist." NaCL was also Chrome-only IIRC, whereas WASM is a successful web standard (no small feat).
NaCL was further along in every meaningful dimension (the ability to run native software at native speeds) after a year or two of development, than WASM is today after a decade (and I think this will be true a decade from now).

So the upside of WASM according to you, is that it got greenlit by the standards committee chaired by companies whose business model would've been hurt the most by a competent in-browser sandbox.

For example, the Epic-Apple Fortnite battle couldn't even have happened. Epic would've shipped it on NaCL and users would've been just as happy, and Apple (or Google) would've had no way of enforcing their sandox.

Whew, thankfully we've been saved from that terrible fate of getting to publish and enjoy software without gatekeepers and appstores.

At least I hope you have something to gain from your opinion, as the rest of us certainly lost out.

It seems like you know quite a bit of the history here. Were you involved in some way? If so, I'm curious to know why you think NaCL did not achieve broad adoption? And what's stopping the world from catching up to your line of thinking and adopting a NaCL successor?
> Were you involved in some way?

Only as a developer using the technology, as part of a failed commercial venture.

> If so, I'm curious to know why you think NaCL did not achieve broad adoption?

NaCl had 2 limitations compared to WASM, the first one was a design philosophy difference:

Unlike WASM, it was designed to maximize compatibility with native code, so it had no ability to coexist in the same process with JS/DOM like WASM does. You had to put the code in an iframe, and talk to it via postMessage. WASM promised to be a better design, but a decade on, we can see it's missing most of those promised features, or said features are half-baked, and it has turned into one of the biggest NIH quests in modern computer science.

The second issue was that it worked through Chrome's plugin API, which has since been deprecated. You could sit down and standardize an API that's not chrome specific. The biggest piece of API surface the browser has is WebGL, and they essentially exposed OpenGL ES to the browser, which is identical to what PPAPI did.

Some APIs were much better, like audio just gave you a buffer to write into, compared to WebAudio, which aims to implement the whole processing pipeline via stringing together JS objects, and everybody seems to hate it.

> And what's stopping the world from catching up to your line of thinking and adopting a NaCL successor?

Theoretically nothing, but you'd have to fork Chrome, do the changes yourself, develop a spec and tooling and THEN ask browser vendors to standardize on your changes. If there was some soul who would undertake this task (maybe feasible with AI for a non-huge team?), combined with a strong awareness campaign to get committees to consider adoption. So it's a tall order in reality.

Surely PNaCl is the one you need, because portability.
Portability isn't worth as much as it was advertised. There are a grand total of 2 relevant CPU architectures for consumers, ARM64 and x86_64. Shipping 2 binaries is just running the compiler twice.

On the client side, there's just a verifier, and then the runtime basically consists of branching to the first instruction and having at it. Near-native performance and instant startup, you can't do better than that.

PNaCL was proto-WebAssembly and suffering from the same issues. They actually shipped LLVM bytecode, and you had to compile the executable locally with the whole toolchain, leading to quite bad startup performance and a lot of baggage.

Turns out there's no such thing as portable VM assembly. You still have to ship a full compiler (well, JIT) and compile the WASM IR.

Browser vendors have spent uncountable amount of engineering resources on making yet another compiler (actually multiple, since afaik Chrome uses a tiered JIT for WASM), that's neither as good as the big boys, and neither as fast as just running the dang binary.

PNaCL was published with a standard and tooling, it was Mozzilla that refused to adopt it, and push asm.js instead.

Ironically, if it was today, Google could have pushed PNaCL without any problem.

> If WASM would've worked as advertised, allowing fully fledged apps to run easily and natively in the browser with no fuss and 90% native perf, then basically all app stores would've been dead.

Working on that! I'm building hypen.space which is platform agnostic language & SDK for building native crossplatform apps.

It's a WASM engine at it's core, and while currently it doesn't have "package this app as wasm" capability but supports streaming/local apps only, that capability is currently being developed - together with WASI layers for all of the platforms.

That way your app can run either as a browser (DOM) app, browser canvas app, native desktop or native mobile app.

It's still early, but moving fast - I just added accessibility support, and the animation framework will be out this week.

Regarding the WASM disappointed, when I started building this about 6 years ago, WASM was in a terrible (barely usable without wasting a ton of time) state. Now that WASI 0.3 is out and LLMs have sped up development by a large margin, it's in a quite usable state to ship things to production without fear.

Crediting LLMs with advancing wasm is a disservice to the best-in-industry bytecodealliance community & org.
You might have misread me - I meant in a time when LLM's are speeding up development in general, as now you can write giant interfaces and implementations without having to manually deal with glue code.