Skip to content

Conversation

@alexcrichton
Copy link
Member

This commit is extracted from #11430 to accurately reflect how const-expr evaluation is an async operation due to GC pauses that may happen. The changes in this commit are:

  • Const-expr evaluation is, at its core, now an async function.
  • To leverage this new async-ness all internal operations are switched from *_maybe_async to *_async meaning all the *_maybe_async methods can be removed.
  • Some libcalls using *_maybe_async are switch to using *_async plus the block_on! utility to help jettison more *_maybe_async methods.
  • Instance initialization is now an async function. This is temporarily handled with block_on during instance initialization to avoid propagating the async-ness further upwards. This block_on will get deleted in future refactorings.
  • Const-expr evaluation has been refactored slightly to enable having a fast path in global initialization which skips an await point entirely, achieving performance-parity in benchmarks prior to this commit.

This ended up fixing a niche issue with GC where if a wasm execution was suspended during table.init, for example, during a const-expr evaluation triggering a GC then if the wasm execution was cancelled it would panic the host. This panic was because the GC operation returned Result but it was unwrap'd as part of the const-expr evaluation which can fail not only to invalid-ness but also due to "computation is cancelled" traps.

This commit is extracted from bytecodealliance#11430 to accurately reflect how
const-expr evaluation is an async operation due to GC pauses that may
happen. The changes in this commit are:

* Const-expr evaluation is, at its core, now an `async` function.
* To leverage this new `async`-ness all internal operations are switched
  from `*_maybe_async` to `*_async` meaning all the `*_maybe_async`
  methods can be removed.
* Some libcalls using `*_maybe_async` are switch to using `*_async` plus
  the `block_on!` utility to help jettison more `*_maybe_async` methods.
* Instance initialization is now an `async` function. This is
  temporarily handled with `block_on` during instance initialization to
  avoid propagating the `async`-ness further upwards. This `block_on`
  will get deleted in future refactorings.
* Const-expr evaluation has been refactored slightly to enable having a
  fast path in global initialization which skips an `await` point
  entirely, achieving performance-parity in benchmarks prior to this commit.

This ended up fixing a niche issue with GC where if a wasm execution was
suspended during `table.init`, for example, during a const-expr
evaluation triggering a GC then if the wasm execution was cancelled it
would panic the host. This panic was because the GC operation returned
`Result` but it was `unwrap`'d as part of the const-expr evaluation
which can fail not only to invalid-ness but also due to "computation is
cancelled" traps.
@alexcrichton alexcrichton requested a review from a team as a code owner August 19, 2025 22:51
@alexcrichton alexcrichton requested review from pchickey and removed request for a team August 19, 2025 22:51
@alexcrichton
Copy link
Member Author

Actually, thinking more, the issue about panicking on const expr evaluation failure means allocation failure in GC is a host panic which isn't great. Deferring that to a separate issue.

@github-actions github-actions bot added wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:ref-types Issues related to reference types and GC in Wasmtime labels Aug 20, 2025
@github-actions
Copy link

Subscribe to Label Action

cc @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:

  • fitzgen: wasmtime:ref-types

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

Learn more.

@pchickey pchickey requested review from fitzgen and removed request for pchickey August 20, 2025 16:48
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

};
block_on!(store, async |store| {
let gc_ref = store
.retry_after_gc_async((), |store, ()| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any non-async retry_after_gc calls at this point? I think all of them should be async by the time we finish the asyncification of the internals, but I'm not sure if we are there yet or not. But when we are, we should delete the non-async version and then just rename the async variation to plain retry_after_gc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soon! (got a PR queued up after #11470 to delete the sync version

Comment on lines +380 to +397
if store.async_support() {
#[cfg(feature = "async")]
store.block_on(|store| {
let module = compiled_module.module().clone();
Box::pin(
async move { vm::initialize_instance(store, id, &module, bulk_memory).await },
)
})??;
#[cfg(not(feature = "async"))]
unreachable!();
} else {
vm::assert_ready(vm::initialize_instance(
store,
id,
compiled_module.module(),
bulk_memory,
))?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then Instance::new_raw will become an async function in another follow up PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! That'll be #11470

@alexcrichton alexcrichton added this pull request to the merge queue Aug 20, 2025
Merged via the queue into bytecodealliance:main with commit d139713 Aug 20, 2025
44 checks passed
@alexcrichton alexcrichton deleted the more-gc-async branch August 20, 2025 17:51
bongjunj pushed a commit to prosyslab/wasmtime that referenced this pull request Oct 20, 2025
* Make const-expr evaluation `async`

This commit is extracted from bytecodealliance#11430 to accurately reflect how
const-expr evaluation is an async operation due to GC pauses that may
happen. The changes in this commit are:

* Const-expr evaluation is, at its core, now an `async` function.
* To leverage this new `async`-ness all internal operations are switched
  from `*_maybe_async` to `*_async` meaning all the `*_maybe_async`
  methods can be removed.
* Some libcalls using `*_maybe_async` are switch to using `*_async` plus
  the `block_on!` utility to help jettison more `*_maybe_async` methods.
* Instance initialization is now an `async` function. This is
  temporarily handled with `block_on` during instance initialization to
  avoid propagating the `async`-ness further upwards. This `block_on`
  will get deleted in future refactorings.
* Const-expr evaluation has been refactored slightly to enable having a
  fast path in global initialization which skips an `await` point
  entirely, achieving performance-parity in benchmarks prior to this commit.

This ended up fixing a niche issue with GC where if a wasm execution was
suspended during `table.init`, for example, during a const-expr
evaluation triggering a GC then if the wasm execution was cancelled it
would panic the host. This panic was because the GC operation returned
`Result` but it was `unwrap`'d as part of the const-expr evaluation
which can fail not only to invalid-ness but also due to "computation is
cancelled" traps.

* Fix configured build

* Undo rebase mistake
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:ref-types Issues related to reference types and GC in Wasmtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants