Skip to content
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

feat: implement error-context #1

Merged
merged 3 commits into from
Jan 16, 2025

Conversation

vados-cosmonic
Copy link

This commit implements error-context related functions inside the VM, along with tests to ensure that basic error-context.new and error-context.debug-message functionality works.

Copy link
Owner

@dicej dicej left a comment

Choose a reason for hiding this comment

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

Looks good overall, thanks! See comments/questions inline.

@vados-cosmonic vados-cosmonic force-pushed the feat=implement-errctx branch 4 times, most recently from 9d846dc to 6982992 Compare January 15, 2025 18:06
@vados-cosmonic vados-cosmonic marked this pull request as ready for review January 15, 2025 18:07
@vados-cosmonic vados-cosmonic force-pushed the feat=implement-errctx branch 4 times, most recently from 72fa7b5 to 89f1f81 Compare January 16, 2025 15:24
This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
@dicej dicej merged commit 64993b9 into dicej:async Jan 16, 2025
@vados-cosmonic vados-cosmonic deleted the feat=implement-errctx branch January 16, 2025 20:50
dicej added a commit that referenced this pull request Jan 17, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 17, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 21, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 22, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 22, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 29, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 29, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 29, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Jan 30, 2025
This is another piece of bytecodealliance#9582 which I'm splitting out to make review easier.

This test exercises fused adapter generation for various flavors of
intercomponent async->async, async->sync, and sync->async calls.

The remaining changes fill in some TODOs to make the test pass.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

address review feedback

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `task.return` to match spec

This temporarily switches to my fork of `wasm-tools` until
bytecodealliance/wasm-tools#1989 is merged.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor `component-model-async` cfg attrs per review feedback

Also, switch to upstream `wasm-tools` main branch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Compiler::new` constructor

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add comments covering various lower/lift combos in FACT generator

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Compiler::global_set` helper function

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component-model-async/task-builtins.wast test

This is another piece of bytecodealliance#9582 which I'm splitting out to make review easier.

This test includes components which use the `task.backpressure`, `task.return`,
`task.wait`, `task.poll`, `task.yield`, and `subtask.drop` builtins.

The rest of the changes fill in some TODOs to make the test pass.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

Add support for async/streams/futures

This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Feb 1, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add round-trip tests with many parameters and results

This adds tests to cover round-tripping values whose flattened form exceed
`MAX_FLAT_PARAMS`.  Although we already had tests to cover this in
tests/all/component_model/func.rs, those tests did not involve any flavor of
composition; these do.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

test: add multiple send as initial context stream test

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

fix Victor's test case

Turns out this was the first test case where the host calls a component via an
async-lifted export, which in turn calls another component's async-lifted export
via a sync-lowered import, which didn't work.  Now it does!

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor sync->async component call adapters

We no longer use global variables to stash parameters and results due to the
hazard of concurrent calls clobbering them.  Instead, we now stash them in the
`GuestTask` object for the task.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Feb 1, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add round-trip tests with many parameters and results

This adds tests to cover round-tripping values whose flattened form exceed
`MAX_FLAT_PARAMS`.  Although we already had tests to cover this in
tests/all/component_model/func.rs, those tests did not involve any flavor of
composition; these do.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

test: add multiple send as initial context stream test

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

fix Victor's test case

Turns out this was the first test case where the host calls a component via an
async-lifted export, which in turn calls another component's async-lifted export
via a sync-lowered import, which didn't work.  Now it does!

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor sync->async component call adapters

We no longer use global variables to stash parameters and results due to the
hazard of concurrent calls clobbering them.  Instead, we now stash them in the
`GuestTask` object for the task.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit that referenced this pull request Feb 1, 2025
This adds support for loading, compiling, linking, and running components which
use the [Async
ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
along with the [`stream`, `future`, and
`error-context`](WebAssembly/component-model#405) types.
It also adds support for generating host bindings such that multiple host
functions can be run concurrently with guest tasks -- without monopolizing the
`Store`.

See the [implementation RFC](bytecodealliance/rfcs#38)
for details, as well as [this
repo](https://github.com/dicej/component-async-demo) containing end-to-end smoke
tests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix clippy warnings and bench/fuzzing errors

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

revert atomic.wit whitespace change

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build when component-model disabled

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless component-macro expected output

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix no-std build error

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix build with --no-default-features --features runtime,component-model

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

partly fix no-std build

It's still broken due to the use of `std::collections::HashMap` in
crates/wasmtime/src/runtime/vm/component.rs.  I'll address that as part of the
work to avoid exposing global task/future/stream/error-context handles to
guests.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

maintain per-instance tables for futures, streams, and error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor task/stream/future handle lifting/lowering

This addresses a couple of issues:

- Previously, we were passing task/stream/future/error-context reps directly to
  instances while keeping track of which instance had access to which rep.  That
  worked fine in that there was no way to forge access to inaccessible reps, but
  it leaked information about what other instances were doing.  Now we maintain
  per-instance waitable and error-context tables which map the reps to and from
  the handles which the instance sees.

- The `no_std` build was broken due to use of `HashMap` in
  `runtime::vm::component`, which is now fixed.

Note that we use one single table per instance for all tasks, streams, and
futures.  This is partly necessary because, when async events are delivered to
the guest, it wouldn't have enough context to know which stream or future we're
talking about if each unique stream and future type had its own table.  So at
minimum, we need to use the same table for all streams (regardless of payload
type), and likewise for futures.  Also, per
WebAssembly/component-model#395 (comment),
the plan is to move towards a shared table for all resource types as well, so
this moves us in that direction.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix wave breakage due to new stream/future/error-context types

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

switch wasm-tools to v1.220.0-based branch

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

check `task.return` type at runtime

We can't statically verify a given call to `task.return` corresponds to the
expected core signature appropriate for the currently running task, so we must
do so at runtime.  In order to make that check efficient, we intern the types.

My initial plan was to use `ModuleInternedTypeIndex` and/or `VMSharedTypeIndex`
for interning, but that got hairy with WasmGC considerations, so instead I added
new fields to `ComponentTypes` and `ComponentTypesBuilder`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `TypedFunc::call_concurrent` and refine stream/future APIs

This implements what I proposed in https://github.com/dicej/rfcs/blob/component-async/accepted/component-model-async.md#wasmtime.  Specifically, it adds:

- A new `Promise` type, useful for working with concurrent operations that require access to a `Store` to make progress.
- A new `PromisesUnordered` type for `await`ing multiple promises concurrently
-`TypedFunc::call_concurrent` (which returns a `Promise`), allowing multiple host->guest calls to run concurrently on the same instance.
- Updated `{Stream|Future}{Writer|Reader}` APIs which use `Promise`

The upshot is that the embedder can now ergonomically manage arbitrary numbers
of concurrent operations.  Previously, this was a lot more difficult to do
without accidentally starving some of the operations due to another one
monopolizing the `Store`.

Finally, this includes various refactorings and fixes for bugs exposed by the
newer, more versatile APIs.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

clean up verbosity in component/func.rs

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

snapshot

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

implement stream/future read/write cancellation

This required a somewhat viral addition of `Send` and `Sync` bounds for async
host function closure types, unfortunately.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add `Func::call_concurrent` and `LinkerInstance::func_new_concurrent`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

dynamic API support for streams/futures/error-contexts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

support callback-less (AKA stackful) async lifts

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix `call_host` regression

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add component model async end-to-end tests

I've ported these over from https://github.com/dicej/component-async-demo

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix test regressions and clippy warnings

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

satisfy clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix async tests when `component-model-async` enabled

Enabling this feature for all tests revealed various missing pieces in the new
`concurrent.rs` fiber mechanism, which I've addressed.

This adds a bunch of ugly `#[cfg(feature = "component-model-async")]` guards,
but those will all go away once I unify the two async fiber implementations.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add and modify tests to cover concurrent APIs

Primarily, this tests and implements cases where parameters and/or results must
be passed via linear memory instead of the stack.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro codegen tests

This enables codegen testing of the `concurrent_imports` and
`concurrent_exports` options to `wasmtime::component::bindgen` and also fixes
code generation for world-level function and resource exports that use the
concurrent call style.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

`concurrent_{imports|exports}` component macro expanded tests

This enables testing of the `concurrent_imports` and `concurrent_exports`
options in `crates/component-macro/tests/expanded.rs`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/*.wast

These only test instantiation of components which use various async options and
built-ins so far.  Next, I'll happy and sad path tests which actually execute
code.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add tests/misc_testsuite/component-model-async/fused.wast

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add non-panicking bounds checks where appropriate

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

remove post-return bits from async result lift code

...at least until we've determined whether post-return options even make sense
for async-lifted exports.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `enum` types to represent status and event codes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix component-model-async/fused.wast test failure (2nd try)

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

use `gc_types = true` in component-model-async/fused.wast

We use `Instruction::RefFunc` when generating adapters for async lifts and/or
lowers, which Winch doesn't understand, and apparently `gc_types = true` is what
tells the test infra not to use Winch.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

trap if async function finishes without calling `task.return`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update wit-bindgen and fix rebase damage

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call post-return function if any for async->sync fused calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build; appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

bless bindgen output whitespace changes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

enforce resource borrow requirements for async calls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

update `wit-bindgen` and simplify `async_borrowing_callee` test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

call `InstanceFlags::set_may_enter` where appropriate

There's still more work to do to fully implement (and test) the reentrance rules
for concurrent tasks, but this is a start.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

finish implementing reentrance checks

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

feat: implement error-context (#1)

* feat: initial error-context implementation

This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: add test for error context callee/caller transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

* wip: test for async context transfer

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

---------

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

run cargo fmt

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

appease clippy

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

pull in Roman's unit stream work; add world-level export test

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add unit stream tests

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

CI fixes

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

fix non-component-model-async build

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

add round-trip tests with many parameters and results

This adds tests to cover round-tripping values whose flattened form exceed
`MAX_FLAT_PARAMS`.  Although we already had tests to cover this in
tests/all/component_model/func.rs, those tests did not involve any flavor of
composition; these do.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

test: add multiple send as initial context stream test

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>

fix Victor's test case

Turns out this was the first test case where the host calls a component via an
async-lifted export, which in turn calls another component's async-lifted export
via a sync-lowered import, which didn't work.  Now it does!

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

refactor sync->async component call adapters

We no longer use global variables to stash parameters and results due to the
hazard of concurrent calls clobbering them.  Instead, we now stash them in the
`GuestTask` object for the task.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants