Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/environ/src/component/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ pub struct Resource {
///
/// Note that this type does not implement `Serialize` or `Deserialize` and
/// that's intentional as this isn't stored in the final compilation artifact.
#[derive(Debug)]
pub enum Trampoline {
/// Description of a lowered import used in conjunction with
/// `GlobalInitializer::LowerImport`.
Expand Down
6 changes: 3 additions & 3 deletions crates/test-programs/src/bin/async_poll_stackless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ unsafe extern "C" fn callback_run(event0: u32, event1: u32, _event2: u32) -> u32

let set = *set;
let result = async_when_ready();
let status = result >> 30;
let call = result & !(0b11 << 30);
let status = result & 0xf;
let call = result >> 4;
assert!(status != STATUS_RETURNED);
waitable_join(call, set);

Expand Down Expand Up @@ -117,7 +117,7 @@ unsafe extern "C" fn callback_run(event0: u32, event1: u32, _event2: u32) -> u32
assert_eq!(event0, EVENT_NONE);

let set = *set;
assert!(async_when_ready() == STATUS_RETURNED << 30);
assert!(async_when_ready() == STATUS_RETURNED);

*state = State::S5 { set };

Expand Down
6 changes: 3 additions & 3 deletions crates/test-programs/src/bin/async_poll_synchronous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ impl Guest for Component {
assert!(waitable_set_poll(set).is_none());

let result = async_when_ready();
let status = result >> 30;
let call = result & !(0b11 << 30);
let status = result & 0xf;
let call = result >> 4;
assert!(status != STATUS_RETURNED);
waitable_join(call, set);

Expand All @@ -64,7 +64,7 @@ impl Guest for Component {

assert!(waitable_set_poll(set).is_none());

assert!(async_when_ready() == STATUS_RETURNED << 30);
assert!(async_when_ready() == STATUS_RETURNED);

assert!(waitable_set_poll(set).is_none());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ unsafe extern "C" fn export_foo(args: *mut u8) {
let results = alloc::alloc(layout);

let result = import_foo(params, results);
let mut status = result >> 30;
let call = result & !(0b11 << 30);
let mut status = result & 0xf;
let call = result >> 4;
let set = waitable_set_new();
if call != 0 {
waitable_join(call, set);
Expand Down
4 changes: 2 additions & 2 deletions crates/test-programs/src/bin/async_round_trip_stackful.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ unsafe extern "C" fn export_foo(ptr: *mut u8, len: usize) {
let results = alloc::alloc(layout);

let result = import_foo(params, results);
let mut status = result >> 30;
let call = result & !(0b11 << 30);
let mut status = result & 0xf;
let call = result >> 4;
let set = waitable_set_new();
if call != 0 {
waitable_join(call, set);
Expand Down
38 changes: 26 additions & 12 deletions crates/wasmtime/src/runtime/component/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,26 @@ mod ready_chunks;
mod states;
mod table;

/// Corresponds to `CallState` in the upstream spec.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
#[repr(u32)]
enum Status {
pub enum Status {
Starting = 1,
Started,
Returned,
Started = 2,
Returned = 3,
}

impl Status {
/// Packs this status and the optional `waitable` provided into a 32-bit
/// result that the canonical ABI requires.
///
/// The low 4 bits are reserved for the status while the upper 28 bits are
/// the waitable, if present.
pub fn pack(self, waitable: Option<u32>) -> u32 {
assert!(matches!(self, Status::Returned) == waitable.is_none());
let waitable = waitable.unwrap_or(0);
assert!(waitable < (1 << 28));
(waitable << 4) | (self as u32)
}
}

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -1602,12 +1616,14 @@ impl ComponentInstance {

log::trace!("status {status:?} for {}", guest_task.rep());

let call = if status != Status::Returned {
let waitable = if status != Status::Returned {
if async_caller {
self.get_mut(guest_task)?.has_suspended = true;

self.waitable_tables()[caller_instance]
.insert(guest_task.rep(), WaitableState::GuestTask)?
Some(
self.waitable_tables()[caller_instance]
.insert(guest_task.rep(), WaitableState::GuestTask)?,
)
} else {
let caller = if let Caller::Guest { task, .. } = &self.get(guest_task)?.caller {
*task
Expand All @@ -1621,10 +1637,10 @@ impl ComponentInstance {

self.poll_for_result(guest_task)?;
status = Status::Returned;
0
None
}
} else {
0
None
};

if let Some(storage) = storage {
Expand All @@ -1635,10 +1651,8 @@ impl ComponentInstance {
} else {
return Err(anyhow!(crate::Trap::NoAsyncResult));
}
Ok(0)
} else {
Ok(((status as u32) << 30) | call)
}
Ok(status.pack(waitable))
}

pub(crate) fn wrap_call<T, F, P, R>(
Expand Down
15 changes: 5 additions & 10 deletions crates/wasmtime/src/runtime/component/func/host.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "component-model-async")]
use crate::component::concurrent::Accessor;
use crate::component::concurrent::{Accessor, Status};
use crate::component::func::{LiftContext, LowerContext, Options};
use crate::component::matching::InstanceType;
use crate::component::storage::slice_to_storage_mut;
Expand All @@ -23,11 +23,6 @@ use wasmtime_environ::component::{
TypeFuncIndex, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
};

#[cfg(feature = "component-model-async")]
const STATUS_PARAMS_READ: u32 = 1;
#[cfg(feature = "component-model-async")]
const STATUS_DONE: u32 = 3;

pub struct HostFunc {
entrypoint: VMLoweringCallee,
typecheck: Box<dyn (Fn(TypeFuncIndex, &InstanceType<'_>) -> Result<()>) + Send + Sync>,
Expand Down Expand Up @@ -335,9 +330,9 @@ where
})?;

let status = if let Some(task) = task {
(STATUS_PARAMS_READ << 30) | task
Status::Started.pack(Some(task))
} else {
STATUS_DONE << 30
Status::Returned.pack(None)
};

storage[0] = MaybeUninit::new(ValRaw::i32(status as i32));
Expand Down Expand Up @@ -591,9 +586,9 @@ where
})?;

let status = if let Some(task) = task {
(STATUS_PARAMS_READ << 30) | task
Status::Started.pack(Some(task))
} else {
STATUS_DONE << 30
Status::Returned.pack(None)
};

storage[0] = MaybeUninit::new(ValRaw::i32(status as i32));
Expand Down