Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit 88dd50b

Browse files
dicejalexcrichton
andauthored
big Store->ComponentInstance refactor (#87)
* Enable async support in wast tests This commit updates the `wasmtime-wast` crate to conditionally use the `Config::async_support` mode of Wasmtime, notably executing `instantiate_async` and `call_async`. At this time no actual concurrency is supported and everything is immediately await'd on via `block_on` and a local single-thread tokio runtime. The motivation for this commit is that in the upcoming implementation of WASIp3 async will effectively be the only way to invoke components. Furthermore to test these components we're wanting to use async APIs as the root of invocations for writing `*.wast` tests for testing component-model async features. In enabling this support this commit additionally updates the `wast_tests` fuzzer to execute all tests both with and without async. Effectively the async configuration is now a fuzz option, meaning that all tests are being executed with async now as well to ensure that they work (yay!). The `--test wast` testing mode and `wasmtime wast` CLI command are both updated to unconditionally use async. There should be no loss in test coverage due to the fuzzer update, and right now knobs aren't provided to conditionally use sync in these two modes, again because it's currently expected that this won't be able to run component model async tests, so the defaults are changing. * big Store->ComponentInstance refactor Previously, I had put a `ConcurrentState` field in `StoreInner`, not realizing that it actually belonged in `ComponentInstance` instead. Only when Alex opened serially) by several `ComponentInstance`s, meaning that the state I had put in `StoreInner` was being reused by multiple instances, with chaotic results. This moves the state to `ComponentInstance`, which required changing a _lot_ of code that assumed it could get everything it needed from a `StoreContextMut`. In the process of all these changes, I was able to remove a lot of type parameters from functions which never really needed the `T` in `StoreContextMut<T>` anyway, which means the compiler doesn't need to do as much monomorphization anymore. Other notable changes: - `Linker::func_{wrap|new}_concurrent` no longer need `Sync` futures, and now they take an `Accessor`, providing the same ergonomic advantages as `wasmtime-wit-bindgen`-generated code offers. - I've changed the `{Future|Stream}{Writer|Reader}::watch_{writer|reader}` return value to make it easier to use and cancel. - You now need a `component::Instance` to create a future or a stream. You can get that from within host functions using `Accessor::instance` or `Access::instance`. And in top-level embedder code, you can get it using `{Linker|InstancePre}::instantiate_async`. - Note that `wasmtime-wit-bindgen`-generated instantiation code tends to hide the `component::Instance` from you, but you can still get it by calling e.g. `Linker::instantiate_async` directly and then passing the result to the appropriate `new` function in the generated bindings. See the tests for examples. Fixes #30 Signed-off-by: Joel Dice <joel.dice@fermyon.com> --------- Signed-off-by: Joel Dice <joel.dice@fermyon.com> Co-authored-by: Alex Crichton <alex@alexcrichton.com>
1 parent bf0d3ec commit 88dd50b

65 files changed

Lines changed: 9692 additions & 7426 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/component-macro/tests/expanded/char_concurrent.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,13 @@ pub mod foo {
199199
fn take_char<T: 'static>(
200200
accessor: &mut wasmtime::component::Accessor<T, Self>,
201201
x: char,
202-
) -> impl ::core::future::Future<Output = ()> + Send + Sync
202+
) -> impl ::core::future::Future<Output = ()> + Send
203203
where
204204
Self: Sized;
205205
/// A function that returns a character
206206
fn return_char<T: 'static>(
207207
accessor: &mut wasmtime::component::Accessor<T, Self>,
208-
) -> impl ::core::future::Future<Output = char> + Send + Sync
208+
) -> impl ::core::future::Future<Output = char> + Send
209209
where
210210
Self: Sized;
211211
}
@@ -247,6 +247,7 @@ pub mod foo {
247247
>(
248248
getter: G,
249249
store: wasmtime::VMStoreRawPtr,
250+
instance: Option<wasmtime::component::Instance>,
250251
cx: &mut wasmtime::component::__internal::Context,
251252
future: wasmtime::component::__internal::Pin<&mut F>,
252253
) -> wasmtime::component::__internal::Poll<F::Output> {
@@ -271,8 +272,10 @@ pub mod foo {
271272
(future.poll(cx), STATE.with(|v| v.take()).unwrap().spawned)
272273
};
273274
for spawned in spawned {
274-
store_cx
275+
instance
276+
.unwrap()
275277
.spawn(
278+
&mut store_cx,
276279
wasmtime::component::__internal::poll_fn(move |cx| {
277280
let mut spawned = spawned.try_lock().unwrap();
278281
let inner = mem::replace(
@@ -284,6 +287,7 @@ pub mod foo {
284287
let result = poll_with_state(
285288
getter,
286289
store,
290+
instance,
287291
cx,
288292
future.as_mut(),
289293
);
@@ -325,50 +329,79 @@ pub mod foo {
325329
let mut inst = linker.instance("foo:foo/chars")?;
326330
inst.func_wrap_concurrent(
327331
"take-char",
328-
move |caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (char,)| {
332+
move |
333+
caller: &mut wasmtime::component::Accessor<T, T>,
334+
(arg0,): (char,)|
335+
{
329336
let mut accessor = unsafe {
330337
wasmtime::component::Accessor::<
331338
T,
332339
_,
333-
>::new(get_host_and_store, spawn_task)
340+
>::new(
341+
get_host_and_store,
342+
spawn_task,
343+
caller.maybe_instance(),
344+
)
334345
};
335346
let mut future = wasmtime::component::__internal::Box::pin(async move {
336347
let r = <G::Host as Host>::take_char(&mut accessor, arg0)
337348
.await;
338349
Ok(r)
339350
});
340-
let store = wasmtime::VMStoreRawPtr(caller.traitobj());
351+
let store = wasmtime::VMStoreRawPtr(
352+
caller
353+
.with(|mut v| {
354+
wasmtime::AsContextMut::as_context_mut(&mut v).traitobj()
355+
}),
356+
);
357+
let instance = caller.maybe_instance();
341358
wasmtime::component::__internal::Box::pin(
342-
wasmtime::component::__internal::poll_fn(move |cx| poll_with_state(
343-
host_getter,
344-
store,
345-
cx,
346-
future.as_mut(),
347-
)),
359+
wasmtime::component::__internal::poll_fn(move |cx| {
360+
poll_with_state(
361+
host_getter,
362+
store,
363+
instance,
364+
cx,
365+
future.as_mut(),
366+
)
367+
}),
348368
)
349369
},
350370
)?;
351371
inst.func_wrap_concurrent(
352372
"return-char",
353-
move |caller: wasmtime::StoreContextMut<'_, T>, (): ()| {
373+
move |caller: &mut wasmtime::component::Accessor<T, T>, (): ()| {
354374
let mut accessor = unsafe {
355375
wasmtime::component::Accessor::<
356376
T,
357377
_,
358-
>::new(get_host_and_store, spawn_task)
378+
>::new(
379+
get_host_and_store,
380+
spawn_task,
381+
caller.maybe_instance(),
382+
)
359383
};
360384
let mut future = wasmtime::component::__internal::Box::pin(async move {
361385
let r = <G::Host as Host>::return_char(&mut accessor).await;
362386
Ok((r,))
363387
});
364-
let store = wasmtime::VMStoreRawPtr(caller.traitobj());
388+
let store = wasmtime::VMStoreRawPtr(
389+
caller
390+
.with(|mut v| {
391+
wasmtime::AsContextMut::as_context_mut(&mut v).traitobj()
392+
}),
393+
);
394+
let instance = caller.maybe_instance();
365395
wasmtime::component::__internal::Box::pin(
366-
wasmtime::component::__internal::poll_fn(move |cx| poll_with_state(
367-
host_getter,
368-
store,
369-
cx,
370-
future.as_mut(),
371-
)),
396+
wasmtime::component::__internal::poll_fn(move |cx| {
397+
poll_with_state(
398+
host_getter,
399+
store,
400+
instance,
401+
cx,
402+
future.as_mut(),
403+
)
404+
}),
372405
)
373406
},
374407
)?;

0 commit comments

Comments
 (0)