1use crate::prelude::*;
4use crate::runtime::vm::component::{ComponentInstance, VMComponentContext};
5use crate::runtime::vm::{HostResultHasUnwindSentinel, VmSafe};
6use core::cell::Cell;
7use core::convert::Infallible;
8use core::ptr::NonNull;
9use core::slice;
10use wasmtime_environ::component::TypeResourceTableIndex;
11
12const UTF16_TAG: usize = 1 << 31;
13
14macro_rules! signature {
15 (@ty size) => (usize);
16 (@ty ptr_u8) => (*mut u8);
17 (@ty ptr_u16) => (*mut u16);
18 (@ty ptr_size) => (*mut usize);
19 (@ty u8) => (u8);
20 (@ty u32) => (u32);
21 (@ty u64) => (u64);
22 (@ty bool) => (bool);
23 (@ty vmctx) => (NonNull<VMComponentContext>);
24}
25
26macro_rules! define_builtins {
29 (
30 $(
31 $( #[$attr:meta] )*
32 $name:ident( $( $pname:ident: $param:ident ),* ) $( -> $result:ident )?;
33 )*
34 ) => {
35 #[repr(C)]
38 pub struct VMComponentBuiltins {
39 $(
40 $name: unsafe extern "C" fn(
41 $(signature!(@ty $param),)*
42 ) $( -> signature!(@ty $result))?,
43 )*
44 }
45
46 unsafe impl VmSafe for VMComponentBuiltins {}
49
50 impl VMComponentBuiltins {
51 pub const INIT: VMComponentBuiltins = VMComponentBuiltins {
52 $($name: trampolines::$name,)*
53 };
54 }
55 };
56}
57
58wasmtime_environ::foreach_builtin_component_function!(define_builtins);
59
60#[allow(improper_ctypes_definitions)]
65mod trampolines {
66 use super::VMComponentContext;
67 use core::ptr::NonNull;
68
69 macro_rules! shims {
70 (
71 $(
72 $( #[cfg($attr:meta)] )?
73 $name:ident( $( $pname:ident: $param:ident ),* ) $( -> $result:ident )?;
74 )*
75 ) => (
76 $(
77 pub unsafe extern "C" fn $name(
78 $($pname : signature!(@ty $param),)*
79 ) $( -> signature!(@ty $result))? {
80 $(#[cfg($attr)])?
81 {
82 $(shims!(@validate_param $pname $param);)*
83
84 let ret = crate::runtime::vm::traphandlers::catch_unwind_and_record_trap(|| {
85 shims!(@invoke $name() $($pname)*)
86 });
87 shims!(@convert_ret ret $($pname: $param)*)
88 }
89 $(
90 #[cfg(not($attr))]
91 unreachable!();
92 )?
93 }
94 )*
95 );
96
97 (@convert_ret $ret:ident) => ($ret);
100 (@convert_ret $ret:ident $retptr:ident: ptr_size) => ({
101 let (a, b) = $ret;
102 *$retptr = b;
103 a
104 });
105 (@convert_ret $ret:ident $name:ident: $ty:ident $($rest:tt)*) => (
106 shims!(@convert_ret $ret $($rest)*)
107 );
108
109 (@validate_param $arg:ident ptr_u16) => ({
110 assert!(($arg as usize) % 2 == 0, "unaligned 16-bit pointer");
114 });
115 (@validate_param $arg:ident $ty:ident) => ();
116
117 (@invoke $m:ident ($($args:tt)*)) => (super::$m($($args)*));
120
121 (@invoke $m:ident ($($args:tt)*) ret2 $($rest:tt)*) => (
123 shims!(@invoke $m ($($args)*) $($rest)*)
124 );
125
126 (@invoke $m:ident ($($args:tt)*) $param:ident $($rest:tt)*) => (
128 shims!(@invoke $m ($($args)* $param,) $($rest)*)
129 );
130 }
131
132 wasmtime_environ::foreach_builtin_component_function!(shims);
133}
134
135fn assert_no_overlap<T, U>(a: &[T], b: &[U]) {
139 let a_start = a.as_ptr() as usize;
140 let a_end = a_start + (a.len() * core::mem::size_of::<T>());
141 let b_start = b.as_ptr() as usize;
142 let b_end = b_start + (b.len() * core::mem::size_of::<U>());
143
144 if a_start < b_start {
145 assert!(a_end < b_start);
146 } else {
147 assert!(b_end < a_start);
148 }
149}
150
151unsafe fn utf8_to_utf8(src: *mut u8, len: usize, dst: *mut u8) -> Result<()> {
157 let src = slice::from_raw_parts(src, len);
158 let dst = slice::from_raw_parts_mut(dst, len);
159 assert_no_overlap(src, dst);
160 log::trace!("utf8-to-utf8 {len}");
161 let src = core::str::from_utf8(src).map_err(|_| anyhow!("invalid utf8 encoding"))?;
162 dst.copy_from_slice(src.as_bytes());
163 Ok(())
164}
165
166unsafe fn utf16_to_utf16(src: *mut u16, len: usize, dst: *mut u16) -> Result<()> {
172 let src = slice::from_raw_parts(src, len);
173 let dst = slice::from_raw_parts_mut(dst, len);
174 assert_no_overlap(src, dst);
175 log::trace!("utf16-to-utf16 {len}");
176 run_utf16_to_utf16(src, dst)?;
177 Ok(())
178}
179
180fn run_utf16_to_utf16(src: &[u16], mut dst: &mut [u16]) -> Result<bool> {
183 let mut all_latin1 = true;
184 for ch in core::char::decode_utf16(src.iter().map(|i| u16::from_le(*i))) {
185 let ch = ch.map_err(|_| anyhow!("invalid utf16 encoding"))?;
186 all_latin1 = all_latin1 && u8::try_from(u32::from(ch)).is_ok();
187 let result = ch.encode_utf16(dst);
188 let size = result.len();
189 for item in result {
190 *item = item.to_le();
191 }
192 dst = &mut dst[size..];
193 }
194 Ok(all_latin1)
195}
196
197unsafe fn latin1_to_latin1(src: *mut u8, len: usize, dst: *mut u8) -> Result<()> {
202 let src = slice::from_raw_parts(src, len);
203 let dst = slice::from_raw_parts_mut(dst, len);
204 assert_no_overlap(src, dst);
205 log::trace!("latin1-to-latin1 {len}");
206 dst.copy_from_slice(src);
207 Ok(())
208}
209
210unsafe fn latin1_to_utf16(src: *mut u8, len: usize, dst: *mut u16) -> Result<()> {
215 let src = slice::from_raw_parts(src, len);
216 let dst = slice::from_raw_parts_mut(dst, len);
217 assert_no_overlap(src, dst);
218 for (src, dst) in src.iter().zip(dst) {
219 *dst = u16::from(*src).to_le();
220 }
221 log::trace!("latin1-to-utf16 {len}");
222 Ok(())
223}
224
225struct CopySizeReturn(usize);
226
227unsafe impl HostResultHasUnwindSentinel for CopySizeReturn {
228 type Abi = usize;
229 const SENTINEL: usize = usize::MAX;
230 fn into_abi(self) -> usize {
231 self.0
232 }
233}
234
235unsafe fn utf8_to_utf16(src: *mut u8, len: usize, dst: *mut u16) -> Result<CopySizeReturn> {
240 let src = slice::from_raw_parts(src, len);
241 let dst = slice::from_raw_parts_mut(dst, len);
242 assert_no_overlap(src, dst);
243
244 let result = run_utf8_to_utf16(src, dst)?;
245 log::trace!("utf8-to-utf16 {len} => {result}");
246 Ok(CopySizeReturn(result))
247}
248
249fn run_utf8_to_utf16(src: &[u8], dst: &mut [u16]) -> Result<usize> {
250 let src = core::str::from_utf8(src).map_err(|_| anyhow!("invalid utf8 encoding"))?;
251 let mut amt = 0;
252 for (i, dst) in src.encode_utf16().zip(dst) {
253 *dst = i.to_le();
254 amt += 1;
255 }
256 Ok(amt)
257}
258
259struct SizePair {
260 src_read: usize,
261 dst_written: usize,
262}
263
264unsafe impl HostResultHasUnwindSentinel for SizePair {
265 type Abi = (usize, usize);
266 const SENTINEL: (usize, usize) = (usize::MAX, 0);
267 fn into_abi(self) -> (usize, usize) {
268 (self.src_read, self.dst_written)
269 }
270}
271
272unsafe fn utf16_to_utf8(
279 src: *mut u16,
280 src_len: usize,
281 dst: *mut u8,
282 dst_len: usize,
283) -> Result<SizePair> {
284 let src = slice::from_raw_parts(src, src_len);
285 let mut dst = slice::from_raw_parts_mut(dst, dst_len);
286 assert_no_overlap(src, dst);
287
288 let src_iter_read = Cell::new(0);
292 let src_iter = src.iter().map(|i| {
293 src_iter_read.set(src_iter_read.get() + 1);
294 u16::from_le(*i)
295 });
296
297 let mut src_read = 0;
298 let mut dst_written = 0;
299
300 for ch in core::char::decode_utf16(src_iter) {
301 let ch = ch.map_err(|_| anyhow!("invalid utf16 encoding"))?;
302
303 if dst.len() < 4 && dst.len() < ch.len_utf8() {
307 break;
308 }
309
310 src_read = src_iter_read.get();
313 let len = ch.encode_utf8(dst).len();
314 dst_written += len;
315 dst = &mut dst[len..];
316 }
317
318 log::trace!("utf16-to-utf8 {src_len}/{dst_len} => {src_read}/{dst_written}");
319 Ok(SizePair {
320 src_read,
321 dst_written,
322 })
323}
324
325unsafe fn latin1_to_utf8(
332 src: *mut u8,
333 src_len: usize,
334 dst: *mut u8,
335 dst_len: usize,
336) -> Result<SizePair> {
337 let src = slice::from_raw_parts(src, src_len);
338 let dst = slice::from_raw_parts_mut(dst, dst_len);
339 assert_no_overlap(src, dst);
340 let (read, written) = encoding_rs::mem::convert_latin1_to_utf8_partial(src, dst);
341 log::trace!("latin1-to-utf8 {src_len}/{dst_len} => ({read}, {written})");
342 Ok(SizePair {
343 src_read: read,
344 dst_written: written,
345 })
346}
347
348unsafe fn utf16_to_compact_probably_utf16(
356 src: *mut u16,
357 len: usize,
358 dst: *mut u16,
359) -> Result<CopySizeReturn> {
360 let src = slice::from_raw_parts(src, len);
361 let dst = slice::from_raw_parts_mut(dst, len);
362 assert_no_overlap(src, dst);
363 let all_latin1 = run_utf16_to_utf16(src, dst)?;
364 if all_latin1 {
365 let (left, dst, right) = dst.align_to_mut::<u8>();
366 assert!(left.is_empty());
367 assert!(right.is_empty());
368 for i in 0..len {
369 dst[i] = dst[2 * i];
370 }
371 log::trace!("utf16-to-compact-probably-utf16 {len} => latin1 {len}");
372 Ok(CopySizeReturn(len))
373 } else {
374 log::trace!("utf16-to-compact-probably-utf16 {len} => utf16 {len}");
375 Ok(CopySizeReturn(len | UTF16_TAG))
376 }
377}
378
379unsafe fn utf8_to_latin1(src: *mut u8, len: usize, dst: *mut u8) -> Result<SizePair> {
390 let src = slice::from_raw_parts(src, len);
391 let dst = slice::from_raw_parts_mut(dst, len);
392 assert_no_overlap(src, dst);
393 let read = encoding_rs::mem::utf8_latin1_up_to(src);
394 let written = encoding_rs::mem::convert_utf8_to_latin1_lossy(&src[..read], dst);
395 log::trace!("utf8-to-latin1 {len} => ({read}, {written})");
396 Ok(SizePair {
397 src_read: read,
398 dst_written: written,
399 })
400}
401
402unsafe fn utf16_to_latin1(src: *mut u16, len: usize, dst: *mut u8) -> Result<SizePair> {
406 let src = slice::from_raw_parts(src, len);
407 let dst = slice::from_raw_parts_mut(dst, len);
408 assert_no_overlap(src, dst);
409
410 let mut size = 0;
411 for (src, dst) in src.iter().zip(dst) {
412 let src = u16::from_le(*src);
413 match u8::try_from(src) {
414 Ok(src) => *dst = src,
415 Err(_) => break,
416 }
417 size += 1;
418 }
419 log::trace!("utf16-to-latin1 {len} => {size}");
420 Ok(SizePair {
421 src_read: size,
422 dst_written: size,
423 })
424}
425
426unsafe fn utf8_to_compact_utf16(
442 src: *mut u8,
443 src_len: usize,
444 dst: *mut u16,
445 dst_len: usize,
446 latin1_bytes_so_far: usize,
447) -> Result<CopySizeReturn> {
448 let src = slice::from_raw_parts(src, src_len);
449 let dst = slice::from_raw_parts_mut(dst, dst_len);
450 assert_no_overlap(src, dst);
451
452 let dst = inflate_latin1_bytes(dst, latin1_bytes_so_far);
453 let result = run_utf8_to_utf16(src, dst)?;
454 log::trace!("utf8-to-compact-utf16 {src_len}/{dst_len}/{latin1_bytes_so_far} => {result}");
455 Ok(CopySizeReturn(result + latin1_bytes_so_far))
456}
457
458unsafe fn utf16_to_compact_utf16(
460 src: *mut u16,
461 src_len: usize,
462 dst: *mut u16,
463 dst_len: usize,
464 latin1_bytes_so_far: usize,
465) -> Result<CopySizeReturn> {
466 let src = slice::from_raw_parts(src, src_len);
467 let dst = slice::from_raw_parts_mut(dst, dst_len);
468 assert_no_overlap(src, dst);
469
470 let dst = inflate_latin1_bytes(dst, latin1_bytes_so_far);
471 run_utf16_to_utf16(src, dst)?;
472 let result = src.len();
473 log::trace!("utf16-to-compact-utf16 {src_len}/{dst_len}/{latin1_bytes_so_far} => {result}");
474 Ok(CopySizeReturn(result + latin1_bytes_so_far))
475}
476
477fn inflate_latin1_bytes(dst: &mut [u16], latin1_bytes_so_far: usize) -> &mut [u16] {
484 let (to_inflate, rest) = dst.split_at_mut(latin1_bytes_so_far);
489
490 let (left, mid, right) = unsafe { to_inflate.align_to_mut::<u8>() };
492 assert!(left.is_empty());
493 assert!(right.is_empty());
494 for i in (0..latin1_bytes_so_far).rev() {
495 mid[2 * i] = mid[i];
496 mid[2 * i + 1] = 0;
497 }
498
499 return rest;
500}
501
502unsafe fn resource_new32(
503 vmctx: NonNull<VMComponentContext>,
504 resource: u32,
505 rep: u32,
506) -> Result<u32> {
507 let resource = TypeResourceTableIndex::from_u32(resource);
508 ComponentInstance::from_vmctx(vmctx, |instance| instance.resource_new32(resource, rep))
509}
510
511unsafe fn resource_rep32(
512 vmctx: NonNull<VMComponentContext>,
513 resource: u32,
514 idx: u32,
515) -> Result<u32> {
516 let resource = TypeResourceTableIndex::from_u32(resource);
517 ComponentInstance::from_vmctx(vmctx, |instance| instance.resource_rep32(resource, idx))
518}
519
520unsafe fn resource_drop(
521 vmctx: NonNull<VMComponentContext>,
522 resource: u32,
523 idx: u32,
524) -> Result<ResourceDropRet> {
525 let resource = TypeResourceTableIndex::from_u32(resource);
526 ComponentInstance::from_vmctx(vmctx, |instance| {
527 Ok(ResourceDropRet(instance.resource_drop(resource, idx)?))
528 })
529}
530
531struct ResourceDropRet(Option<u32>);
532
533unsafe impl HostResultHasUnwindSentinel for ResourceDropRet {
534 type Abi = u64;
535 const SENTINEL: u64 = u64::MAX;
536 fn into_abi(self) -> u64 {
537 match self.0 {
538 Some(rep) => (u64::from(rep) << 1) | 1,
539 None => 0,
540 }
541 }
542}
543
544unsafe fn resource_transfer_own(
545 vmctx: NonNull<VMComponentContext>,
546 src_idx: u32,
547 src_table: u32,
548 dst_table: u32,
549) -> Result<u32> {
550 let src_table = TypeResourceTableIndex::from_u32(src_table);
551 let dst_table = TypeResourceTableIndex::from_u32(dst_table);
552 ComponentInstance::from_vmctx(vmctx, |instance| {
553 instance.resource_transfer_own(src_idx, src_table, dst_table)
554 })
555}
556
557unsafe fn resource_transfer_borrow(
558 vmctx: NonNull<VMComponentContext>,
559 src_idx: u32,
560 src_table: u32,
561 dst_table: u32,
562) -> Result<u32> {
563 let src_table = TypeResourceTableIndex::from_u32(src_table);
564 let dst_table = TypeResourceTableIndex::from_u32(dst_table);
565 ComponentInstance::from_vmctx(vmctx, |instance| {
566 instance.resource_transfer_borrow(src_idx, src_table, dst_table)
567 })
568}
569
570unsafe fn resource_enter_call(vmctx: NonNull<VMComponentContext>) {
571 ComponentInstance::from_vmctx(vmctx, |instance| instance.resource_enter_call())
572}
573
574unsafe fn resource_exit_call(vmctx: NonNull<VMComponentContext>) -> Result<()> {
575 ComponentInstance::from_vmctx(vmctx, |instance| instance.resource_exit_call())
576}
577
578unsafe fn trap(_vmctx: NonNull<VMComponentContext>, code: u8) -> Result<Infallible> {
579 Err(wasmtime_environ::Trap::from_u8(code).unwrap().into())
580}
581
582#[cfg(feature = "component-model-async")]
583unsafe fn backpressure_set(
584 vmctx: NonNull<VMComponentContext>,
585 caller_instance: u32,
586 enabled: u32,
587) -> Result<()> {
588 ComponentInstance::from_vmctx(vmctx, |instance| {
589 (*instance.store())
590 .component_async_store()
591 .backpressure_set(
592 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(
593 caller_instance,
594 ),
595 enabled,
596 )
597 })
598}
599
600#[cfg(feature = "component-model-async")]
601unsafe fn task_return(
602 vmctx: NonNull<VMComponentContext>,
603 ty: u32,
604 storage: *mut u8,
605 storage_len: usize,
606) -> Result<()> {
607 ComponentInstance::from_vmctx(vmctx, |instance| {
608 (*instance.store()).component_async_store().task_return(
609 instance,
610 wasmtime_environ::component::TypeTupleIndex::from_u32(ty),
611 storage.cast::<crate::ValRaw>(),
612 storage_len,
613 )
614 })
615}
616
617#[cfg(feature = "component-model-async")]
618unsafe fn waitable_set_new(
619 vmctx: NonNull<VMComponentContext>,
620 caller_instance: u32,
621) -> Result<u32> {
622 ComponentInstance::from_vmctx(vmctx, |instance| {
623 (*instance.store())
624 .component_async_store()
625 .waitable_set_new(
626 instance,
627 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(
628 caller_instance,
629 ),
630 )
631 })
632}
633
634#[cfg(feature = "component-model-async")]
635unsafe fn waitable_set_wait(
636 vmctx: NonNull<VMComponentContext>,
637 caller_instance: u32,
638 set: u32,
639 async_: u8,
640 memory: *mut u8,
641 payload: u32,
642) -> Result<u32> {
643 ComponentInstance::from_vmctx(vmctx, |instance| {
644 (*instance.store())
645 .component_async_store()
646 .waitable_set_wait(
647 instance,
648 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(
649 caller_instance,
650 ),
651 set,
652 async_ != 0,
653 memory.cast::<crate::vm::VMMemoryDefinition>(),
654 payload,
655 )
656 })
657}
658
659#[cfg(feature = "component-model-async")]
660unsafe fn waitable_set_poll(
661 vmctx: NonNull<VMComponentContext>,
662 caller_instance: u32,
663 set: u32,
664 async_: u8,
665 memory: *mut u8,
666 payload: u32,
667) -> Result<u32> {
668 ComponentInstance::from_vmctx(vmctx, |instance| {
669 (*instance.store())
670 .component_async_store()
671 .waitable_set_poll(
672 instance,
673 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(
674 caller_instance,
675 ),
676 set,
677 async_ != 0,
678 memory.cast::<crate::vm::VMMemoryDefinition>(),
679 payload,
680 )
681 })
682}
683
684#[cfg(feature = "component-model-async")]
685unsafe fn waitable_set_drop(
686 vmctx: NonNull<VMComponentContext>,
687 caller_instance: u32,
688 set: u32,
689) -> Result<()> {
690 ComponentInstance::from_vmctx(vmctx, |instance| {
691 (*instance.store())
692 .component_async_store()
693 .waitable_set_drop(
694 instance,
695 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(
696 caller_instance,
697 ),
698 set,
699 )
700 })
701}
702
703#[cfg(feature = "component-model-async")]
704unsafe fn waitable_join(
705 vmctx: NonNull<VMComponentContext>,
706 caller_instance: u32,
707 set: u32,
708 waitable: u32,
709) -> Result<()> {
710 ComponentInstance::from_vmctx(vmctx, |instance| {
711 (*instance.store()).component_async_store().waitable_join(
712 instance,
713 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
714 set,
715 waitable,
716 )
717 })
718}
719
720#[cfg(feature = "component-model-async")]
721unsafe fn yield_(vmctx: NonNull<VMComponentContext>, async_: u8) -> Result<()> {
722 ComponentInstance::from_vmctx(vmctx, |instance| {
723 (*instance.store())
724 .component_async_store()
725 .yield_(instance, async_ != 0)
726 })
727}
728
729#[cfg(feature = "component-model-async")]
730unsafe fn subtask_drop(
731 vmctx: NonNull<VMComponentContext>,
732 caller_instance: u32,
733 task_id: u32,
734) -> Result<()> {
735 ComponentInstance::from_vmctx(vmctx, |instance| {
736 (*instance.store()).component_async_store().subtask_drop(
737 instance,
738 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
739 task_id,
740 )
741 })
742}
743
744#[cfg(feature = "component-model-async")]
745unsafe fn sync_enter(
746 vmctx: NonNull<VMComponentContext>,
747 start: *mut u8,
748 return_: *mut u8,
749 caller_instance: u32,
750 task_return_type: u32,
751 result_count: u32,
752 storage: *mut u8,
753 storage_len: usize,
754) -> Result<()> {
755 ComponentInstance::from_vmctx(vmctx, |instance| {
756 (*instance.store()).component_async_store().sync_enter(
757 start.cast::<crate::vm::VMFuncRef>(),
758 return_.cast::<crate::vm::VMFuncRef>(),
759 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
760 wasmtime_environ::component::TypeTupleIndex::from_u32(task_return_type),
761 result_count,
762 storage.cast::<crate::ValRaw>(),
763 storage_len,
764 )
765 })
766}
767
768#[cfg(feature = "component-model-async")]
769unsafe fn sync_exit(
770 vmctx: NonNull<VMComponentContext>,
771 callback: *mut u8,
772 caller_instance: u32,
773 callee: *mut u8,
774 callee_instance: u32,
775 param_count: u32,
776 storage: *mut u8,
777 storage_len: usize,
778) -> Result<()> {
779 ComponentInstance::from_vmctx(vmctx, |instance| {
780 (*instance.store()).component_async_store().sync_exit(
781 instance,
782 callback.cast::<crate::vm::VMFuncRef>(),
783 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
784 callee.cast::<crate::vm::VMFuncRef>(),
785 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(callee_instance),
786 param_count,
787 storage.cast::<std::mem::MaybeUninit<crate::ValRaw>>(),
788 storage_len,
789 )
790 })
791}
792
793#[cfg(feature = "component-model-async")]
794unsafe fn async_enter(
795 vmctx: NonNull<VMComponentContext>,
796 start: *mut u8,
797 return_: *mut u8,
798 caller_instance: u32,
799 task_return_type: u32,
800 params: u32,
801 results: u32,
802) -> Result<()> {
803 ComponentInstance::from_vmctx(vmctx, |instance| {
804 (*instance.store()).component_async_store().async_enter(
805 start.cast::<crate::vm::VMFuncRef>(),
806 return_.cast::<crate::vm::VMFuncRef>(),
807 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
808 wasmtime_environ::component::TypeTupleIndex::from_u32(task_return_type),
809 params,
810 results,
811 )
812 })
813}
814
815#[cfg(feature = "component-model-async")]
816unsafe fn async_exit(
817 vmctx: NonNull<VMComponentContext>,
818 callback: *mut u8,
819 post_return: *mut u8,
820 caller_instance: u32,
821 callee: *mut u8,
822 callee_instance: u32,
823 param_count: u32,
824 result_count: u32,
825 flags: u32,
826) -> Result<u32> {
827 ComponentInstance::from_vmctx(vmctx, |instance| {
828 (*instance.store()).component_async_store().async_exit(
829 instance,
830 callback.cast::<crate::vm::VMFuncRef>(),
831 post_return.cast::<crate::vm::VMFuncRef>(),
832 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(caller_instance),
833 callee.cast::<crate::vm::VMFuncRef>(),
834 wasmtime_environ::component::RuntimeComponentInstanceIndex::from_u32(callee_instance),
835 param_count,
836 result_count,
837 flags,
838 )
839 })
840}
841
842#[cfg(feature = "component-model-async")]
843unsafe fn future_transfer(
844 vmctx: NonNull<VMComponentContext>,
845 src_idx: u32,
846 src_table: u32,
847 dst_table: u32,
848) -> Result<u32> {
849 let src_table = wasmtime_environ::component::TypeFutureTableIndex::from_u32(src_table);
850 let dst_table = wasmtime_environ::component::TypeFutureTableIndex::from_u32(dst_table);
851 ComponentInstance::from_vmctx(vmctx, |instance| {
852 instance.future_transfer(src_idx, src_table, dst_table)
853 })
854}
855
856#[cfg(feature = "component-model-async")]
857unsafe fn stream_transfer(
858 vmctx: NonNull<VMComponentContext>,
859 src_idx: u32,
860 src_table: u32,
861 dst_table: u32,
862) -> Result<u32> {
863 let src_table = wasmtime_environ::component::TypeStreamTableIndex::from_u32(src_table);
864 let dst_table = wasmtime_environ::component::TypeStreamTableIndex::from_u32(dst_table);
865 ComponentInstance::from_vmctx(vmctx, |instance| {
866 instance.stream_transfer(src_idx, src_table, dst_table)
867 })
868}
869
870#[cfg(feature = "component-model-async")]
871unsafe fn error_context_transfer(
872 vmctx: NonNull<VMComponentContext>,
873 src_idx: u32,
874 src_table: u32,
875 dst_table: u32,
876) -> Result<u32> {
877 let src_table =
878 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(src_table);
879 let dst_table =
880 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(dst_table);
881 ComponentInstance::from_vmctx(vmctx, |instance| {
882 instance.error_context_transfer(src_idx, src_table, dst_table)
883 })
884}
885
886#[cfg(feature = "component-model-async")]
887unsafe fn future_new(vmctx: NonNull<VMComponentContext>, ty: u32) -> Result<u32> {
888 ComponentInstance::from_vmctx(vmctx, |instance| {
889 (*instance.store()).component_async_store().future_new(
890 instance,
891 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
892 )
893 })
894}
895
896#[cfg(feature = "component-model-async")]
897unsafe fn future_write(
898 vmctx: NonNull<VMComponentContext>,
899 memory: *mut u8,
900 realloc: *mut u8,
901 string_encoding: u8,
902 ty: u32,
903 future: u32,
904 address: u32,
905) -> Result<u32> {
906 ComponentInstance::from_vmctx(vmctx, |instance| {
907 (*instance.store()).component_async_store().future_write(
908 instance,
909 memory.cast::<crate::vm::VMMemoryDefinition>(),
910 realloc.cast::<crate::vm::VMFuncRef>(),
911 string_encoding,
912 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
913 future,
914 address,
915 )
916 })
917}
918
919#[cfg(feature = "component-model-async")]
920unsafe fn future_read(
921 vmctx: NonNull<VMComponentContext>,
922 memory: *mut u8,
923 realloc: *mut u8,
924 string_encoding: u8,
925 ty: u32,
926 err_ctx_ty: u32,
927 future: u32,
928 address: u32,
929) -> Result<u32> {
930 ComponentInstance::from_vmctx(vmctx, |instance| {
931 (*instance.store()).component_async_store().future_read(
932 instance,
933 memory.cast::<crate::vm::VMMemoryDefinition>(),
934 realloc.cast::<crate::vm::VMFuncRef>(),
935 string_encoding,
936 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
937 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(
938 err_ctx_ty,
939 ),
940 future,
941 address,
942 )
943 })
944}
945
946#[cfg(feature = "component-model-async")]
947unsafe fn future_cancel_write(
948 vmctx: NonNull<VMComponentContext>,
949 ty: u32,
950 async_: u8,
951 writer: u32,
952) -> Result<u32> {
953 ComponentInstance::from_vmctx(vmctx, |instance| {
954 (*instance.store())
955 .component_async_store()
956 .future_cancel_write(
957 instance,
958 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
959 async_ != 0,
960 writer,
961 )
962 })
963}
964
965#[cfg(feature = "component-model-async")]
966unsafe fn future_cancel_read(
967 vmctx: NonNull<VMComponentContext>,
968 ty: u32,
969 async_: u8,
970 reader: u32,
971) -> Result<u32> {
972 ComponentInstance::from_vmctx(vmctx, |instance| {
973 (*instance.store())
974 .component_async_store()
975 .future_cancel_read(
976 instance,
977 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
978 async_ != 0,
979 reader,
980 )
981 })
982}
983
984#[cfg(feature = "component-model-async")]
985unsafe fn future_close_writable(
986 vmctx: NonNull<VMComponentContext>,
987 ty: u32,
988 err_ctx_ty: u32,
989 writer: u32,
990 error: u32,
991) -> Result<()> {
992 ComponentInstance::from_vmctx(vmctx, |instance| {
993 (*instance.store())
994 .component_async_store()
995 .future_close_writable(
996 instance,
997 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
998 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(
999 err_ctx_ty,
1000 ),
1001 writer,
1002 error,
1003 )
1004 })
1005}
1006
1007#[cfg(feature = "component-model-async")]
1008unsafe fn future_close_readable(
1009 vmctx: NonNull<VMComponentContext>,
1010 ty: u32,
1011 reader: u32,
1012 error: u32,
1013) -> Result<()> {
1014 ComponentInstance::from_vmctx(vmctx, |instance| {
1015 (*instance.store())
1016 .component_async_store()
1017 .future_close_readable(
1018 instance,
1019 wasmtime_environ::component::TypeFutureTableIndex::from_u32(ty),
1020 reader,
1021 error,
1022 )
1023 })
1024}
1025
1026#[cfg(feature = "component-model-async")]
1027unsafe fn stream_new(vmctx: NonNull<VMComponentContext>, ty: u32) -> Result<u32> {
1028 ComponentInstance::from_vmctx(vmctx, |instance| {
1029 (*instance.store()).component_async_store().stream_new(
1030 instance,
1031 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1032 )
1033 })
1034}
1035
1036#[cfg(feature = "component-model-async")]
1037unsafe fn stream_write(
1038 vmctx: NonNull<VMComponentContext>,
1039 memory: *mut u8,
1040 realloc: *mut u8,
1041 string_encoding: u8,
1042 ty: u32,
1043 stream: u32,
1044 address: u32,
1045 count: u32,
1046) -> Result<u32> {
1047 ComponentInstance::from_vmctx(vmctx, |instance| {
1048 (*instance.store()).component_async_store().stream_write(
1049 instance,
1050 memory.cast::<crate::vm::VMMemoryDefinition>(),
1051 realloc.cast::<crate::vm::VMFuncRef>(),
1052 string_encoding,
1053 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1054 stream,
1055 address,
1056 count,
1057 )
1058 })
1059}
1060
1061#[cfg(feature = "component-model-async")]
1062unsafe fn stream_read(
1063 vmctx: NonNull<VMComponentContext>,
1064 memory: *mut u8,
1065 realloc: *mut u8,
1066 string_encoding: u8,
1067 ty: u32,
1068 err_ctx_ty: u32,
1069 stream: u32,
1070 address: u32,
1071 count: u32,
1072) -> Result<u32> {
1073 ComponentInstance::from_vmctx(vmctx, |instance| {
1074 (*instance.store()).component_async_store().stream_read(
1075 instance,
1076 memory.cast::<crate::vm::VMMemoryDefinition>(),
1077 realloc.cast::<crate::vm::VMFuncRef>(),
1078 string_encoding,
1079 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1080 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(
1081 err_ctx_ty,
1082 ),
1083 stream,
1084 address,
1085 count,
1086 )
1087 })
1088}
1089
1090#[cfg(feature = "component-model-async")]
1091unsafe fn stream_cancel_write(
1092 vmctx: NonNull<VMComponentContext>,
1093 ty: u32,
1094 async_: u8,
1095 writer: u32,
1096) -> Result<u32> {
1097 ComponentInstance::from_vmctx(vmctx, |instance| {
1098 (*instance.store())
1099 .component_async_store()
1100 .stream_cancel_write(
1101 instance,
1102 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1103 async_ != 0,
1104 writer,
1105 )
1106 })
1107}
1108
1109#[cfg(feature = "component-model-async")]
1110unsafe fn stream_cancel_read(
1111 vmctx: NonNull<VMComponentContext>,
1112 ty: u32,
1113 async_: u8,
1114 reader: u32,
1115) -> Result<u32> {
1116 ComponentInstance::from_vmctx(vmctx, |instance| {
1117 (*instance.store())
1118 .component_async_store()
1119 .stream_cancel_read(
1120 instance,
1121 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1122 async_ != 0,
1123 reader,
1124 )
1125 })
1126}
1127
1128#[cfg(feature = "component-model-async")]
1129unsafe fn stream_close_writable(
1130 vmctx: NonNull<VMComponentContext>,
1131 ty: u32,
1132 err_ctx_ty: u32,
1133 writer: u32,
1134 error: u32,
1135) -> Result<()> {
1136 ComponentInstance::from_vmctx(vmctx, |instance| {
1137 (*instance.store())
1138 .component_async_store()
1139 .stream_close_writable(
1140 instance,
1141 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1142 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(
1143 err_ctx_ty,
1144 ),
1145 writer,
1146 error,
1147 )
1148 })
1149}
1150
1151#[cfg(feature = "component-model-async")]
1152unsafe fn stream_close_readable(
1153 vmctx: NonNull<VMComponentContext>,
1154 ty: u32,
1155 reader: u32,
1156 error: u32,
1157) -> Result<()> {
1158 ComponentInstance::from_vmctx(vmctx, |instance| {
1159 (*instance.store())
1160 .component_async_store()
1161 .stream_close_readable(
1162 instance,
1163 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1164 reader,
1165 error,
1166 )
1167 })
1168}
1169
1170#[cfg(feature = "component-model-async")]
1171unsafe fn flat_stream_write(
1172 vmctx: NonNull<VMComponentContext>,
1173 memory: *mut u8,
1174 realloc: *mut u8,
1175 ty: u32,
1176 payload_size: u32,
1177 payload_align: u32,
1178 stream: u32,
1179 address: u32,
1180 count: u32,
1181) -> Result<u32> {
1182 ComponentInstance::from_vmctx(vmctx, |instance| {
1183 (*instance.store())
1184 .component_async_store()
1185 .flat_stream_write(
1186 instance,
1187 memory.cast::<crate::vm::VMMemoryDefinition>(),
1188 realloc.cast::<crate::vm::VMFuncRef>(),
1189 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1190 payload_size,
1191 payload_align,
1192 stream,
1193 address,
1194 count,
1195 )
1196 })
1197}
1198
1199#[cfg(feature = "component-model-async")]
1200unsafe fn flat_stream_read(
1201 vmctx: NonNull<VMComponentContext>,
1202 memory: *mut u8,
1203 realloc: *mut u8,
1204 ty: u32,
1205 err_ctx_ty: u32,
1206 payload_size: u32,
1207 payload_align: u32,
1208 stream: u32,
1209 address: u32,
1210 count: u32,
1211) -> Result<u32> {
1212 ComponentInstance::from_vmctx(vmctx, |instance| {
1213 (*instance.store())
1214 .component_async_store()
1215 .flat_stream_read(
1216 instance,
1217 memory.cast::<crate::vm::VMMemoryDefinition>(),
1218 realloc.cast::<crate::vm::VMFuncRef>(),
1219 wasmtime_environ::component::TypeStreamTableIndex::from_u32(ty),
1220 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(
1221 err_ctx_ty,
1222 ),
1223 payload_size,
1224 payload_align,
1225 stream,
1226 address,
1227 count,
1228 )
1229 })
1230}
1231
1232#[cfg(feature = "component-model-async")]
1233unsafe fn error_context_new(
1234 vmctx: NonNull<VMComponentContext>,
1235 memory: *mut u8,
1236 realloc: *mut u8,
1237 string_encoding: u8,
1238 ty: u32,
1239 debug_msg_address: u32,
1240 debug_msg_len: u32,
1241) -> Result<u32> {
1242 ComponentInstance::from_vmctx(vmctx, |instance| {
1243 (*instance.store())
1244 .component_async_store()
1245 .error_context_new(
1246 instance,
1247 memory.cast::<crate::vm::VMMemoryDefinition>(),
1248 realloc.cast::<crate::vm::VMFuncRef>(),
1249 string_encoding,
1250 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(ty),
1251 debug_msg_address,
1252 debug_msg_len,
1253 )
1254 })
1255}
1256
1257#[cfg(feature = "component-model-async")]
1258unsafe fn error_context_debug_message(
1259 vmctx: NonNull<VMComponentContext>,
1260 memory: *mut u8,
1261 realloc: *mut u8,
1262 string_encoding: u8,
1263 ty: u32,
1264 err_ctx_handle: u32,
1265 debug_msg_address: u32,
1266) -> Result<()> {
1267 ComponentInstance::from_vmctx(vmctx, |instance| {
1268 (*instance.store())
1269 .component_async_store()
1270 .error_context_debug_message(
1271 instance,
1272 memory.cast::<crate::vm::VMMemoryDefinition>(),
1273 realloc.cast::<crate::vm::VMFuncRef>(),
1274 string_encoding,
1275 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(ty),
1276 err_ctx_handle,
1277 debug_msg_address,
1278 )
1279 })
1280}
1281
1282#[cfg(feature = "component-model-async")]
1283unsafe fn error_context_drop(
1284 vmctx: NonNull<VMComponentContext>,
1285 ty: u32,
1286 err_ctx_handle: u32,
1287) -> Result<()> {
1288 ComponentInstance::from_vmctx(vmctx, |instance| {
1289 (*instance.store())
1290 .component_async_store()
1291 .error_context_drop(
1292 instance,
1293 wasmtime_environ::component::TypeComponentLocalErrorContextTableIndex::from_u32(ty),
1294 err_ctx_handle,
1295 )
1296 })
1297}