-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Implement exception objects. #11230
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
Implement exception objects. #11230
Conversation
|
A few other missing bits that I will do before marking as ready:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
We'll need to think about how to hide this appropriately
Personally I think it's reasonable to keep this behind the gc feature flag for now and leave it at that. This won't bring in any significantly new runtime dependencies that gc doesn't already bring, so having it behind the same flag I think is reasonable. In that sense filling out similar-ish GC-disabled stubs for exnref I think is fine.
In the future this means that the hypothetical Config::wasm_exceptions knob will only be available with feature = "gc" and if the gc feature is disabled then this feature will always be disabled for wasmparser, effectively being where we're at today.
One hypothetical branch point we could reach in the future is to implement wasm exceptions entirely independently of wasm gc. In such a world we'd probably have a separate feature gate for exception-handling but in lieu of that I don't think it's necessary to add a new feature just for exceptions (assuming no new "substantial" runtime dependencies or such are needed, which AFAIK won't be the case)
As a small aside, it's a bit regrettable how much duplication in a sense there is necessary for this. Most of this PR looks like a copy/paste of the GC bits for structref but then edited to be for exnref instead. That's not a dealbreaker by any means and rustc more-or-less shoehorns these implementations to exactly what they are, but I also think it'd be reasonable if you see refactoring opportunities to apply them more aggressively too (e.g. what you did here with initialization/reading struct fields and refactoring that so exceptions can use the same path)
Oh one thing I forgot, are you familiar enough with the JS API for exceptions to say whether or not the approach here is roughly analagous? I don't know myself what the JS API looks like so I'm not sure myself. |
Subscribe to Label Actioncc @fitzgen
This issue or pull request has been labeled: "wasmtime:api", "wasmtime:ref-types"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
As far as I can tell, this is pretty close to both the Wasm JS API and the host API outlined in the spec, modulo requiring the |
Yeah, I thought about this quite a bit before building out this part of the proposal: I was wondering whether the two (exceptions and GC) could be kept orthogonal as much as possible, largely to avoid the effort in this PR. An exnref would then be more like an externref; maybe held as an
Yeah, I don't like it too much either; but several alternatives I considered didn't feel great either. In particular one could imagine either using more dynamism internally (having a "struct or exception layout" that knows its kind dynamically and has the appropriate dynamic checks) or using traits or macros to factor out method implementations. In the end the surface bits needed to be separate for clean typesafe API reasons and the rest kind of fell out of that. Happy to take any particulara suggestions for refactors if anyone has any though! |
…eatures --features runtime`).
FWIW I agree with your conclusions as well. I mostly brought this up to say that I think it would warrant a separate feature in such a hypothetical alternative world, but given the current implementation I don't think this warrants a separate feature or anything more than gating behind GC.
FWIW this is mostly my takeaway as well. It's wordy, but easy to read and verify it's right. The downside is that if it's got a bug (which would likely be preexisting if any) there's a lot of places to chase down. I think it's best to leave that for the hypothetical future in which we discover this though. Otherwise though I don't have any silver bullet suggestions myself either. |
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? |
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 |
|
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 #11256 |
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. It is currently stacked on top of bytecodealliance#11321. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. This PR does not yet provide host-boundary-crossing exceptions; exceptions that are not caught in a given Wasm activation become traps at the host boundary. That support will come in a subsequent PR. Because exceptions do not yet cross the host boundary, this also does not yet enable the `assert_exception` wast directive, and so cannot yet support the spec-tests. That will also come in a subsequent PR. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/ prtest:full
This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/ prtest:full
* WebAssembly exception-handling support. This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in #10510 for Cranelift-level exception support, #10919 for an unwinder, and #11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/ prtest:full * Permit UnwindToWasm to have unused fields in Pulley builds (for now). * Resolve miri-caught reborrowing issue. * Ignore exceptions tests in miri for now (Pulley not supported). * Use wasmtime_test on exceptions tests. * Get tests passing on pulley platforms * Add a check to `supports_host` for the generated test and assert failure also when that is false. * Remove `pulley_unsupported` test as it falls out of `#[wasmtime_test]` * Remove `exceptions_store` helper as it falls out of `#[wasmtime_test]` * Remove miri annotations as they fall out of `#[wasmtime_test]` * Remove dead import * Skip some unsupported tests entirely in `#[wasmtime_test]` If the selected compiler doesn't support the host at all then there's no need to run it. Actually running it could misinterpret `CraneliftNative` as "run with pulley" otherwise, so avoid such false negatives. * Cranelift: dynamic contexts: account for outgoing-args area. --------- Co-authored-by: Alex Crichton <[email protected]>
* WIP: Working exception objects * Clean build with gc disabled (`cargo check -p wasmtime --no-default-features --features runtime`). * Review feedback. * Stub out C-API support. * Fix Clippy complaints. * Fix dead-code warning in c-api build. * Actually fix 27->26 reserved bit rename and test. * Fix exnref doc-test. * fix fuzzing build * fix feature-flagging on Instance::id * Bless disas test diff due to reserved-bits change. * Review feedback.
* WebAssembly exception-handling support. This PR introduces support for the [Wasm exception-handling proposal], which introduces a conventional try/catch mechanism to WebAssembly. The PR supports modules that use `try_table` to register handlers for a lexical scope; and provides `throw` and `throw_ref` that allocate (in the first case) and throw exception objects. This PR builds on top of the work in bytecodealliance#10510 for Cranelift-level exception support, bytecodealliance#10919 for an unwinder, and bytecodealliance#11230 for exception objects built on top of GC, in addition a bunch of smaller fix and enabling PRs around those. [Wasm exception-handling proposal]: https://github.com/WebAssembly/exception-handling/ prtest:full * Permit UnwindToWasm to have unused fields in Pulley builds (for now). * Resolve miri-caught reborrowing issue. * Ignore exceptions tests in miri for now (Pulley not supported). * Use wasmtime_test on exceptions tests. * Get tests passing on pulley platforms * Add a check to `supports_host` for the generated test and assert failure also when that is false. * Remove `pulley_unsupported` test as it falls out of `#[wasmtime_test]` * Remove `exceptions_store` helper as it falls out of `#[wasmtime_test]` * Remove miri annotations as they fall out of `#[wasmtime_test]` * Remove dead import * Skip some unsupported tests entirely in `#[wasmtime_test]` If the selected compiler doesn't support the host at all then there's no need to run it. Actually running it could misinterpret `CraneliftNative` as "run with pulley" otherwise, so avoid such false negatives. * Cranelift: dynamic contexts: account for outgoing-args area. --------- Co-authored-by: Alex Crichton <[email protected]>
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
TagTypeis a thin wrapper aroundFuncTypeas 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.