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

Commit d977c53

Browse files
committed
add comments to unsafe code in futures_and_streams.rs
Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent 6de0738 commit d977c53

2 files changed

Lines changed: 512 additions & 195 deletions

File tree

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

Lines changed: 160 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,10 @@ impl ComponentInstance {
763763
log::trace!("push call context for {guest_task:?}");
764764
let call_context = task.call_context.take().unwrap();
765765
// SAFETY: This `ComponentInstance` belongs to the store in which it
766-
// resides, so if it is valid then so is its store.
766+
// resides, so if it is valid then so is its store. Furthermore,
767+
// this function is only called (transitively) from
768+
// `ComponentInstance::poll_until`, which has exclusive access to
769+
// both the `ComponentInstance` and the store.
767770
unsafe { &mut (*self.store()) }
768771
.store_opaque_mut()
769772
.component_resource_state()
@@ -779,6 +782,9 @@ impl ComponentInstance {
779782
let call_context = Some(
780783
// SAFETY: This `ComponentInstance` belongs to the store in
781784
// which it resides, so if it is valid then so is its store.
785+
// Furthermore, this function is only called (transitively) from
786+
// `ComponentInstance::poll_until`, which has exclusive access
787+
// to both the `ComponentInstance` and the store.
782788
unsafe { &mut (*self.store()) }
783789
.component_resource_state()
784790
.0
@@ -962,6 +968,9 @@ impl ComponentInstance {
962968
Box::new(move |instance: &mut ComponentInstance| {
963969
// SAFETY: This `ComponentInstance` belongs to the store in
964970
// which it resides, so if it is valid then so is its store.
971+
// Furthermore, this closure is only called (transitively) from
972+
// `ComponentInstance::poll_until`, which has exclusive access
973+
// to both the `ComponentInstance` and the store.
965974
//
966975
// In addition, the store's data type is known to be `T` because
967976
// this closure will have been called with the same
@@ -1126,6 +1135,9 @@ impl ComponentInstance {
11261135
Box::new(move |instance, dst| {
11271136
// SAFETY: This `ComponentInstance` belongs to the store in
11281137
// which it resides, so if it is valid then so is its store.
1138+
// Furthermore, this closure is only called (transitively) from
1139+
// `ComponentInstance::poll_until`, which has exclusive access
1140+
// to both the `ComponentInstance` and the store.
11291141
//
11301142
// In addition, the store's data type is known to be `T` because
11311143
// this closure will have been called with the same
@@ -1250,7 +1262,10 @@ impl ComponentInstance {
12501262
handle: u32,
12511263
) -> Result<u32> {
12521264
// SAFETY: This `ComponentInstance` belongs to the store in which it
1253-
// resides, so if it is valid then so is its store.
1265+
// resides, so if it is valid then so is its store. Furthermore, this
1266+
// function is only called (transitively) from
1267+
// `ComponentInstance::poll_until`, which has exclusive access to both
1268+
// the `ComponentInstance` and the store.
12541269
//
12551270
// In addition, the store's data type is known to be `T` because this
12561271
// function will have been called with the same `ComponentInstance` that
@@ -1822,10 +1837,14 @@ impl ComponentInstance {
18221837
// smuggling it as a `VMStoreRawPtr` in order to ensure the future is
18231838
// `Send`.
18241839
//
1840+
// By the time the future returned by `poll_fn` completes, we'll have
1841+
// exclusive access to it again.
1842+
//
18251843
// SAFETY: This `ComponentInstance` belongs to the store in which it
1826-
// resides, so if it is valid then so is its store. By the time the
1827-
// future returned by `poll_fn` completes, we'll have exclusive access
1828-
// to it again.
1844+
// resides, so if it is valid then so is its store. Furthermore, this
1845+
// function is only called (transitively) from
1846+
// `ComponentInstance::poll_until`, which has exclusive access to both
1847+
// the `ComponentInstance` and the store.
18291848
let fiber = unsafe {
18301849
poll_fn(
18311850
VMStoreRawPtr(NonNull::new(self.store()).unwrap()),
@@ -2076,7 +2095,10 @@ impl ComponentInstance {
20762095
status: Status,
20772096
) -> Result<()> {
20782097
// SAFETY: This `ComponentInstance` belongs to the store in which it
2079-
// resides, so if it is valid then so is its store.
2098+
// resides, so if it is valid then so is its store. Furthermore, this
2099+
// function is only called (transitively) from
2100+
// `ComponentInstance::poll_until`, which has exclusive access to both
2101+
// the `ComponentInstance` and the store.
20802102
let (calls, host_table, _) = unsafe { &mut *self.store() }
20812103
.store_opaque_mut()
20822104
.component_resource_state();
@@ -2232,8 +2254,12 @@ impl ComponentInstance {
22322254
let event = self.get_event(guest_task, params.caller_instance, Some(params.set))?;
22332255

22342256
// SAFETY: This `ComponentInstance` belongs to the store in
2235-
// which it resides, so if it is valid then so is its store. In
2236-
// addition, `params.memory` is a valid `*mut
2257+
// which it resides, so if it is valid then so is its store.
2258+
// Furthermore, this function is only called (transitively) from
2259+
// `ComponentInstance::poll_until`, which has exclusive access
2260+
// to both the `ComponentInstance` and the store.
2261+
//
2262+
// In addition, `params.memory` is a valid `*mut
22372263
// VMMemoryDefinition` passed to this intrinsic via
22382264
// `wasmtime_cranelift`-generated code.
22392265
let store_and_options = |me: &mut Self| unsafe {
@@ -3013,20 +3039,25 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
30133039
future: u32,
30143040
address: u32,
30153041
) -> Result<u32> {
3016-
instance
3017-
.guest_write(
3018-
StoreContextMut(self),
3019-
memory,
3020-
realloc,
3021-
string_encoding,
3022-
async_,
3023-
TableIndex::Future(ty),
3024-
None,
3025-
future,
3026-
address,
3027-
1,
3028-
)
3029-
.map(|result| result.encode())
3042+
// SAFETY: This function is only called from
3043+
// `wasmtime-cranelift`-generated guest code, which ensures that
3044+
// `instance` belongs to `self`, to which we have (and may confer)
3045+
// exclusive access in the following call.
3046+
unsafe {
3047+
instance
3048+
.guest_write::<T>(
3049+
memory,
3050+
realloc,
3051+
string_encoding,
3052+
async_,
3053+
TableIndex::Future(ty),
3054+
None,
3055+
future,
3056+
address,
3057+
1,
3058+
)
3059+
.map(|result| result.encode())
3060+
}
30303061
}
30313062

30323063
fn future_read(
@@ -3040,20 +3071,22 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
30403071
future: u32,
30413072
address: u32,
30423073
) -> Result<u32> {
3043-
instance
3044-
.guest_read(
3045-
StoreContextMut(self),
3046-
memory,
3047-
realloc,
3048-
string_encoding,
3049-
async_,
3050-
TableIndex::Future(ty),
3051-
None,
3052-
future,
3053-
address,
3054-
1,
3055-
)
3056-
.map(|result| result.encode())
3074+
// SAFETY: See corresponding comment in `Self::future_write`.
3075+
unsafe {
3076+
instance
3077+
.guest_read::<T>(
3078+
memory,
3079+
realloc,
3080+
string_encoding,
3081+
async_,
3082+
TableIndex::Future(ty),
3083+
None,
3084+
future,
3085+
address,
3086+
1,
3087+
)
3088+
.map(|result| result.encode())
3089+
}
30573090
}
30583091

30593092
fn stream_write(
@@ -3068,20 +3101,22 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
30683101
address: u32,
30693102
count: u32,
30703103
) -> Result<u32> {
3071-
instance
3072-
.guest_write(
3073-
StoreContextMut(self),
3074-
memory,
3075-
realloc,
3076-
string_encoding,
3077-
async_,
3078-
TableIndex::Stream(ty),
3079-
None,
3080-
stream,
3081-
address,
3082-
count,
3083-
)
3084-
.map(|result| result.encode())
3104+
// SAFETY: See corresponding comment in `Self::future_write`.
3105+
unsafe {
3106+
instance
3107+
.guest_write::<T>(
3108+
memory,
3109+
realloc,
3110+
string_encoding,
3111+
async_,
3112+
TableIndex::Stream(ty),
3113+
None,
3114+
stream,
3115+
address,
3116+
count,
3117+
)
3118+
.map(|result| result.encode())
3119+
}
30853120
}
30863121

30873122
fn stream_read(
@@ -3096,20 +3131,22 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
30963131
address: u32,
30973132
count: u32,
30983133
) -> Result<u32> {
3099-
instance
3100-
.guest_read(
3101-
StoreContextMut(self),
3102-
memory,
3103-
realloc,
3104-
string_encoding,
3105-
async_,
3106-
TableIndex::Stream(ty),
3107-
None,
3108-
stream,
3109-
address,
3110-
count,
3111-
)
3112-
.map(|result| result.encode())
3134+
// SAFETY: See corresponding comment in `Self::future_write`.
3135+
unsafe {
3136+
instance
3137+
.guest_read::<T>(
3138+
memory,
3139+
realloc,
3140+
string_encoding,
3141+
async_,
3142+
TableIndex::Stream(ty),
3143+
None,
3144+
stream,
3145+
address,
3146+
count,
3147+
)
3148+
.map(|result| result.encode())
3149+
}
31133150
}
31143151

31153152
fn flat_stream_write(
@@ -3125,23 +3162,25 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
31253162
address: u32,
31263163
count: u32,
31273164
) -> Result<u32> {
3128-
instance
3129-
.guest_write(
3130-
StoreContextMut(self),
3131-
memory,
3132-
realloc,
3133-
StringEncoding::Utf8 as u8,
3134-
async_,
3135-
TableIndex::Stream(ty),
3136-
Some(FlatAbi {
3137-
size: payload_size,
3138-
align: payload_align,
3139-
}),
3140-
stream,
3141-
address,
3142-
count,
3143-
)
3144-
.map(|result| result.encode())
3165+
// SAFETY: See corresponding comment in `Self::future_write`.
3166+
unsafe {
3167+
instance
3168+
.guest_write::<T>(
3169+
memory,
3170+
realloc,
3171+
StringEncoding::Utf8 as u8,
3172+
async_,
3173+
TableIndex::Stream(ty),
3174+
Some(FlatAbi {
3175+
size: payload_size,
3176+
align: payload_align,
3177+
}),
3178+
stream,
3179+
address,
3180+
count,
3181+
)
3182+
.map(|result| result.encode())
3183+
}
31453184
}
31463185

31473186
fn flat_stream_read(
@@ -3157,23 +3196,25 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
31573196
address: u32,
31583197
count: u32,
31593198
) -> Result<u32> {
3160-
instance
3161-
.guest_read(
3162-
StoreContextMut(self),
3163-
memory,
3164-
realloc,
3165-
StringEncoding::Utf8 as u8,
3166-
async_,
3167-
TableIndex::Stream(ty),
3168-
Some(FlatAbi {
3169-
size: payload_size,
3170-
align: payload_align,
3171-
}),
3172-
stream,
3173-
address,
3174-
count,
3175-
)
3176-
.map(|result| result.encode())
3199+
// SAFETY: See corresponding comment in `Self::future_write`.
3200+
unsafe {
3201+
instance
3202+
.guest_read::<T>(
3203+
memory,
3204+
realloc,
3205+
StringEncoding::Utf8 as u8,
3206+
async_,
3207+
TableIndex::Stream(ty),
3208+
Some(FlatAbi {
3209+
size: payload_size,
3210+
align: payload_align,
3211+
}),
3212+
stream,
3213+
address,
3214+
count,
3215+
)
3216+
.map(|result| result.encode())
3217+
}
31773218
}
31783219

31793220
fn error_context_debug_message(
@@ -3186,15 +3227,17 @@ unsafe impl<T> VMComponentAsyncStore for StoreInner<T> {
31863227
err_ctx_handle: u32,
31873228
debug_msg_address: u32,
31883229
) -> Result<()> {
3189-
instance.error_context_debug_message(
3190-
StoreContextMut(self),
3191-
memory,
3192-
realloc,
3193-
string_encoding,
3194-
ty,
3195-
err_ctx_handle,
3196-
debug_msg_address,
3197-
)
3230+
// SAFETY: See corresponding comment in `Self::future_write`.
3231+
unsafe {
3232+
instance.error_context_debug_message::<T>(
3233+
memory,
3234+
realloc,
3235+
string_encoding,
3236+
ty,
3237+
err_ctx_handle,
3238+
debug_msg_address,
3239+
)
3240+
}
31983241
}
31993242
}
32003243

@@ -4253,9 +4296,11 @@ pub(crate) unsafe fn prepare_call<T: Send, R>(
42534296
// gracefully cancel the call without trapping or panicking.
42544297
todo!("gracefully cancel `call_async` tasks when future is dropped")
42554298
} else {
4256-
// SAFETY: The provided `ComponentInstance` belongs to the
4257-
// store in which it resides, so if it is valid then so is
4258-
// its store.
4299+
// SAFETY: This `ComponentInstance` belongs to the store in
4300+
// which it resides, so if it is valid then so is its store.
4301+
// Furthermore, this closure is only called (transitively)
4302+
// from `ComponentInstance::poll_until`, which has exclusive
4303+
// access to both the `ComponentInstance` and the store.
42594304
//
42604305
// Also, per the contract of `prepare_call`, `ptr` must be
42614306
// valid and `lower_params` must either use it safely or not at
@@ -4268,8 +4313,11 @@ pub(crate) unsafe fn prepare_call<T: Send, R>(
42684313
})),
42694314
LiftResult {
42704315
lift: Box::new(for_any_lift(move |instance, result| {
4271-
// SAFETY: The provided `ComponentInstance` belongs to the store
4272-
// in which it resides, so if it is valid then so is its store.
4316+
// SAFETY: This `ComponentInstance` belongs to the store in
4317+
// which it resides, so if it is valid then so is its store.
4318+
// Furthermore, this closure is only called (transitively) from
4319+
// `ComponentInstance::poll_until`, which has exclusive access
4320+
// to both the `ComponentInstance` and the store.
42734321
unsafe { lift_result(handle, instance.store(), result) }
42744322
})),
42754323
ty: task_return_type,

0 commit comments

Comments
 (0)