Skip to content
Open
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
14 changes: 0 additions & 14 deletions benches/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,11 +642,6 @@ mod component {
typed.call(&mut *store, typed_params).unwrap()
};
assert_eq!(results, typed_results);
if is_async.use_async() {
run_await(typed.post_return_async(&mut *store)).unwrap()
} else {
typed.post_return(&mut *store).unwrap()
}
})
});

Expand All @@ -667,11 +662,6 @@ mod component {
for (expected, actual) in expected_results.iter().zip(&results) {
assert_eq!(expected, actual);
}
if is_async.use_async() {
run_await(untyped.post_return_async(&mut *store)).unwrap()
} else {
untyped.post_return(&mut *store).unwrap()
}
})
},
);
Expand Down Expand Up @@ -864,10 +854,8 @@ mod component {
let start = Instant::now();
if is_async.use_async() {
run_await(run.call_async(&mut *store, (iters,))).unwrap();
run_await(run.post_return_async(&mut *store)).unwrap();
} else {
run.call(&mut *store, (iters,)).unwrap();
run.post_return(&mut *store).unwrap();
}
start.elapsed()
})
Expand All @@ -882,10 +870,8 @@ mod component {
let start = Instant::now();
if is_async.use_async() {
run_await(run.call_async(&mut *store, (iters,))).unwrap();
run_await(run.post_return_async(&mut *store)).unwrap();
} else {
run.call(&mut *store, (iters,)).unwrap();
run.post_return(&mut *store).unwrap();
}
start.elapsed()
})
Expand Down
9 changes: 4 additions & 5 deletions crates/c-api/src/component/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ pub unsafe extern "C" fn wasmtime_component_func_call(
})
}

#[deprecated(note = "no longer has any effect")]
Copy link
Member

Choose a reason for hiding this comment

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

Can this percolate up into the C API documentation to indicate that the function is a noop?

#[unsafe(no_mangle)]
pub unsafe extern "C" fn wasmtime_component_func_post_return(
func: &Func,
mut context: WasmtimeStoreContextMut<'_>,
_func: &Func,
_context: WasmtimeStoreContextMut<'_>,
) -> Option<Box<wasmtime_error_t>> {
let result = func.post_return(&mut context);

crate::handle_result(result, |_| {})
crate::handle_result(Ok(()), |_| {})
Copy link
Member

Choose a reason for hiding this comment

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

It's ok to just return None from this function, no need to use the handle_result helper

}

#[unsafe(no_mangle)]
Expand Down
5 changes: 1 addition & 4 deletions crates/fuzzing/src/oracles/component_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,7 @@ where
.await
.unwrap()
} else {
let result = func.call_async(&mut store, params).await.unwrap();
func.post_return_async(&mut store).await.unwrap();
result
func.call_async(&mut store, params).await.unwrap()
};
log::trace!("got result {actual:?}");
assert_eq!(actual, result);
Expand Down Expand Up @@ -382,7 +380,6 @@ pub fn dynamic_component_api_target(input: &mut arbitrary::Unstructured) -> arbi
func.call_async(&mut store, &params, &mut actual)
.await
.unwrap();
func.post_return_async(&mut store).await.unwrap();
}
log::trace!("received results {actual:?}");
assert_eq!(actual, results);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,6 @@ pub async fn test_round_trip(
unreachable!()
};
assert_eq!(*expected, actual);
foo_function.post_return_async(&mut store).await?;
}

store.assert_concurrent_state_empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,6 @@ async fn test_round_trip_many(
unreachable!()
};
assert_eq!(&make(expected), actual);
foo_function.post_return_async(&mut store).await?;
}

store.assert_concurrent_state_empty();
Expand Down
46 changes: 2 additions & 44 deletions crates/test-util/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,10 @@ use std::mem::MaybeUninit;
use wasmtime::component::__internal::{
CanonicalAbiInfo, InstanceType, InterfaceType, LiftContext, LowerContext,
};
use wasmtime::component::{ComponentNamedList, ComponentType, Func, Lift, Lower, TypedFunc, Val};
use wasmtime::{AsContextMut, Config, Engine};
use wasmtime::component::{ComponentType, Lift, Lower};
use wasmtime::{Config, Engine};
use wasmtime_environ::prelude::*;

pub trait TypedFuncExt<P, R> {
fn call_and_post_return(&self, store: impl AsContextMut<Data: Send>, params: P) -> Result<R>;
}

impl<P, R> TypedFuncExt<P, R> for TypedFunc<P, R>
where
P: ComponentNamedList + Lower,
R: ComponentNamedList + Lift + Send + Sync + 'static,
{
fn call_and_post_return(
&self,
mut store: impl AsContextMut<Data: Send>,
params: P,
) -> Result<R> {
let result = self.call(&mut store, params)?;
self.post_return(&mut store)?;
Ok(result)
}
}

pub trait FuncExt {
fn call_and_post_return(
&self,
store: impl AsContextMut<Data: Send>,
params: &[Val],
results: &mut [Val],
) -> Result<()>;
}

impl FuncExt for Func {
fn call_and_post_return(
&self,
mut store: impl AsContextMut<Data: Send>,
params: &[Val],
results: &mut [Val],
) -> Result<()> {
self.call(&mut store, params, results)?;
self.post_return(&mut store)?;
Ok(())
}
}

pub fn config() -> Config {
drop(env_logger::try_init());

Expand Down
117 changes: 21 additions & 96 deletions crates/wasmtime/src/runtime/component/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
//! store. This is equivalent to `StoreContextMut::spawn` but more convenient to use
//! in host functions.

use crate::component::func::{self, Func};
use crate::component::func::{self, Func, call_post_return};
use crate::component::{
HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, RuntimeInstance,
};
Expand Down Expand Up @@ -81,7 +81,6 @@ use std::mem::{self, ManuallyDrop, MaybeUninit};
use std::ops::DerefMut;
use std::pin::{Pin, pin};
use std::ptr::{self, NonNull};
use std::slice;
use std::sync::Arc;
use std::task::{Context, Poll, Waker};
use std::vec::Vec;
Expand Down Expand Up @@ -1444,7 +1443,6 @@ impl StoreOpaque {
tx: None,
exit_tx: Arc::new(oneshot::channel().0),
host_future_present: false,
call_post_return_automatically: false,
caller: state.guest_thread,
}
},
Expand Down Expand Up @@ -2225,7 +2223,7 @@ impl Instance {
log::trace!(
"sync/async-stackful call: replaced {old_thread:?} with {guest_thread:?} as current thread",
);
let mut flags = self.id().get(store).instance_flags(callee_instance.index);
let flags = self.id().get(store).instance_flags(callee_instance.index);

store.maybe_push_call_context(guest_thread.task)?;

Expand All @@ -2244,12 +2242,9 @@ impl Instance {
// over must be valid.
let storage = call(store)?;

// This is a callback-less call, so the implicit thread has now completed
self.cleanup_thread(store, guest_thread, callee_instance.index)?;

if async_ {
let task = store.concurrent_state_mut().get_mut(guest_thread.task)?;
if task.threads.is_empty() && !task.returned_or_cancelled() {
if task.threads.len() == 1 && !task.returned_or_cancelled() {
bail!(Trap::NoAsyncResult);
}
} else {
Expand Down Expand Up @@ -2287,47 +2282,21 @@ impl Instance {
_ => unreachable!(),
};

if store
.concurrent_state_mut()
.get_mut(guest_thread.task)?
.call_post_return_automatically()
{
unsafe {
flags.set_may_leave(false);
flags.set_needs_post_return(false);
}

if let Some(func) = post_return {
let mut store = token.as_context_mut(store);

// SAFETY: `func` is a valid `*mut VMFuncRef` from
// either `wasmtime-cranelift`-generated fused adapter
// code or `component::Options`. Per `wasmparser`
// post-return signature validation, we know it takes a
// single parameter.
unsafe {
crate::Func::call_unchecked_raw(
&mut store,
func.as_non_null(),
slice::from_ref(&post_return_arg).into(),
)?;
}
}

unsafe {
flags.set_may_leave(true);
}
unsafe {
call_post_return(
token.as_context_mut(store),
post_return.map(|v| v.as_non_null()),
post_return_arg,
flags,
)?;
}

self.task_complete(
store,
guest_thread.task,
result,
Status::Returned,
post_return_arg,
)?;
self.task_complete(store, guest_thread.task, result, Status::Returned)?;
}

// This is a callback-less call, so the implicit thread has now completed
self.cleanup_thread(store, guest_thread, callee_instance.index)?;

store.set_thread(old_thread);

store.maybe_pop_call_context(guest_thread.task)?;
Expand Down Expand Up @@ -2975,13 +2944,7 @@ impl Instance {
log::trace!("task.return for {guest_thread:?}");

let result = (lift.lift)(store, storage)?;
self.task_complete(
store,
guest_thread.task,
result,
Status::Returned,
ValRaw::i32(0),
)
self.task_complete(store, guest_thread.task, result, Status::Returned)
}

/// Implements the `task.cancel` intrinsic.
Expand Down Expand Up @@ -3011,7 +2974,6 @@ impl Instance {
guest_thread.task,
Box::new(DummyResult),
Status::ReturnCancelled,
ValRaw::i32(0),
)
}

Expand All @@ -3026,35 +2988,14 @@ impl Instance {
guest_task: TableId<GuestTask>,
result: Box<dyn Any + Send + Sync>,
status: Status,
post_return_arg: ValRaw,
) -> Result<()> {
if store
.concurrent_state_mut()
.get_mut(guest_task)?
.call_post_return_automatically()
{
let (calls, host_table, _, instance) =
store.component_resource_state_with_instance(self);
ResourceTables {
calls,
host_table: Some(host_table),
guest: Some(instance.instance_states()),
}
.exit_call()?;
} else {
// As of this writing, the only scenario where `call_post_return_automatically`
// would be false for a `GuestTask` is for host-to-guest calls using
// `[Typed]Func::call_async`, in which case the `function_index`
// should be a non-`None` value.
let function_index = store
.concurrent_state_mut()
.get_mut(guest_task)?
.function_index
.unwrap();
self.id()
.get_mut(store)
.post_return_arg_set(function_index, post_return_arg);
Comment on lines -3054 to -3056
Copy link
Member

Choose a reason for hiding this comment

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

I think this function on vm::ComponentInstance, as well as the internal slot for this, may all be deletable now too

let (calls, host_table, _, instance) = store.component_resource_state_with_instance(self);
ResourceTables {
calls,
host_table: Some(host_table),
guest: Some(instance.instance_states()),
}
.exit_call()?;

let state = store.concurrent_state_mut();
let task = state.get_mut(guest_task)?;
Expand Down Expand Up @@ -4321,8 +4262,6 @@ enum Caller {
/// If true, there's a host future that must be dropped before the task
/// can be deleted.
host_future_present: bool,
/// If true, call `post-return` function (if any) automatically.
call_post_return_automatically: bool,
/// If `Some`, represents the `QualifiedThreadId` caller of the host
/// function which called back into a guest. Note that this thread
/// could belong to an entirely unrelated top-level component instance
Expand Down Expand Up @@ -4656,7 +4595,6 @@ impl GuestTask {
// exited:
exit_tx: exit_tx.clone(),
host_future_present: false,
call_post_return_automatically: true,
caller: *caller,
};
}
Expand All @@ -4672,17 +4610,6 @@ impl GuestTask {

Ok(())
}

fn call_post_return_automatically(&self) -> bool {
matches!(
self.caller,
Caller::Guest { .. }
| Caller::Host {
call_post_return_automatically: true,
..
}
)
}
}

impl TableDebug for GuestTask {
Expand Down Expand Up @@ -5300,7 +5227,6 @@ pub(crate) fn prepare_call<T, R>(
handle: Func,
param_count: usize,
host_future_present: bool,
call_post_return_automatically: bool,
lower_params: impl FnOnce(Func, StoreContextMut<T>, &mut [MaybeUninit<ValRaw>]) -> Result<()>
+ Send
+ Sync
Expand Down Expand Up @@ -5348,7 +5274,6 @@ pub(crate) fn prepare_call<T, R>(
tx: Some(tx),
exit_tx: Arc::new(exit_tx),
host_future_present,
call_post_return_automatically,
caller,
},
callback.map(|callback| {
Expand Down
Loading
Loading