Skip to content

Commit 1dae3da

Browse files
authored
Implement waitable-sets (bytecodealliance#2068)
This commit catches up with WebAssembly/component-model#438 with respect to the addition of `waitable-set` pseudo-resources and new intrinsics. The old `task.wait` and `task.poll` intrinsics are renamed/repurposed under these new names along with some other management intrinsics for `waitable-set`s.
1 parent a4b41c6 commit 1dae3da

File tree

28 files changed

+979
-578
lines changed

28 files changed

+979
-578
lines changed

crates/wasm-encoder/src/component/builder.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -407,18 +407,6 @@ impl ComponentBuilder {
407407
inc(&mut self.core_funcs)
408408
}
409409

410-
/// Declares a new `task.wait` intrinsic.
411-
pub fn task_wait(&mut self, async_: bool, memory: u32) -> u32 {
412-
self.canonical_functions().task_wait(async_, memory);
413-
inc(&mut self.core_funcs)
414-
}
415-
416-
/// Declares a new `task.poll` intrinsic.
417-
pub fn task_poll(&mut self, async_: bool, memory: u32) -> u32 {
418-
self.canonical_functions().task_poll(async_, memory);
419-
inc(&mut self.core_funcs)
420-
}
421-
422410
/// Declares a new `task.yield` intrinsic.
423411
pub fn task_yield(&mut self, async_: bool) -> u32 {
424412
self.canonical_functions().task_yield(async_);
@@ -558,6 +546,36 @@ impl ComponentBuilder {
558546
inc(&mut self.core_funcs)
559547
}
560548

549+
/// Declares a new `waitable-set.new` intrinsic.
550+
pub fn waitable_set_new(&mut self) -> u32 {
551+
self.canonical_functions().waitable_set_new();
552+
inc(&mut self.core_funcs)
553+
}
554+
555+
/// Declares a new `waitable-set.wait` intrinsic.
556+
pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> u32 {
557+
self.canonical_functions().waitable_set_wait(async_, memory);
558+
inc(&mut self.core_funcs)
559+
}
560+
561+
/// Declares a new `waitable-set.poll` intrinsic.
562+
pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> u32 {
563+
self.canonical_functions().waitable_set_poll(async_, memory);
564+
inc(&mut self.core_funcs)
565+
}
566+
567+
/// Declares a new `waitable-set.drop` intrinsic.
568+
pub fn waitable_set_drop(&mut self) -> u32 {
569+
self.canonical_functions().waitable_set_drop();
570+
inc(&mut self.core_funcs)
571+
}
572+
573+
/// Declares a new `waitable.join` intrinsic.
574+
pub fn waitable_join(&mut self) -> u32 {
575+
self.canonical_functions().waitable_join();
576+
inc(&mut self.core_funcs)
577+
}
578+
561579
/// Adds a new custom section to this component.
562580
pub fn custom_section(&mut self, section: &CustomSection<'_>) {
563581
self.flush();

crates/wasm-encoder/src/component/canonicals.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -200,31 +200,6 @@ impl CanonicalFunctionSection {
200200
self
201201
}
202202

203-
/// Defines a function which waits for at least one outstanding async
204-
/// task/stream/future to make progress, returning the first such event.
205-
///
206-
/// If `async_` is true, the caller instance may be reentered.
207-
pub fn task_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
208-
self.bytes.push(0x0a);
209-
self.bytes.push(if async_ { 1 } else { 0 });
210-
memory.encode(&mut self.bytes);
211-
self.num_added += 1;
212-
self
213-
}
214-
215-
/// Defines a function which checks whether any outstanding async
216-
/// task/stream/future has made progress. Unlike `task.wait`, this does not
217-
/// block and may return nothing if no such event has occurred.
218-
///
219-
/// If `async_` is true, the caller instance may be reentered.
220-
pub fn task_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
221-
self.bytes.push(0x0b);
222-
self.bytes.push(if async_ { 1 } else { 0 });
223-
memory.encode(&mut self.bytes);
224-
self.num_added += 1;
225-
self
226-
}
227-
228203
/// Defines a function which yields control to the host so that other tasks
229204
/// are able to make progress, if any.
230205
///
@@ -425,6 +400,50 @@ impl CanonicalFunctionSection {
425400
self
426401
}
427402

403+
/// Declare a new `waitable-set.new` intrinsic, used to create a
404+
/// `waitable-set` pseudo-resource.
405+
pub fn waitable_set_new(&mut self) -> &mut Self {
406+
self.bytes.push(0x1f);
407+
self.num_added += 1;
408+
self
409+
}
410+
411+
/// Declare a new `waitable-set.wait` intrinsic, used to block on a
412+
/// `waitable-set`.
413+
pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
414+
self.bytes.push(0x20);
415+
self.bytes.push(if async_ { 1 } else { 0 });
416+
memory.encode(&mut self.bytes);
417+
self.num_added += 1;
418+
self
419+
}
420+
421+
/// Declare a new `waitable-set.wait` intrinsic, used to check, without
422+
/// blocking, if anything in a `waitable-set` is ready.
423+
pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
424+
self.bytes.push(0x21);
425+
self.bytes.push(if async_ { 1 } else { 0 });
426+
memory.encode(&mut self.bytes);
427+
self.num_added += 1;
428+
self
429+
}
430+
431+
/// Declare a new `waitable-set.drop` intrinsic, used to dispose a
432+
/// `waitable-set` pseudo-resource.
433+
pub fn waitable_set_drop(&mut self) -> &mut Self {
434+
self.bytes.push(0x22);
435+
self.num_added += 1;
436+
self
437+
}
438+
439+
/// Declare a new `waitable.join` intrinsic, used to add an item to a
440+
/// `waitable-set`.
441+
pub fn waitable_join(&mut self) -> &mut Self {
442+
self.bytes.push(0x23);
443+
self.num_added += 1;
444+
self
445+
}
446+
428447
fn encode_options<O>(&mut self, options: O) -> &mut Self
429448
where
430449
O: IntoIterator<Item = CanonicalOption>,

crates/wasm-encoder/src/reencode/component.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -969,12 +969,6 @@ pub mod component_utils {
969969
options.iter().map(|o| reencoder.canonical_option(*o)),
970970
);
971971
}
972-
wasmparser::CanonicalFunction::TaskWait { async_, memory } => {
973-
section.task_wait(async_, reencoder.memory_index(memory));
974-
}
975-
wasmparser::CanonicalFunction::TaskPoll { async_, memory } => {
976-
section.task_poll(async_, reencoder.memory_index(memory));
977-
}
978972
wasmparser::CanonicalFunction::TaskYield { async_ } => {
979973
section.task_yield(async_);
980974
}
@@ -1046,6 +1040,21 @@ pub mod component_utils {
10461040
wasmparser::CanonicalFunction::ErrorContextDrop => {
10471041
section.error_context_drop();
10481042
}
1043+
wasmparser::CanonicalFunction::WaitableSetNew => {
1044+
section.waitable_set_new();
1045+
}
1046+
wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
1047+
section.waitable_set_wait(async_, reencoder.memory_index(memory));
1048+
}
1049+
wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
1050+
section.waitable_set_poll(async_, reencoder.memory_index(memory));
1051+
}
1052+
wasmparser::CanonicalFunction::WaitableSetDrop => {
1053+
section.waitable_set_drop();
1054+
}
1055+
wasmparser::CanonicalFunction::WaitableJoin => {
1056+
section.waitable_join();
1057+
}
10491058
}
10501059
Ok(())
10511060
}

crates/wasmparser/src/readers/component/canonicals.rs

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -90,23 +90,6 @@ pub enum CanonicalFunction {
9090
/// The canonical options for the function.
9191
options: Box<[CanonicalOption]>,
9292
},
93-
/// A function which waits for at least one outstanding async
94-
/// task/stream/future to make progress, returning the first such event.
95-
TaskWait {
96-
/// If `true`, indicates the caller instance maybe reentered.
97-
async_: bool,
98-
/// Memory to use when storing the event.
99-
memory: u32,
100-
},
101-
/// A function which checks whether any outstanding async task/stream/future
102-
/// has made progress. Unlike `task.wait`, this does not block and may
103-
/// return nothing if no such event has occurred.
104-
TaskPoll {
105-
/// If `true`, indicates the caller instance maybe reentered.
106-
async_: bool,
107-
/// Memory to use when storing the event, if any.
108-
memory: u32,
109-
},
11093
/// A function which yields control to the host so that other tasks are able
11194
/// to make progress, if any.
11295
TaskYield {
@@ -233,6 +216,28 @@ pub enum CanonicalFunction {
233216
},
234217
/// A function to drop a specified `error-context`.
235218
ErrorContextDrop,
219+
/// A function to create a new `waitable-set`.
220+
WaitableSetNew,
221+
/// A function to block on the next item within a `waitable-set`.
222+
WaitableSetWait {
223+
/// Whether or not the guest can be reentered while calling this
224+
/// function.
225+
async_: bool,
226+
/// Which memory the results of this operation are stored in.
227+
memory: u32,
228+
},
229+
/// A function to check if any items are ready within a `waitable-set`.
230+
WaitableSetPoll {
231+
/// Whether or not the guest can be reentered while calling this
232+
/// function.
233+
async_: bool,
234+
/// Which memory the results of this operation are stored in.
235+
memory: u32,
236+
},
237+
/// A function to drop a `waitable-set`.
238+
WaitableSetDrop,
239+
/// A function to add an item to a `waitable-set`.
240+
WaitableJoin,
236241
}
237242

238243
/// A reader for the canonical section of a WebAssembly component.
@@ -277,14 +282,6 @@ impl<'a> FromReader<'a> for CanonicalFunction {
277282
result: crate::read_resultlist(reader)?,
278283
options: read_opts(reader)?,
279284
},
280-
0x0a => CanonicalFunction::TaskWait {
281-
async_: reader.read()?,
282-
memory: reader.read()?,
283-
},
284-
0x0b => CanonicalFunction::TaskPoll {
285-
async_: reader.read()?,
286-
memory: reader.read()?,
287-
},
288285
0x0c => CanonicalFunction::TaskYield {
289286
async_: reader.read()?,
290287
},
@@ -334,6 +331,18 @@ impl<'a> FromReader<'a> for CanonicalFunction {
334331
options: read_opts(reader)?,
335332
},
336333
0x1e => CanonicalFunction::ErrorContextDrop,
334+
335+
0x1f => CanonicalFunction::WaitableSetNew,
336+
0x20 => CanonicalFunction::WaitableSetWait {
337+
async_: reader.read()?,
338+
memory: reader.read()?,
339+
},
340+
0x21 => CanonicalFunction::WaitableSetPoll {
341+
async_: reader.read()?,
342+
memory: reader.read()?,
343+
},
344+
0x22 => CanonicalFunction::WaitableSetDrop,
345+
0x23 => CanonicalFunction::WaitableJoin,
337346
x => return reader.invalid_leading_byte(x, "canonical function"),
338347
})
339348
}

crates/wasmparser/src/validator.rs

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,110 +1272,7 @@ impl Validator {
12721272
},
12731273
|components, types, features, func, offset| {
12741274
let current = components.last_mut().unwrap();
1275-
match func {
1276-
crate::CanonicalFunction::Lift {
1277-
core_func_index,
1278-
type_index,
1279-
options,
1280-
} => current.lift_function(
1281-
core_func_index,
1282-
type_index,
1283-
&options,
1284-
types,
1285-
offset,
1286-
features,
1287-
),
1288-
crate::CanonicalFunction::Lower {
1289-
func_index,
1290-
options,
1291-
} => current.lower_function(func_index, &options, types, offset, features),
1292-
crate::CanonicalFunction::ResourceNew { resource } => {
1293-
current.resource_new(resource, types, offset)
1294-
}
1295-
crate::CanonicalFunction::ResourceDrop { resource } => {
1296-
current.resource_drop(resource, types, offset)
1297-
}
1298-
crate::CanonicalFunction::ResourceDropAsync { resource } => {
1299-
current.resource_drop_async(resource, types, offset, features)
1300-
}
1301-
crate::CanonicalFunction::ResourceRep { resource } => {
1302-
current.resource_rep(resource, types, offset)
1303-
}
1304-
crate::CanonicalFunction::ThreadSpawn { func_ty_index } => {
1305-
current.thread_spawn(func_ty_index, types, offset, features)
1306-
}
1307-
crate::CanonicalFunction::ThreadAvailableParallelism => {
1308-
current.thread_available_parallelism(types, offset, features)
1309-
}
1310-
crate::CanonicalFunction::BackpressureSet => {
1311-
current.backpressure_set(types, offset, features)
1312-
}
1313-
crate::CanonicalFunction::TaskReturn { result, options } => {
1314-
current.task_return(&result, &options, types, offset, features)
1315-
}
1316-
crate::CanonicalFunction::TaskWait { async_, memory } => {
1317-
current.task_wait(async_, memory, types, offset, features)
1318-
}
1319-
crate::CanonicalFunction::TaskPoll { async_, memory } => {
1320-
current.task_poll(async_, memory, types, offset, features)
1321-
}
1322-
crate::CanonicalFunction::TaskYield { async_ } => {
1323-
current.task_yield(async_, types, offset, features)
1324-
}
1325-
crate::CanonicalFunction::SubtaskDrop => {
1326-
current.subtask_drop(types, offset, features)
1327-
}
1328-
crate::CanonicalFunction::StreamNew { ty } => {
1329-
current.stream_new(ty, types, offset, features)
1330-
}
1331-
crate::CanonicalFunction::StreamRead { ty, options } => {
1332-
current.stream_read(ty, &options, types, offset, features)
1333-
}
1334-
crate::CanonicalFunction::StreamWrite { ty, options } => {
1335-
current.stream_write(ty, &options, types, offset, features)
1336-
}
1337-
crate::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1338-
current.stream_cancel_read(ty, async_, types, offset, features)
1339-
}
1340-
crate::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1341-
current.stream_cancel_write(ty, async_, types, offset, features)
1342-
}
1343-
crate::CanonicalFunction::StreamCloseReadable { ty } => {
1344-
current.stream_close_readable(ty, types, offset, features)
1345-
}
1346-
crate::CanonicalFunction::StreamCloseWritable { ty } => {
1347-
current.stream_close_writable(ty, types, offset, features)
1348-
}
1349-
crate::CanonicalFunction::FutureNew { ty } => {
1350-
current.future_new(ty, types, offset, features)
1351-
}
1352-
crate::CanonicalFunction::FutureRead { ty, options } => {
1353-
current.future_read(ty, &options, types, offset, features)
1354-
}
1355-
crate::CanonicalFunction::FutureWrite { ty, options } => {
1356-
current.future_write(ty, options.into_vec(), types, offset, features)
1357-
}
1358-
crate::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1359-
current.future_cancel_read(ty, async_, types, offset, features)
1360-
}
1361-
crate::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1362-
current.future_cancel_write(ty, async_, types, offset, features)
1363-
}
1364-
crate::CanonicalFunction::FutureCloseReadable { ty } => {
1365-
current.future_close_readable(ty, types, offset, features)
1366-
}
1367-
crate::CanonicalFunction::FutureCloseWritable { ty } => {
1368-
current.future_close_writable(ty, types, offset, features)
1369-
}
1370-
crate::CanonicalFunction::ErrorContextNew { options } => {
1371-
current.error_context_new(options.into_vec(), types, offset, features)
1372-
}
1373-
crate::CanonicalFunction::ErrorContextDebugMessage { options } => current
1374-
.error_context_debug_message(options.into_vec(), types, offset, features),
1375-
crate::CanonicalFunction::ErrorContextDrop => {
1376-
current.error_context_drop(types, offset, features)
1377-
}
1378-
}
1275+
current.canonical_function(func, types, offset, features)
13791276
},
13801277
)
13811278
}

0 commit comments

Comments
 (0)