Skip to content

Commit 2357916

Browse files
committed
add component-model-async/task-builtins.wast test
This is another piece of bytecodealliance#9582 which I'm splitting out to make review easier. This test includes components which use the `task.backpressure`, `task.return`, `task.wait`, `task.poll`, `task.yield`, and `subtask.drop` builtins. The rest of the changes fill in some TODOs to make the test pass. Signed-off-by: Joel Dice <[email protected]>
1 parent 098bd1c commit 2357916

File tree

6 files changed

+375
-56
lines changed

6 files changed

+375
-56
lines changed

crates/cranelift/src/compiler/component.rs

+120-55
Original file line numberDiff line numberDiff line change
@@ -95,34 +95,25 @@ impl<'a> TrampolineCompiler<'a> {
9595
self.translate_always_trap();
9696
}
9797
Trampoline::TaskBackpressure { instance } => {
98-
_ = instance;
99-
todo!()
98+
self.translate_task_backpressure_call(*instance)
10099
}
101100
Trampoline::TaskReturn => self.translate_task_return_call(),
102101
Trampoline::TaskWait {
103102
instance,
104103
async_,
105104
memory,
106105
} => {
107-
_ = (instance, async_, memory);
108-
todo!()
106+
self.translate_task_wait_or_poll_call(*instance, *async_, *memory, host::task_wait)
109107
}
110108
Trampoline::TaskPoll {
111109
instance,
112110
async_,
113111
memory,
114112
} => {
115-
_ = (instance, async_, memory);
116-
todo!()
117-
}
118-
Trampoline::TaskYield { async_ } => {
119-
_ = async_;
120-
todo!()
121-
}
122-
Trampoline::SubtaskDrop { instance } => {
123-
_ = instance;
124-
todo!()
113+
self.translate_task_wait_or_poll_call(*instance, *async_, *memory, host::task_poll)
125114
}
115+
Trampoline::TaskYield { async_ } => self.translate_task_yield_call(*async_),
116+
Trampoline::SubtaskDrop { instance } => self.translate_subtask_drop_call(*instance),
126117
Trampoline::StreamNew { ty } => {
127118
_ = ty;
128119
todo!()
@@ -261,7 +252,16 @@ impl<'a> TrampolineCompiler<'a> {
261252
}
262253
}
263254

264-
fn translate_task_return_call(&mut self) {
255+
fn translate_intrinsic_libcall(
256+
&mut self,
257+
vmctx: ir::Value,
258+
get_libcall: fn(
259+
&dyn TargetIsa,
260+
&mut ir::Function,
261+
) -> (ir::SigRef, ComponentBuiltinFunctionIndex),
262+
args: &[ir::Value],
263+
result: ir::types::Type,
264+
) {
265265
match self.abi {
266266
Abi::Wasm => {}
267267

@@ -273,14 +273,28 @@ impl<'a> TrampolineCompiler<'a> {
273273
}
274274
}
275275

276+
let call = self.call_libcall(vmctx, get_libcall, args);
277+
278+
if result == ir::types::I64 {
279+
let result = self.builder.func.dfg.inst_results(call)[0];
280+
let result = self.raise_if_i32_trapped(result);
281+
self.abi_store_results(&[result]);
282+
} else {
283+
if result != ir::types::I8 {
284+
todo!("support additional intrinsic return types")
285+
}
286+
let succeeded = self.builder.func.dfg.inst_results(call)[0];
287+
self.raise_if_host_trapped(succeeded);
288+
self.builder.ins().return_(&[]);
289+
}
290+
}
291+
292+
fn translate_task_return_call(&mut self) {
276293
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
277294
let vmctx = args[0];
278295

279296
let (values_vec_ptr, values_vec_len) = self.store_wasm_arguments(&args[2..]);
280297

281-
let (host_sig, index) = host::task_return(self.isa, &mut self.builder.func);
282-
let host_fn = self.load_libcall(vmctx, index);
283-
284298
let params = self.types[self.signature]
285299
.unwrap_func()
286300
.params()
@@ -309,16 +323,12 @@ impl<'a> TrampolineCompiler<'a> {
309323
),
310324
);
311325

312-
let call = self.compiler.call_indirect_host(
313-
&mut self.builder,
314-
index,
315-
host_sig,
316-
host_fn,
326+
self.translate_intrinsic_libcall(
327+
vmctx,
328+
host::task_return,
317329
&[vmctx, ty, values_vec_ptr, values_vec_len],
330+
ir::types::I8,
318331
);
319-
let succeeded = self.builder.func.dfg.inst_results(call)[0];
320-
self.raise_if_host_trapped(succeeded);
321-
self.builder.ins().return_(&[]);
322332
}
323333

324334
fn translate_async_enter_or_exit(
@@ -333,23 +343,9 @@ impl<'a> TrampolineCompiler<'a> {
333343
)>,
334344
result: ir::types::Type,
335345
) {
336-
match self.abi {
337-
Abi::Wasm => {}
338-
339-
// These trampolines can only actually be called by Wasm, so
340-
// let's assert that here.
341-
Abi::Array => {
342-
self.builder.ins().trap(TRAP_INTERNAL_ASSERT);
343-
return;
344-
}
345-
}
346-
347346
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
348347
let vmctx = args[0];
349348

350-
let (host_sig, index) = get_libcall(self.isa, &mut self.builder.func);
351-
let host_fn = self.load_libcall(vmctx, index);
352-
353349
let mut callee_args = vec![vmctx];
354350

355351
if let Some((callback, post_return)) = callback_and_post_return {
@@ -383,24 +379,93 @@ impl<'a> TrampolineCompiler<'a> {
383379
// remaining parameters
384380
callee_args.extend(args[2..].iter().copied());
385381

386-
let call = self.compiler.call_indirect_host(
387-
&mut self.builder,
388-
index,
389-
host_sig,
390-
host_fn,
382+
self.translate_intrinsic_libcall(vmctx, get_libcall, &callee_args, result);
383+
}
384+
385+
fn translate_task_backpressure_call(&mut self, caller_instance: RuntimeComponentInstanceIndex) {
386+
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
387+
let vmctx = args[0];
388+
389+
let mut callee_args = vec![
390+
vmctx,
391+
self.builder
392+
.ins()
393+
.iconst(ir::types::I32, i64::from(caller_instance.as_u32())),
394+
];
395+
396+
callee_args.extend(args[2..].iter().copied());
397+
398+
self.translate_intrinsic_libcall(
399+
vmctx,
400+
host::task_backpressure,
391401
&callee_args,
402+
ir::types::I8,
392403
);
404+
}
393405

394-
if result == ir::types::I64 {
395-
let result = self.builder.func.dfg.inst_results(call)[0];
396-
let result = self.raise_if_i32_trapped(result);
397-
self.abi_store_results(&[result]);
398-
} else {
399-
assert!(result == ir::types::I8);
400-
let succeeded = self.builder.func.dfg.inst_results(call)[0];
401-
self.raise_if_host_trapped(succeeded);
402-
self.builder.ins().return_(&[]);
403-
}
406+
fn translate_task_wait_or_poll_call(
407+
&mut self,
408+
caller_instance: RuntimeComponentInstanceIndex,
409+
async_: bool,
410+
memory: RuntimeMemoryIndex,
411+
get_libcall: fn(
412+
&dyn TargetIsa,
413+
&mut ir::Function,
414+
) -> (ir::SigRef, ComponentBuiltinFunctionIndex),
415+
) {
416+
let pointer_type = self.isa.pointer_type();
417+
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
418+
let vmctx = args[0];
419+
420+
let mut callee_args = vec![
421+
vmctx,
422+
self.builder
423+
.ins()
424+
.iconst(ir::types::I32, i64::from(caller_instance.as_u32())),
425+
self.builder
426+
.ins()
427+
.iconst(ir::types::I8, if async_ { 1 } else { 0 }),
428+
self.builder.ins().load(
429+
pointer_type,
430+
MemFlags::trusted(),
431+
vmctx,
432+
i32::try_from(self.offsets.runtime_memory(memory)).unwrap(),
433+
),
434+
];
435+
436+
callee_args.extend(args[2..].iter().copied());
437+
438+
self.translate_intrinsic_libcall(vmctx, get_libcall, &callee_args, ir::types::I64);
439+
}
440+
441+
fn translate_task_yield_call(&mut self, async_: bool) {
442+
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
443+
let vmctx = args[0];
444+
445+
let callee_args = [
446+
vmctx,
447+
self.builder
448+
.ins()
449+
.iconst(ir::types::I8, if async_ { 1 } else { 0 }),
450+
];
451+
452+
self.translate_intrinsic_libcall(vmctx, host::task_yield, &callee_args, ir::types::I8);
453+
}
454+
455+
fn translate_subtask_drop_call(&mut self, caller_instance: RuntimeComponentInstanceIndex) {
456+
let args = self.builder.func.dfg.block_params(self.block0).to_vec();
457+
let vmctx = args[0];
458+
459+
let mut callee_args = vec![
460+
vmctx,
461+
self.builder
462+
.ins()
463+
.iconst(ir::types::I32, i64::from(caller_instance.as_u32())),
464+
];
465+
466+
callee_args.extend(args[2..].iter().copied());
467+
468+
self.translate_intrinsic_libcall(vmctx, host::subtask_drop, &callee_args, ir::types::I8);
404469
}
405470

406471
fn translate_lower_import(

crates/environ/src/component.rs

+6
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,13 @@ macro_rules! foreach_builtin_component_function {
8383
resource_enter_call(vmctx: vmctx);
8484
resource_exit_call(vmctx: vmctx) -> bool;
8585

86+
task_backpressure(vmctx: vmctx, caller_instance: u32, enabled: u32) -> bool;
8687
task_return(vmctx: vmctx, ty: u32, storage: ptr_u8, storage_len: size) -> bool;
88+
task_wait(vmctx: vmctx, caller_instance: u32, async_: u8, memory: ptr_u8, payload: u32) -> u64;
89+
task_poll(vmctx: vmctx, caller_instance: u32, async_: u8, memory: ptr_u8, payload: u32) -> u64;
90+
task_yield(vmctx: vmctx, async_: u8) -> bool;
91+
subtask_drop(vmctx: vmctx, caller_instance: u32, task_id: u32) -> bool;
92+
8793
async_enter(vmctx: vmctx, start: ptr_u8, return_: ptr_u8, caller_instance: u32, task_return_type: u32, params: u32, results: u32) -> bool;
8894
async_exit(vmctx: vmctx, callback: ptr_u8, post_return: ptr_u8, caller_instance: u32, callee: ptr_u8, callee_instance: u32, param_count: u32, result_count: u32, flags: u32) -> u64;
8995

crates/wasmtime/src/runtime/store.rs

+45
Original file line numberDiff line numberDiff line change
@@ -2551,6 +2551,15 @@ impl AsyncCx {
25512551

25522552
#[cfg(feature = "component-model-async")]
25532553
unsafe impl<T> crate::runtime::vm::VMComponentAsyncStore for StoreInner<T> {
2554+
fn task_backpressure(
2555+
&mut self,
2556+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
2557+
enabled: u32,
2558+
) -> Result<()> {
2559+
_ = (caller_instance, enabled);
2560+
todo!()
2561+
}
2562+
25542563
fn task_return(
25552564
&mut self,
25562565
ty: wasmtime_environ::component::TypeTaskReturnIndex,
@@ -2561,6 +2570,42 @@ unsafe impl<T> crate::runtime::vm::VMComponentAsyncStore for StoreInner<T> {
25612570
todo!()
25622571
}
25632572

2573+
fn task_wait(
2574+
&mut self,
2575+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
2576+
async_: bool,
2577+
memory: *mut crate::vm::VMMemoryDefinition,
2578+
payload: u32,
2579+
) -> Result<u32> {
2580+
_ = (caller_instance, async_, memory, payload);
2581+
todo!()
2582+
}
2583+
2584+
fn task_poll(
2585+
&mut self,
2586+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
2587+
async_: bool,
2588+
memory: *mut crate::vm::VMMemoryDefinition,
2589+
payload: u32,
2590+
) -> Result<u32> {
2591+
_ = (caller_instance, async_, memory, payload);
2592+
todo!()
2593+
}
2594+
2595+
fn task_yield(&mut self, async_: bool) -> Result<()> {
2596+
_ = async_;
2597+
todo!()
2598+
}
2599+
2600+
fn subtask_drop(
2601+
&mut self,
2602+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
2603+
task_id: u32,
2604+
) -> Result<()> {
2605+
_ = (caller_instance, task_id);
2606+
todo!()
2607+
}
2608+
25642609
fn async_enter(
25652610
&mut self,
25662611
start: *mut VMFuncRef,

crates/wasmtime/src/runtime/vm.rs

+30
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,43 @@ cfg_if::cfg_if! {
118118

119119
#[cfg(feature = "component-model-async")]
120120
pub unsafe trait VMComponentAsyncStore {
121+
fn task_backpressure(
122+
&mut self,
123+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
124+
enabled: u32,
125+
) -> Result<()>;
126+
121127
fn task_return(
122128
&mut self,
123129
ty: wasmtime_environ::component::TypeTaskReturnIndex,
124130
storage: *mut ValRaw,
125131
storage_len: usize,
126132
) -> Result<()>;
127133

134+
fn task_wait(
135+
&mut self,
136+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
137+
async_: bool,
138+
memory: *mut VMMemoryDefinition,
139+
payload: u32,
140+
) -> Result<u32>;
141+
142+
fn task_poll(
143+
&mut self,
144+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
145+
async_: bool,
146+
memory: *mut VMMemoryDefinition,
147+
payload: u32,
148+
) -> Result<u32>;
149+
150+
fn task_yield(&mut self, async_: bool) -> Result<()>;
151+
152+
fn subtask_drop(
153+
&mut self,
154+
caller_instance: wasmtime_environ::component::RuntimeComponentInstanceIndex,
155+
task_id: u32,
156+
) -> Result<()>;
157+
128158
fn async_enter(
129159
&mut self,
130160
start: *mut VMFuncRef,

0 commit comments

Comments
 (0)