Skip to content

Commit a8c9d94

Browse files
committed
trap sync-lowered, guest->guest async calls in sync tasks
I somehow forgot to address this earlier. Thanks to Luke for catching this. Note that this commit doesn't include test coverage, but Luke's forthecoming tests in the `component-model` repo will cover it, and we'll pull that in with the next submodule update. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent 438edee commit a8c9d94

File tree

9 files changed

+49
-0
lines changed

9 files changed

+49
-0
lines changed

crates/cranelift/src/compiler/component.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,14 @@ impl<'a> TrampolineCompiler<'a> {
742742
|_, _| {},
743743
);
744744
}
745+
Trampoline::CheckBlocking => {
746+
self.translate_libcall(
747+
host::check_blocking,
748+
TrapSentinel::Falsy,
749+
WasmArgs::InRegisters,
750+
|_, _| {},
751+
);
752+
}
745753
Trampoline::ContextGet { instance, slot } => {
746754
self.translate_libcall(
747755
host::context_get,

crates/environ/src/component.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ macro_rules! foreach_builtin_component_function {
187187
#[cfg(feature = "component-model-async")]
188188
error_context_transfer(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u64;
189189
#[cfg(feature = "component-model-async")]
190+
check_blocking(vmctx: vmctx) -> bool;
191+
#[cfg(feature = "component-model-async")]
190192
context_get(vmctx: vmctx, caller_instance: u32, slot: u32) -> u64;
191193
#[cfg(feature = "component-model-async")]
192194
context_set(vmctx: vmctx, caller_instance: u32, slot: u32, val: u32) -> bool;

crates/environ/src/component/dfg.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ pub enum Trampoline {
478478
FutureTransfer,
479479
StreamTransfer,
480480
ErrorContextTransfer,
481+
CheckBlocking,
481482
ContextGet {
482483
instance: RuntimeComponentInstanceIndex,
483484
slot: u32,
@@ -1160,6 +1161,7 @@ impl LinearizeDfg<'_> {
11601161
Trampoline::FutureTransfer => info::Trampoline::FutureTransfer,
11611162
Trampoline::StreamTransfer => info::Trampoline::StreamTransfer,
11621163
Trampoline::ErrorContextTransfer => info::Trampoline::ErrorContextTransfer,
1164+
Trampoline::CheckBlocking => info::Trampoline::CheckBlocking,
11631165
Trampoline::ContextGet { instance, slot } => info::Trampoline::ContextGet {
11641166
instance: *instance,
11651167
slot: *slot,

crates/environ/src/component/info.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,10 @@ pub enum Trampoline {
11121112
/// component does not invalidate the handle in the original component.
11131113
ErrorContextTransfer,
11141114

1115+
/// An intrinsic used by FACT-generated modules to check whether an
1116+
/// async-typed function may be called via a sync lower.
1117+
CheckBlocking,
1118+
11151119
/// Intrinsic used to implement the `context.get` component model builtin.
11161120
///
11171121
/// The payload here represents that this is accessing the Nth slot of local
@@ -1242,6 +1246,7 @@ impl Trampoline {
12421246
FutureTransfer => format!("future-transfer"),
12431247
StreamTransfer => format!("stream-transfer"),
12441248
ErrorContextTransfer => format!("error-context-transfer"),
1249+
CheckBlocking => format!("check-blocking"),
12451250
ContextGet { .. } => format!("context-get"),
12461251
ContextSet { .. } => format!("context-set"),
12471252
ThreadIndex => format!("thread-index"),

crates/environ/src/component/translate/adapt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ fn fact_import_to_core_def(
345345
fact::Import::ErrorContextTransfer => {
346346
simple_intrinsic(dfg::Trampoline::ErrorContextTransfer)
347347
}
348+
fact::Import::CheckBlocking => simple_intrinsic(dfg::Trampoline::CheckBlocking),
348349
}
349350
}
350351

crates/environ/src/fact.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub struct Module<'a> {
9090
imported_stream_transfer: Option<FuncIndex>,
9191
imported_error_context_transfer: Option<FuncIndex>,
9292

93+
imported_check_blocking: Option<FuncIndex>,
94+
9395
// Current status of index spaces from the imports generated so far.
9496
imported_funcs: PrimaryMap<FuncIndex, Option<CoreDef>>,
9597
imported_memories: PrimaryMap<MemoryIndex, CoreDef>,
@@ -260,6 +262,7 @@ impl<'a> Module<'a> {
260262
imported_future_transfer: None,
261263
imported_stream_transfer: None,
262264
imported_error_context_transfer: None,
265+
imported_check_blocking: None,
263266
exports: Vec::new(),
264267
}
265268
}
@@ -713,6 +716,17 @@ impl<'a> Module<'a> {
713716
)
714717
}
715718

719+
fn import_check_blocking(&mut self) -> FuncIndex {
720+
self.import_simple(
721+
"async",
722+
"check-blocking",
723+
&[],
724+
&[],
725+
Import::CheckBlocking,
726+
|me| &mut me.imported_check_blocking,
727+
)
728+
}
729+
716730
fn translate_helper(&mut self, helper: Helper) -> FunctionId {
717731
*self.helper_funcs.entry(helper).or_insert_with(|| {
718732
// Generate a fresh `Function` with a unique id for what we're about to
@@ -871,6 +885,9 @@ pub enum Import {
871885
/// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
872886
/// ownership of an `error-context`.
873887
ErrorContextTransfer,
888+
/// An intrinsic used by FACT-generated modules to check whether an
889+
/// async-typed function may be called via a sync lower.
890+
CheckBlocking,
874891
}
875892

876893
impl Options {

crates/environ/src/fact/trampoline.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,11 @@ impl<'a, 'b> Compiler<'a, 'b> {
753753
);
754754
}
755755

756+
if self.types[adapter.lift.ty].async_ {
757+
let check_blocking = self.module.import_check_blocking();
758+
self.instruction(Call(check_blocking.as_u32()));
759+
}
760+
756761
if self.emit_resource_call {
757762
let enter = self.module.import_resource_enter_call();
758763
self.instruction(Call(enter.as_u32()));

crates/wasmtime/src/runtime/component/concurrent.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,10 @@ impl Instance {
20722072
) -> Result<()> {
20732073
self.id().get(store.0).check_may_leave(caller_instance)?;
20742074

2075+
if let (CallerInfo::Sync { .. }, true) = (&caller_info, callee_async) {
2076+
store.0.concurrent_state_mut().check_blocking()?;
2077+
}
2078+
20752079
enum ResultInfo {
20762080
Heap { results: u32 },
20772081
Stack { result_count: u32 },

crates/wasmtime/src/runtime/vm/component/libcalls.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,11 @@ fn error_context_transfer(
979979
instance.error_context_transfer(store, src_idx, src_table, dst_table)
980980
}
981981

982+
#[cfg(feature = "component-model-async")]
983+
fn check_blocking(store: &mut dyn VMStore, _instance: Instance) -> Result<()> {
984+
crate::component::concurrent::check_blocking(store)
985+
}
986+
982987
#[cfg(feature = "component-model-async")]
983988
unsafe impl HostResultHasUnwindSentinel for ResourcePair {
984989
type Abi = u64;

0 commit comments

Comments
 (0)