Stream: git-wasmtime

Topic: wasmtime / PR #11230 Implement exception objects.


view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin edited PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin has marked PR #11230 as ready for review.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin requested alexcrichton for a review on PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin requested wasmtime-compiler-reviewers for a review on PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin requested wasmtime-core-reviewers for a review on PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin requested wasmtime-fuzz-reviewers for a review on PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin requested fitzgen for a review on PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 00:21):

cfallin commented on PR #11230:

I think this is ready for a proper review now (and I've addressed comments from Alex and bjorn3 already -- thanks!).

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 01:48):

fitzgen submitted PR review:

LGTM!

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 01:48):

fitzgen created PR review comment:

Should this return a StoreInstanceId (i.e. a (StoreId, InstanceId) pair) instead of a plain InstanceId as the first tuple member here? That would make it fully "tamper-proof".

I am not sure where this method is used yet tho...

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 01:48):

fitzgen created PR review comment:

    /// * `Ok(Ok(_))`: The allocation was successful.

I guess the copy-paste source probably needs updates too...

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 01:48):

fitzgen created PR review comment:

    /// Allocate an uninitialized exception object with the given type

"exceptino" would make a good pokemon name

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 04:03):

github-actions[bot] commented on PR #11230:

Subscribe to Label Action

cc @fitzgen

<details>
This issue or pull request has been labeled: "fuzzing", "wasmtime:c-api"

Thus the following users have been cc'd because of the following labels:

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

Learn more.
</details>

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 06:03):

jeffparsons submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 06:03):

jeffparsons created PR review comment:

Isn't that the evolution of _MissingNo._?

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 09:06):

tschneidereit commented on PR #11230:

Perhaps with the exception of a setjmp/longjmp use-case in wasi-libc?

I think this is a very load-bearing "perhaps", fwiw: I can very very easily see people wanting to have smallest-possible Wasmtime builds and not use GC. And I can equally easily see wasi-libc switch to using sjlj based on EH.

None of this might be enough to put in the work to support exceptions without GC, of course. But if it's more a lack of signal for a need for it: I would bet good money on us getting that signal before too long

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 12:27):

sunfishcode commented on PR #11230:

wasi-libc does have a setjmp/longjmp implementation using EH, and does not support setjmp/longjmp otherwise.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:08):

cfallin commented on PR #11230:

Yes, that's fair, and I did discuss this with Nick early on re: overheads of requiring GC. It seems that the lazy GC heap allocation means that we should be able to have GC enabled without paying a large penalty for it when not used. That, put against the huge duplication of code to also have a "GC-less exceptions" implementation (which would necessarily be almost fully separate, and would also require separate codegen paths), convinced me to go this route.

I'll note that the exceptions proposal's structuring unfortunately pushes us in this direction too: it does not hold back catch_ref clauses and throw_ref to a "when GC enabled" superset, but rather these are always available. It wouldn't be too bad to do an "unboxed exceptions" implementation that directly copies payload values and supports only catch clauses and throw, and indeed I started designing down that route in the hope that I could make setjmp/longjmp a happy fastpath, but it's just too much duplication to be maintainable, and also once you need to support the full proposal and box into exception objects, it adds dynamic checks to support the full matrix of {boxed, unboxed} ^ 2.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:17):

alexcrichton commented on PR #11230:

Personally while I agree with @cfallin's conclusions about this direction being the way to go for now I also believe that this issue won't be put to rest and this is something we're going to have to deal with. One example is that allocating a GC heap is akin to a second linear memory meaning that the per-Store overhead will jump from one linear memory to two linear memories for "lean" languages such as Rust/C/C++, just to support exceptions. (assuming guests eventually get to the point of using exceptions by default). That's then additionally coupled with the fact that it's unlikely embedders will want to interact deeply with exceptions (e.g. make their own, read fields, etc) and nor will Rust/C/C++ use the GC-like behavior of exceptions (e.g. a catch_ref is probably immediately always followed by a throw_ref later in the control flow).

I think these are all problems we're going to have to tackle at some point in the future. "Just turn on GC" as-is today I don't think is going to cut it in the long-term, but I also don't think that should apply stop-energy here either. This implementation is also going to be required in the fullness of time to support GC languages and the exceptions they throw/use. In essence I think that this implementation is basically inevitable and the only hypothetical missing piece is a leaner implementation of "only the exceptions bits needed for linear memory languages". That's hypothetical in that it's not certain we need it and it's also not certain what exact subset, if any, is needed.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:43):

cfallin created PR review comment:

I thought about that, but this is stored within an object within the store, and when we reconstitute a &Tag we use the store it came from, so I think we should be fine in this case (vs. adding 4 bytes to every exception object).

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:43):

cfallin submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:44):

cfallin updated PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:44):

cfallin created PR review comment:

Fixed!

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:44):

cfallin submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:45):

cfallin submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:45):

cfallin created PR review comment:

Fixed!

And fwiw, I believe exceptinos are the subatomic particles that convey exception throws at the speed of light...

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:45):

cfallin edited PR #11230:

This PR implements exception objects: the data model required to support Wasm exceptions, integrated with Wasm GC.

It builds out support for defining exception types (based on function signatures), and a host API to allocate and examine exception objects. It does not yet tie this into any exception-throwing or -catching instructions (throw, throw_ref, try_table); that will come next.

The design is a little fiddly because the type system has a nominal aspect to it: tags are per-instance entities and exceptions are associated with tags. The stack-switching work already added support for tags analogously to other instance entities (memories, tables, etc.). But, notably, because they are a runtime concept, they are not types per-se. Their signatures are, though, and TagType is a thin wrapper around FuncType as a result. The Wasm proposal does not define any concrete type definitions for exception objects in the lattice, only providing top (exnref / (ref null exn)) and bottom (nullexnref / (ref null noexn)) types. In order to align with the way the rest of the GC system works, I've opted to define our own notion of structural types at the host API and type-interning layer built around the signatures; so all Wasm exception objects with the same func-type / signature are the same "type" as far as GC is concerned. The objects of that type are then associated with particular tag instances via runtime fields. In essence we are refining the Wasm types further to allow our implementation to precompute things (i.e., layouts); this is fine because this refinement is not exposed to Wasm.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 16:46):

cfallin has enabled auto merge for PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 17:39):

cfallin merged PR #11230.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 15 2025 at 17:46):

fitzgen commented on PR #11230:

I think we will want to keep the implementation of exceptions in terms of GC objects, with possible unboxing optimizations that are really orthogonal to the core discussion here, but we will want to add config knobs dedicated for GC heaps. Right now, GC heaps are always the same configuration as linear memories. For LIME-style deployments, however, they will want to configure the GC heap to be much smaller than 64KiB (effectively using custom-page-sizes for GC heap memories), after which

allocating a GC heap is akin to a second linear memory

is effectively resolved.

We really don't want to have to maintain two implementations of exceptions: one for LIME Wasm and one for GC Wasm. By allowing one to configure the GC heap so that it is tiny, we are effectively allowing the GC-based implementation to be tuned down into the equivalent side-table that we would implement for the LIME Wasm version.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 16 2025 at 10:20):

tschneidereit commented on PR #11230:

is effectively resolved.

Does this allow us to set the allocation to 0, or something really very small? Because if it still requires at least one host page size of memory, I'm not sure it really is effectively resolved for all use cases.

Besides memory usage, I'm also concerned about the code size increase we incur by forcing the inclusion of full GC support for exception handling. Do we have a way to quantify / at least very roughly estimate how much larger a size-optimized binary becomes because of that?

view this post on Zulip Wasmtime GitHub notifications bot (Jul 16 2025 at 12:42):

sunfishcode commented on PR #11230:

It wouldn't be too bad to do an "unboxed exceptions" implementation that directly copies payload values and supports only catch clauses and throw

In the Lime series, we do have the ability to subset features, for exactly this reason, so perhaps we should to that for EH too.

It seems likely that other engines will want a subset too. And the setjmp/longjmp used by LLVM and wasi-libc already uses just catch and throw.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 16 2025 at 17:31):

fitzgen commented on PR #11230:

Meta note: I am going to file a follow up issue for this discussion. Once I do so, let's move all this discussion there.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 16 2025 at 18:08):

fitzgen commented on PR #11230:

Meta note: I am going to file a follow up issue for this discussion. Once I do so, let's move all this discussion there.

Filed https://github.com/bytecodealliance/wasmtime/issues/11256


Last updated: Dec 06 2025 at 07:03 UTC