| 6e21cf1f | 21-Aug-2025 |
Alex Crichton <[email protected]> |
Remove `StoreOpaque::async_yield_impl` (#11482)
* Remove `StoreOpaque::async_yield_impl`
Now that we have all this fancy support for natively running `async` things this commit refactors fuel/epoch
Remove `StoreOpaque::async_yield_impl` (#11482)
* Remove `StoreOpaque::async_yield_impl`
Now that we have all this fancy support for natively running `async` things this commit refactors fuel/epochs to use it. This simplifies the `VMStore` trait, removes a usage of `block_on`, and helps keep the `async` boundary close to the libcall entrypoint rather than further down the stack. This all in turn enables using rustc to check our stack-locals for non-`Send` values instead of pinky promising that we're doing the right thing everywhere.
* Clean up some code movement and comments
* Fix a merge conflict
show more ...
|
| e1f50aad | 21-Aug-2025 |
Alex Crichton <[email protected]> |
Make table/memory creation async functions (#11470)
* Make core instance allocation an `async` function
This commit is a step in preparation for #11430, notably core instance allocation, or `Store
Make table/memory creation async functions (#11470)
* Make core instance allocation an `async` function
This commit is a step in preparation for #11430, notably core instance allocation, or `StoreOpaque::allocate_instance` is now an `async fn`. This function does not actually use the `async`-ness just yet so it's a noop from that point of view, but this propagates outwards to enough locations that I wanted to split this off to make future changes more digestable.
Notably some creation functions here such as making an `Instance`, `Table`, or `Memory` are refactored internally to use this new `async` function. Annotations of `assert_ready` or `one_poll` are used as appropriate as well.
For reference this commit was benchmarked with our `instantiation.rs` benchmark in the pooling allocator and shows no changes relative to the original baseline from before-`async`-PRs.
* Make table/memory creation `async` functions
This commit is a large-ish refactor which is made possible by the many previous refactorings to internals w.r.t. async-in-Wasmtime. The end goal of this change is that table and memory allocation are both `async` functions. Achieving this, however, required some refactoring to enable it to work:
* To work with `Send` neither function can close over `dyn VMStore`. This required changing their `Option<&mut dyn VMStore>` arugment to `Option<&mut StoreResourceLimiter<'_>>` * Somehow a `StoreResourceLimiter` needed to be acquired from an `InstanceAllocationRequest`. Previously the store was stored here as an unsafe raw pointer, but I've refactored this now so `InstanceAllocationRequest` directly stores `&StoreOpaque` and `Option<&mut StoreResourceLimiter>` meaning it's trivial to acquire them. This additionally means no more `unsafe` access of the store during instance allocation (yay!). * Now-redundant fields of `InstanceAllocationRequest` were removed since they can be safely inferred from `&StoreOpaque`. For example passing around `&Tunables` is now all gone. * Methods upwards from table/memory allocation to the `InstanceAllocator` trait needed to be made `async`. This includes new `#[async_trait]` methods for example. * `StoreOpaque::ensure_gc_store` is now an `async` function. This internally carries a new `unsafe` block carried over from before with the raw point passed around in `InstanceAllocationRequest`. A future PR will delete this `unsafe` block, it's just temporary.
I attempted a few times to split this PR up into separate commits but everything is relatively intertwined here so this is the smallest "atomic" unit I could manage to land these changes and refactorings.
* Shuffle `async-trait` dep
* Fix configured build
show more ...
|
| d1397130 | 20-Aug-2025 |
Alex Crichton <[email protected]> |
Make const-expr evaluation `async` (#11468)
* Make const-expr evaluation `async`
This commit is extracted from #11430 to accurately reflect how const-expr evaluation is an async operation due to GC
Make const-expr evaluation `async` (#11468)
* Make const-expr evaluation `async`
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.
* Fix configured build
* Undo rebase mistake
show more ...
|
| 1a88c70a | 19-Aug-2025 |
Alex Crichton <[email protected]> |
Make garbage collection an `async` function (#11461)
* Make garbage collection an `async` function
This commit is similar to #11442 and #11460 except it's applied to the garbage collection phase o
Make garbage collection an `async` function (#11461)
* Make garbage collection an `async` function
This commit is similar to #11442 and #11460 except it's applied to the garbage collection phase of Wasmtime's GC. Specifically the functions that actually perform a GC are no longer duplicated across sync, async, and maybe async versions. There's only one "always async" version and the root-level crate entrypoints for sync versions assert that async support is disabled and then use the async version.
Worth noting here is that GC suffers from a preexisting issue described in #11409 where it's not sound how a `StoreOpaque` is widened to acquire a resource limiter. This commit seemingly makes the issue worse by adding a few more `unsafe` blocks, but they're all fundamentally doing the same thing as before. Fully solving this issue will require making memory/table creation an `async` function that takes the limiter as an argument. Doing this will require further refactoring/code movement so my goal is to effectively maintain the status quo, but in a slightly different location, and enable knocking out the `unsafe` in the future. In the meantime the previous `unsafe` block is "lifted higher up" so it's not quite so deep and should be easier to remove in the future.
* Review comments
* Fix configured build
* More configured build fixes
show more ...
|
| aa91737e | 19-Aug-2025 |
Alex Crichton <[email protected]> |
Relax the `Send` bound on fiber creation (#11454)
* Relax the `Send` bound on fiber creation
This commit removes the need for `Send` for all usages of fiber-related bits. The goal is that the futu
Relax the `Send` bound on fiber creation (#11454)
* Relax the `Send` bound on fiber creation
This commit removes the need for `Send` for all usages of fiber-related bits. The goal is that the future returned from `async` functions is `Send` if all the inputs are `Send`, but there's no actual need to require that in the function signatures themselves. This property was identified in upcoming work to make more internals of Wasmtime `async` where `async` functions are going to be used to implement the synchronous path through Wasmtime where `Send` isn't a bound today, nor ideally do we want to have it there.
The way this commit works is:
* First `make_fiber` now has a `Send` bound which makes it sound. Before #11444 it took `&mut dyn VMStore` which is never `Send` and the refactoring there missed adding this bound. This change required a few `Send` bounds in `concurrent.rs` where it's expected to have no impact as everything there is basically already `Send`.
* Next `make_fiber_unchecked` is added which is the same as `make_fiber` except without a `Send` bound. The `on_fiber` function is then updated to use this `*_unchecked` variant. This means that fibers can now be used with non-`Send` stores. Crucially though the structure of internals in play means that future produced is still only `Send` if `T: Send` meaning that there is no loss in safety.
* Next some `Send` bounds were dropped throughout async functions in Wasmtime as a proof-of-concept to require these changes to `on_fiber`. This means that these entrypoints into Wasmtime no longer require `Send`, but still naturally require `Send` if the result future is sent to various threads.
* Finally a new doctest is added to `Instance::new_async` with a `compile_fail` example to ensure that this fails. This is unfortunately a very brittle test because all we can assert is that compilation failed, not why compilation failed. That means that this is likely to regress over time, but it's the best we can do at this time.
Note that the goal here is NOT to remove `Send` bounds throughout Wasmtime. Many of them are still required, for example all the ones related to `Linker`. The realization is that we can remove some of the "edge" bounds on entrypoints where the resulting future can be conditionally `Send` depending on `T` meaning we don't actually have to write down any bounds ourselves.
This refactoring will enable future refactorings to have sync-and-async functions use the same internals and neither entrypoint needs to have a `Send` bound.
* Review comments
show more ...
|
| 8aefdcc0 | 18-Aug-2025 |
Alex Crichton <[email protected]> |
Delete `StoreOpaque::traitobj_mut` (#11444)
* Delete `StoreOpaque::traitobj_mut`
This was a fundamentally unsound function because it is widening a mutable borrow to encompass more than it original
Delete `StoreOpaque::traitobj_mut` (#11444)
* Delete `StoreOpaque::traitobj_mut`
This was a fundamentally unsound function because it is widening a mutable borrow to encompass more than it originally contained. Removal of its usage falls into a few buckets here:
* Many instances of `store.0.traitobj_mut()` were starting from a `&mut StoreInner<T>`, going to `&mut StoreOpaque`, then going back to `&mut dyn VMStore`. These are replaced with `store.0` as `&mut StoreInner<T>` directly coerces into `&mut dyn VMStore`.
* Some fiber-related helpers were updated to take any store-opaque-thing which encapsulates the ability to start/resume a borrow with a part of the store, but you only get that part of the store during the fiber itself. This means there's no widening necessary.
* Some methods previously taking `&mut StoreOpaque` are now appropriately widened to `&mut dyn VMStore`.
This all enables full deletion of this function which prevents accidentally ever tripping over its unsound-ness.
* Fix configured build
* Another fix for a configured build
* Fix a warning
* Don't hold `VMStore` live over await points
* Review comments
* Move `AsStoreOpaque` to `store.rs` and use it in GC
* Fix configured build
* Switch lint annotation
show more ...
|
| f828ce08 | 18-Aug-2025 |
Alex Crichton <[email protected]> |
Add a helper always-`Sync` utility to Wasmtime (#11453)
* Add a helper always-`Sync` utility to Wasmtime
This commit adds a newtype wrapper to Wasmtime, `AlwaysMut`, which is unconditionally `Sync`
Add a helper always-`Sync` utility to Wasmtime (#11453)
* Add a helper always-`Sync` utility to Wasmtime
This commit adds a newtype wrapper to Wasmtime, `AlwaysMut`, which is unconditionally `Sync` if the stored type is `Send`. This is similar to a `Mutex<T>` where it promotes a `Send` bound to a `Sync` bound, but it's unlike `Mutex<T>` in that `AlwaysMut<T>` has no synchronization. The reason that this is safe is that `AlwaysMut<T>` completely disallows access to the underlying data through `&self` and requires `&mut self`. This is similar to how `Mutex::get_mut` is safe, for example.
This type cleans up a preexisting `unsafe impl Sync` block in funcref management around `SendSyncBump` (`bumpalo::Bump` is `Send`, not `Sync`, but we only access it through `&mut self`). This then additionally removes `unsafe impl Sync for StoreFiber` which, upon reflection, is not sound because we don't ever constraint the store's `T` type to `Sync`, only `Send`. This is effectively no change throughout Wasmtime, however, as fibers are only accessed with `&mut`.
Overall this is mostly just internal refactoring to reduce the amount of `unsafe` inside of Wasmtime and to add a new utility to use in the future too.
* Fix configured build
* Review comments
* Fix configured build
show more ...
|