Skip to content

Commit a2d6b03

Browse files
authored
rust: Store raw intrinsics in vtables (#1187)
Instead of generating a wrapper-per-intrinsic try to instead store raw functions inside of vtables to push as much code as possible into `mod async_support`, as it's generally easier to grok code in one location rather than generated code. Note that this does not update the `read` or `write` vtable functions as they're going to be trickier, if even possible, to expose the more raw version. This shouldn't have any functional change, it's just a reorganizing. The `cancel_*` intrinsics are all marked with a `TODO`, however, to come back and reconsider the return value which is otherwise discarded right now.
1 parent ccebf1d commit a2d6b03

File tree

5 files changed

+162
-268
lines changed

5 files changed

+162
-268
lines changed

crates/guest-rust/rt/src/async_support.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ mod future_support;
2525
mod stream_support;
2626

2727
pub use {
28-
future_support::{FutureReader, FutureVtable, FutureWriter},
29-
stream_support::{StreamReader, StreamVtable, StreamWriter},
28+
future_support::{future_new, FutureReader, FutureVtable, FutureWriter},
29+
stream_support::{stream_new, StreamReader, StreamVtable, StreamWriter},
3030
};
3131

3232
pub use futures;

crates/guest-rust/rt/src/async_support/future_support.rs

+41-14
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,29 @@ use {
2222
pub struct FutureVtable<T> {
2323
pub write: fn(future: u32, value: T) -> Pin<Box<dyn Future<Output = bool>>>,
2424
pub read: fn(future: u32) -> Pin<Box<dyn Future<Output = Option<Result<T, ErrorContext>>>>>,
25-
pub cancel_write: fn(future: u32),
26-
pub cancel_read: fn(future: u32),
27-
pub close_writable: fn(future: u32, err_ctx: u32),
28-
pub close_readable: fn(future: u32),
25+
pub cancel_write: unsafe extern "C" fn(future: u32) -> u32,
26+
pub cancel_read: unsafe extern "C" fn(future: u32) -> u32,
27+
pub close_writable: unsafe extern "C" fn(future: u32, err_ctx: u32),
28+
pub close_readable: unsafe extern "C" fn(future: u32),
29+
pub new: unsafe extern "C" fn() -> u32,
30+
}
31+
32+
/// Helper function to create a new read/write pair for a component model
33+
/// future.
34+
pub unsafe fn future_new<T>(
35+
vtable: &'static FutureVtable<T>,
36+
) -> (FutureWriter<T>, FutureReader<T>) {
37+
let handle = unsafe { (vtable.new)() };
38+
super::with_entry(handle, |entry| match entry {
39+
Entry::Vacant(entry) => {
40+
entry.insert(Handle::LocalOpen);
41+
}
42+
Entry::Occupied(_) => unreachable!(),
43+
});
44+
(
45+
FutureWriter::new(handle, vtable),
46+
FutureReader::new(handle, vtable),
47+
)
2948
}
3049

3150
/// Represents the writable end of a Component Model `future`.
@@ -84,7 +103,11 @@ impl<T> CancelableWrite<T> {
84103
Handle::LocalReady(..) => {
85104
entry.insert(Handle::LocalOpen);
86105
}
87-
Handle::Write => (writer.vtable.cancel_write)(writer.handle),
106+
Handle::Write => unsafe {
107+
// TODO: spec-wise this can return `BLOCKED` which seems
108+
// bad?
109+
(writer.vtable.cancel_write)(writer.handle);
110+
},
88111
},
89112
});
90113
writer
@@ -179,17 +202,17 @@ impl<T> Drop for FutureWriter<T> {
179202
entry.insert(Handle::LocalClosed);
180203
}
181204
Handle::Read => unreachable!(),
182-
Handle::Write | Handle::LocalClosed => {
205+
Handle::Write | Handle::LocalClosed => unsafe {
183206
entry.remove();
184207
(self.vtable.close_writable)(self.handle, 0);
185-
}
208+
},
186209
Handle::WriteClosedErr(_) => match entry.remove() {
187-
Handle::WriteClosedErr(None) => {
210+
Handle::WriteClosedErr(None) => unsafe {
188211
(self.vtable.close_writable)(self.handle, 0);
189-
}
190-
Handle::WriteClosedErr(Some(err_ctx)) => {
212+
},
213+
Handle::WriteClosedErr(Some(err_ctx)) => unsafe {
191214
(self.vtable.close_writable)(self.handle, err_ctx.handle());
192-
}
215+
},
193216
_ => unreachable!(),
194217
},
195218
},
@@ -240,7 +263,11 @@ impl<T> CancelableRead<T> {
240263
Handle::LocalWaiting(_) => {
241264
entry.insert(Handle::LocalOpen);
242265
}
243-
Handle::Read => (reader.vtable.cancel_read)(handle),
266+
Handle::Read => unsafe {
267+
// TODO: spec-wise this can return `BLOCKED` which seems
268+
// bad?
269+
(reader.vtable.cancel_read)(handle);
270+
},
244271
},
245272
});
246273
reader
@@ -389,10 +416,10 @@ impl<T> Drop for FutureReader<T> {
389416
Handle::LocalOpen | Handle::LocalWaiting(_) => {
390417
entry.insert(Handle::LocalClosed);
391418
}
392-
Handle::Read | Handle::LocalClosed => {
419+
Handle::Read | Handle::LocalClosed => unsafe {
393420
entry.remove();
394421
(self.vtable.close_readable)(handle);
395-
}
422+
},
396423
Handle::Write | Handle::WriteClosedErr(_) => unreachable!(),
397424
},
398425
});

crates/guest-rust/rt/src/async_support/stream_support.rs

+41-13
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,30 @@ pub struct StreamVtable<T> {
3535
future: u32,
3636
values: &mut [MaybeUninit<T>],
3737
) -> Pin<Box<dyn Future<Output = Option<Result<usize, ErrorContext>>> + '_>>,
38-
pub cancel_write: fn(future: u32),
39-
pub cancel_read: fn(future: u32),
40-
pub close_writable: fn(future: u32, err_ctx: u32),
41-
pub close_readable: fn(future: u32),
38+
pub cancel_write: unsafe extern "C" fn(future: u32) -> u32,
39+
pub cancel_read: unsafe extern "C" fn(future: u32) -> u32,
40+
pub close_writable: unsafe extern "C" fn(future: u32, err_ctx: u32),
41+
pub close_readable: unsafe extern "C" fn(future: u32),
42+
pub new: unsafe extern "C" fn() -> u32,
4243
}
4344

45+
/// Helper function to create a new read/write pair for a component model
46+
/// stream.
47+
pub unsafe fn stream_new<T>(
48+
vtable: &'static StreamVtable<T>,
49+
) -> (StreamWriter<T>, StreamReader<T>) {
50+
let handle = unsafe { (vtable.new)() };
51+
super::with_entry(handle, |entry| match entry {
52+
Entry::Vacant(entry) => {
53+
entry.insert(Handle::LocalOpen);
54+
}
55+
Entry::Occupied(_) => unreachable!(),
56+
});
57+
(
58+
StreamWriter::new(handle, vtable),
59+
StreamReader::new(handle, vtable),
60+
)
61+
}
4462
struct CancelWriteOnDrop<T: 'static> {
4563
handle: Option<u32>,
4664
vtable: &'static StreamVtable<T>,
@@ -60,7 +78,11 @@ impl<T> Drop for CancelWriteOnDrop<T> {
6078
Handle::LocalReady(..) => {
6179
entry.insert(Handle::LocalOpen);
6280
}
63-
Handle::Write => (self.vtable.cancel_write)(handle),
81+
Handle::Write => unsafe {
82+
// TODO: spec-wise this can return `BLOCKED` which seems
83+
// bad?
84+
(self.vtable.cancel_write)(handle);
85+
},
6486
},
6587
});
6688
}
@@ -221,18 +243,20 @@ impl<T> Drop for StreamWriter<T> {
221243
entry.insert(Handle::LocalClosed);
222244
}
223245
Handle::Read => unreachable!(),
224-
Handle::Write | Handle::LocalClosed => {
246+
Handle::Write | Handle::LocalClosed => unsafe {
225247
entry.remove();
226248
(self.vtable.close_writable)(self.handle, 0);
227-
}
249+
},
228250
Handle::WriteClosedErr(_) => match entry.remove() {
229251
// Care is taken to avoid dropping the ErrorContext before close_writable is called.
230252
// If the error context is dropped prematurely, the component may garbage collect
231253
// the error context before it can be used/referenced by close_writable().
232-
Handle::WriteClosedErr(Some(e)) => {
254+
Handle::WriteClosedErr(Some(e)) => unsafe {
233255
(self.vtable.close_writable)(self.handle, e.handle)
234-
}
235-
Handle::WriteClosedErr(None) => (self.vtable.close_writable)(self.handle, 0),
256+
},
257+
Handle::WriteClosedErr(None) => unsafe {
258+
(self.vtable.close_writable)(self.handle, 0)
259+
},
236260
_ => unreachable!(),
237261
},
238262
},
@@ -259,7 +283,11 @@ impl<T> Drop for CancelReadOnDrop<T> {
259283
Handle::LocalWaiting(_) => {
260284
entry.insert(Handle::LocalOpen);
261285
}
262-
Handle::Read => (self.vtable.cancel_read)(handle),
286+
Handle::Read => unsafe {
287+
// TODO: spec-wise this can return `BLOCKED` which seems
288+
// bad?
289+
(self.vtable.cancel_read)(handle);
290+
},
263291
},
264292
});
265293
}
@@ -457,10 +485,10 @@ impl<T> Drop for StreamReader<T> {
457485
Handle::LocalOpen | Handle::LocalWaiting(_) => {
458486
entry.insert(Handle::LocalClosed);
459487
}
460-
Handle::Read | Handle::LocalClosed => {
488+
Handle::Read | Handle::LocalClosed => unsafe {
461489
entry.remove();
462490
(self.vtable.close_readable)(handle);
463-
}
491+
},
464492
Handle::Write | Handle::WriteClosedErr(_) => unreachable!(),
465493
},
466494
});

0 commit comments

Comments
 (0)