1use crate::{
40 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, DefinedTagIndex, FuncIndex,
41 FuncRefIndex, GlobalIndex, MemoryIndex, Module, OwnedMemoryIndex, RuntimeDataIndex, TableIndex,
42 TagIndex,
43};
44use cranelift_entity::packed_option::ReservedValue;
45
46pub const NUM_COMPONENT_CONTEXT_SLOTS: usize = 2;
49
50#[cfg(target_pointer_width = "32")]
51fn cast_to_u32(sz: usize) -> u32 {
52 u32::try_from(sz).unwrap()
53}
54#[cfg(target_pointer_width = "64")]
55fn cast_to_u32(sz: usize) -> u32 {
56 u32::try_from(sz).expect("overflow in cast from usize to u32")
57}
58
59#[inline]
61fn align(offset: u32, width: u32) -> u32 {
62 (offset + (width - 1)) / width * width
63}
64
65#[derive(Debug, Clone, Copy)]
68pub struct VMOffsets<P> {
69 pub ptr: P,
71 pub num_imported_functions: u32,
73 pub num_imported_tables: u32,
75 pub num_imported_memories: u32,
77 pub num_imported_globals: u32,
79 pub num_imported_tags: u32,
81 pub num_defined_tables: u32,
83 pub num_defined_memories: u32,
85 pub num_owned_memories: u32,
87 pub num_defined_globals: u32,
89 pub num_defined_tags: u32,
91 pub num_escaped_funcs: u32,
94 pub num_runtime_data: u32,
96 pub has_startup_func: bool,
98
99 imported_functions: u32,
101 imported_tables: u32,
102 imported_memories: u32,
103 imported_globals: u32,
104 imported_tags: u32,
105 defined_tables: u32,
106 defined_memories: u32,
107 owned_memories: u32,
108 defined_globals: u32,
109 defined_tags: u32,
110 defined_func_refs: u32,
111 startup_func_ref: u32,
112 runtime_data_bases: u32,
113 runtime_data_lengths: u32,
114 size: u32,
115}
116
117pub trait PtrSize {
119 fn size(&self) -> u8;
121
122 fn vmcontext_store_context(&self) -> u8 {
124 u8::try_from(align(
125 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
126 u32::from(self.size()),
127 ))
128 .unwrap()
129 }
130
131 fn vmcontext_builtin_functions(&self) -> u8 {
133 self.vmcontext_store_context() + self.size()
134 }
135
136 #[inline]
138 fn vm_func_ref_array_call(&self) -> u8 {
139 0 * self.size()
140 }
141
142 #[inline]
144 fn vm_func_ref_wasm_call(&self) -> u8 {
145 1 * self.size()
146 }
147
148 #[inline]
150 fn vm_func_ref_type_index(&self) -> u8 {
151 2 * self.size()
152 }
153
154 #[inline]
156 fn vm_func_ref_vmctx(&self) -> u8 {
157 3 * self.size()
158 }
159
160 #[inline]
162 fn size_of_vm_func_ref(&self) -> u8 {
163 4 * self.size()
164 }
165
166 #[inline]
168 fn size_of_vmshared_type_index(&self) -> u8 {
169 4
170 }
171
172 #[inline]
175 fn size_of_vmglobal_definition(&self) -> u8 {
176 16
177 }
178
179 #[inline]
181 fn size_of_vmtag_definition(&self) -> u8 {
182 4
183 }
184
185 #[inline]
187 fn maximum_value_size(&self) -> u8 {
188 self.size_of_vmglobal_definition()
189 }
190
191 #[inline]
195 fn vmstore_context_fuel_consumed(&self) -> u8 {
196 0
197 }
198
199 #[inline]
201 fn vmstore_context_epoch_deadline(&self) -> u8 {
202 self.vmstore_context_fuel_consumed() + 8
203 }
204
205 #[inline]
208 fn vmstore_context_execution_version(&self) -> u8 {
209 self.vmstore_context_epoch_deadline() + 8
210 }
211
212 #[inline]
214 fn vmstore_context_stack_limit(&self) -> u8 {
215 self.vmstore_context_execution_version() + 8
216 }
217
218 #[inline]
220 fn vmstore_context_gc_heap(&self) -> u8 {
221 self.vmstore_context_stack_limit() + self.size()
222 }
223
224 fn vmstore_context_gc_heap_base(&self) -> u8 {
226 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_base();
227 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
228 offset
229 }
230
231 fn vmstore_context_gc_heap_current_length(&self) -> u8 {
233 let offset = self.vmstore_context_gc_heap() + self.vmmemory_definition_current_length();
234 debug_assert!(offset < self.vmstore_context_last_wasm_exit_trampoline_fp());
235 offset
236 }
237
238 fn vmstore_context_last_wasm_exit_trampoline_fp(&self) -> u8 {
241 self.vmstore_context_gc_heap() + self.size_of_vmmemory_definition()
242 }
243
244 fn vmstore_context_last_wasm_exit_pc(&self) -> u8 {
246 self.vmstore_context_last_wasm_exit_trampoline_fp() + self.size()
247 }
248
249 fn vmstore_context_last_wasm_entry_sp(&self) -> u8 {
251 self.vmstore_context_last_wasm_exit_pc() + self.size()
252 }
253
254 fn vmstore_context_last_wasm_entry_fp(&self) -> u8 {
256 self.vmstore_context_last_wasm_entry_sp() + self.size()
257 }
258
259 fn vmstore_context_last_wasm_entry_trap_handler(&self) -> u8 {
261 self.vmstore_context_last_wasm_entry_fp() + self.size()
262 }
263
264 fn vmstore_context_stack_chain(&self) -> u8 {
266 self.vmstore_context_last_wasm_entry_trap_handler() + self.size()
267 }
268
269 fn vmstore_context_store_data(&self) -> u8 {
271 self.vmstore_context_stack_chain() + self.size_of_vmstack_chain()
272 }
273
274 fn vmstore_context_async_guard_range(&self) -> u8 {
276 self.vmstore_context_store_data() + self.size()
277 }
278
279 fn vmstore_context_component_context_slot(&self, i: u8) -> u8 {
282 assert!(usize::from(i) < NUM_COMPONENT_CONTEXT_SLOTS);
283 let base = self.vmstore_context_async_guard_range() + 2 * self.size();
284 let slot_size = 4;
285 base + i * slot_size
286 }
287
288 fn vmstore_context_current_thread(&self) -> u8 {
290 self.vmstore_context_component_context_slot(0) + (NUM_COMPONENT_CONTEXT_SLOTS as u8) * 4
291 }
292
293 fn vmdeferred_thread_parent(&self) -> u8 {
297 0
298 }
299
300 fn vmdeferred_thread_caller_instance(&self) -> u8 {
302 self.size()
303 }
304
305 fn vmdeferred_thread_callee_async(&self) -> u8 {
307 self.vmdeferred_thread_caller_instance() + 4
308 }
309
310 fn vmdeferred_thread_callee_instance(&self) -> u8 {
312 self.vmdeferred_thread_callee_async() + 4
313 }
314
315 fn vmdeferred_thread_saved_context(&self, i: u8) -> u8 {
317 assert!(usize::from(i) < NUM_COMPONENT_CONTEXT_SLOTS);
318 self.vmdeferred_thread_callee_instance() + 4 + i * 4
319 }
320
321 fn size_of_vmdeferred_thread(&self) -> u8 {
323 let unaligned =
324 self.vmdeferred_thread_callee_instance() + 4 + (NUM_COMPONENT_CONTEXT_SLOTS as u8) * 4;
325 align(u32::from(unaligned), u32::from(self.size())) as u8
326 }
327
328 #[inline]
332 fn vmmemory_definition_base(&self) -> u8 {
333 0 * self.size()
334 }
335
336 #[inline]
338 fn vmmemory_definition_current_length(&self) -> u8 {
339 1 * self.size()
340 }
341
342 #[inline]
344 fn size_of_vmmemory_definition(&self) -> u8 {
345 2 * self.size()
346 }
347
348 #[inline]
350 fn size_of_vmmemory_pointer(&self) -> u8 {
351 self.size()
352 }
353
354 fn vmarray_call_host_func_context_func_ref(&self) -> u8 {
358 u8::try_from(align(
359 u32::try_from(core::mem::size_of::<u32>()).unwrap(),
360 u32::from(self.size()),
361 ))
362 .unwrap()
363 }
364
365 fn size_of_vmstack_chain(&self) -> u8 {
367 2 * self.size()
368 }
369
370 fn vmstack_limits_stack_limit(&self) -> u8 {
374 0
375 }
376
377 fn vmstack_limits_last_wasm_entry_fp(&self) -> u8 {
379 self.size()
380 }
381
382 fn vmhostarray_length(&self) -> u8 {
386 0
387 }
388
389 fn vmhostarray_capacity(&self) -> u8 {
391 4
392 }
393
394 fn vmhostarray_data(&self) -> u8 {
396 8
397 }
398
399 fn size_of_vmhostarray(&self) -> u8 {
401 8 + self.size()
402 }
403
404 fn vmcommon_stack_information_limits(&self) -> u8 {
408 0 * self.size()
409 }
410
411 fn vmcommon_stack_information_state(&self) -> u8 {
413 2 * self.size()
414 }
415
416 fn vmcommon_stack_information_handlers(&self) -> u8 {
418 u8::try_from(align(
419 self.vmcommon_stack_information_state() as u32 + 4,
420 u32::from(self.size()),
421 ))
422 .unwrap()
423 }
424
425 fn vmcommon_stack_information_first_switch_handler_index(&self) -> u8 {
427 self.vmcommon_stack_information_handlers() + self.size_of_vmhostarray()
428 }
429
430 fn size_of_vmcommon_stack_information(&self) -> u8 {
432 u8::try_from(align(
433 self.vmcommon_stack_information_first_switch_handler_index() as u32 + 4,
434 u32::from(self.size()),
435 ))
436 .unwrap()
437 }
438
439 fn vmcontobj_contref(&self) -> u8 {
443 0
444 }
445
446 fn vmcontobj_revision(&self) -> u8 {
448 self.size()
449 }
450
451 fn size_of_vmcontobj(&self) -> u8 {
453 u8::try_from(align(
454 u32::from(self.vmcontobj_revision())
455 + u32::try_from(core::mem::size_of::<usize>()).unwrap(),
456 u32::from(self.size()),
457 ))
458 .unwrap()
459 }
460
461 fn vmcontref_common_stack_information(&self) -> u8 {
465 0 * self.size()
466 }
467
468 fn vmcontref_parent_chain(&self) -> u8 {
470 u8::try_from(align(
471 (self.vmcontref_common_stack_information() + self.size_of_vmcommon_stack_information())
472 as u32,
473 u32::from(self.size()),
474 ))
475 .unwrap()
476 }
477
478 fn vmcontref_last_ancestor(&self) -> u8 {
480 self.vmcontref_parent_chain() + 2 * self.size()
481 }
482
483 fn vmcontref_revision(&self) -> u8 {
485 self.vmcontref_last_ancestor() + self.size()
486 }
487
488 fn vmcontref_stack(&self) -> u8 {
490 self.vmcontref_revision() + self.size()
491 }
492
493 fn vmcontref_args(&self) -> u8 {
495 self.vmcontref_stack() + 3 * self.size()
496 }
497
498 fn vmcontref_values(&self) -> u8 {
500 self.vmcontref_args() + self.size_of_vmhostarray()
501 }
502
503 #[inline]
505 fn vmctx_magic(&self) -> u8 {
506 0
510 }
511
512 #[inline]
514 fn vmctx_store_context(&self) -> u8 {
515 self.vmctx_magic() + self.size()
516 }
517
518 #[inline]
520 fn vmctx_builtin_functions(&self) -> u8 {
521 self.vmctx_store_context() + self.size()
522 }
523
524 #[inline]
527 fn vmctx_epoch_ptr(&self) -> u8 {
528 self.vmctx_builtin_functions() + self.size()
529 }
530
531 #[inline]
536 fn vmctx_gc_heap_data(&self) -> u8 {
537 self.vmctx_epoch_ptr() + self.size()
538 }
539
540 #[inline]
543 fn vmdrc_heap_data_over_approximated_stack_roots(&self) -> u8 {
544 0
545 }
546
547 #[inline]
550 fn vmdrc_heap_data_current_over_approximated_stack_roots_len(&self) -> u8 {
551 4
552 }
553
554 #[inline]
558 fn vmdrc_heap_data_over_approximated_stack_roots_len_after_last_gc(&self) -> u8 {
559 8
560 }
561
562 #[inline]
564 fn size_of_vmdrc_heap_data(&self) -> u8 {
565 12
566 }
567
568 #[inline]
570 fn align_of_vmdrc_heap_data(&self) -> u8 {
571 4
572 }
573
574 #[inline]
576 fn vmcopying_heap_data_bump_ptr(&self) -> u8 {
577 0
578 }
579
580 #[inline]
583 fn vmcopying_heap_data_active_space_end(&self) -> u8 {
584 4
585 }
586
587 #[inline]
589 fn size_of_vmcopying_heap_data(&self) -> u8 {
590 8
591 }
592
593 #[inline]
595 fn align_of_vmcopying_heap_data(&self) -> u8 {
596 4
597 }
598
599 #[inline]
601 fn vmctx_type_ids_array(&self) -> u8 {
602 self.vmctx_gc_heap_data() + self.size()
603 }
604
605 #[inline]
609 fn vmctx_dynamic_data_start(&self) -> u8 {
610 self.vmctx_type_ids_array() + self.size()
611 }
612}
613
614pub trait GetPtrSize {
616 type Ptr: PtrSize;
618
619 fn get_ptr_size(&self) -> &Self::Ptr;
621}
622
623impl<P> GetPtrSize for P
624where
625 P: PtrSize,
626{
627 type Ptr = Self;
628
629 #[inline]
630 fn get_ptr_size(&self) -> &Self::Ptr {
631 self
632 }
633}
634
635#[derive(Clone, Copy)]
637pub struct HostPtr;
638
639impl PtrSize for HostPtr {
640 #[inline]
641 fn size(&self) -> u8 {
642 core::mem::size_of::<usize>() as u8
643 }
644}
645
646impl PtrSize for u8 {
647 #[inline]
648 fn size(&self) -> u8 {
649 *self
650 }
651}
652
653#[derive(Debug, Clone, Copy)]
655pub struct VMOffsetsFields<P> {
656 pub ptr: P,
658 pub num_imported_functions: u32,
660 pub num_imported_tables: u32,
662 pub num_imported_memories: u32,
664 pub num_imported_globals: u32,
666 pub num_imported_tags: u32,
668 pub num_defined_tables: u32,
670 pub num_defined_memories: u32,
672 pub num_owned_memories: u32,
674 pub num_defined_globals: u32,
676 pub num_defined_tags: u32,
678 pub num_escaped_funcs: u32,
681 pub num_runtime_data: u32,
683 pub has_startup_func: bool,
685}
686
687impl<P: PtrSize> VMOffsets<P> {
688 pub fn new(ptr: P, module: &Module) -> Self {
690 let num_owned_memories = module
691 .memories
692 .iter()
693 .skip(module.num_imported_memories)
694 .filter(|p| !p.1.shared)
695 .count()
696 .try_into()
697 .unwrap();
698 VMOffsets::from(VMOffsetsFields {
699 ptr,
700 num_imported_functions: cast_to_u32(module.num_imported_funcs),
701 num_imported_tables: cast_to_u32(module.num_imported_tables),
702 num_imported_memories: cast_to_u32(module.num_imported_memories),
703 num_imported_globals: cast_to_u32(module.num_imported_globals),
704 num_imported_tags: cast_to_u32(module.num_imported_tags),
705 num_defined_tables: cast_to_u32(module.num_defined_tables()),
706 num_defined_memories: cast_to_u32(module.num_defined_memories()),
707 num_owned_memories,
708 num_defined_globals: cast_to_u32(module.globals.len() - module.num_imported_globals),
709 num_defined_tags: cast_to_u32(module.tags.len() - module.num_imported_tags),
710 num_escaped_funcs: cast_to_u32(module.num_escaped_funcs),
711 num_runtime_data: cast_to_u32(module.runtime_data.len()),
712 has_startup_func: !module.startup.is_none(),
713 })
714 }
715
716 #[inline]
718 pub fn pointer_size(&self) -> u8 {
719 self.ptr.size()
720 }
721
722 pub fn region_sizes(&self) -> impl Iterator<Item = (&str, u32)> {
727 macro_rules! calculate_sizes {
728 ($($name:ident: $desc:tt,)*) => {{
729 let VMOffsets {
730 ptr: _,
733 num_imported_functions: _,
734 num_imported_tables: _,
735 num_imported_memories: _,
736 num_imported_globals: _,
737 num_imported_tags: _,
738 num_defined_tables: _,
739 num_defined_globals: _,
740 num_defined_memories: _,
741 num_defined_tags: _,
742 num_owned_memories: _,
743 num_escaped_funcs: _,
744 num_runtime_data: _,
745 has_startup_func: _,
746
747 size,
749
750 $($name,)*
753 } = *self;
754
755 let mut last = size;
759 $(
760 assert!($name <= last);
761 let tmp = $name;
762 let $name = last - $name;
763 last = tmp;
764 )*
765 assert_ne!(last, 0);
766 IntoIterator::into_iter([
767 $(($desc, $name),)*
768 ("static vmctx data", last),
769 ])
770 }};
771 }
772
773 calculate_sizes! {
774 runtime_data_lengths: "runtime data lengths",
775 runtime_data_bases: "runtime data base pointers",
776 startup_func_ref: "startup funcref",
777 defined_func_refs: "module functions",
778 defined_tags: "defined tags",
779 defined_globals: "defined globals",
780 defined_tables: "defined tables",
781 imported_tags: "imported tags",
782 imported_globals: "imported globals",
783 imported_tables: "imported tables",
784 imported_functions: "imported functions",
785 owned_memories: "owned memories",
786 defined_memories: "defined memories",
787 imported_memories: "imported memories",
788 }
789 }
790}
791
792impl<P: PtrSize> GetPtrSize for VMOffsets<P> {
793 type Ptr = P;
794
795 #[inline]
796 fn get_ptr_size(&self) -> &Self::Ptr {
797 &self.ptr
798 }
799}
800
801impl<P: PtrSize> From<VMOffsetsFields<P>> for VMOffsets<P> {
802 fn from(fields: VMOffsetsFields<P>) -> VMOffsets<P> {
803 let mut ret = Self {
804 ptr: fields.ptr,
805 num_imported_functions: fields.num_imported_functions,
806 num_imported_tables: fields.num_imported_tables,
807 num_imported_memories: fields.num_imported_memories,
808 num_imported_globals: fields.num_imported_globals,
809 num_imported_tags: fields.num_imported_tags,
810 num_defined_tables: fields.num_defined_tables,
811 num_defined_memories: fields.num_defined_memories,
812 num_owned_memories: fields.num_owned_memories,
813 num_defined_globals: fields.num_defined_globals,
814 num_defined_tags: fields.num_defined_tags,
815 num_escaped_funcs: fields.num_escaped_funcs,
816 num_runtime_data: fields.num_runtime_data,
817 has_startup_func: fields.has_startup_func,
818 imported_functions: 0,
819 imported_tables: 0,
820 imported_memories: 0,
821 imported_globals: 0,
822 imported_tags: 0,
823 defined_tables: 0,
824 defined_memories: 0,
825 owned_memories: 0,
826 defined_globals: 0,
827 defined_tags: 0,
828 defined_func_refs: 0,
829 startup_func_ref: 0,
830 runtime_data_bases: 0,
831 runtime_data_lengths: 0,
832 size: 0,
833 };
834
835 #[inline]
840 fn cadd(count: u32, size: u32) -> u32 {
841 count.checked_add(size).unwrap()
842 }
843
844 #[inline]
845 fn cmul(count: u32, size: u8) -> u32 {
846 count.checked_mul(u32::from(size)).unwrap()
847 }
848
849 let mut next_field_offset = u32::from(ret.ptr.vmctx_dynamic_data_start());
850
851 macro_rules! fields {
852 (size($field:ident) = $size:expr, $($rest:tt)*) => {
853 ret.$field = next_field_offset;
854 next_field_offset = cadd(next_field_offset, u32::from($size));
855 fields!($($rest)*);
856 };
857 (align($align:expr), $($rest:tt)*) => {
858 next_field_offset = align(next_field_offset, $align);
859 fields!($($rest)*);
860 };
861 () => {};
862 }
863
864 fields! {
865 size(imported_memories)
866 = cmul(ret.num_imported_memories, ret.size_of_vmmemory_import()),
867 size(defined_memories)
868 = cmul(ret.num_defined_memories, ret.ptr.size_of_vmmemory_pointer()),
869 size(owned_memories)
870 = cmul(ret.num_owned_memories, ret.ptr.size_of_vmmemory_definition()),
871 size(imported_functions)
872 = cmul(ret.num_imported_functions, ret.size_of_vmfunction_import()),
873 size(imported_tables)
874 = cmul(ret.num_imported_tables, ret.size_of_vmtable_import()),
875 size(imported_globals)
876 = cmul(ret.num_imported_globals, ret.size_of_vmglobal_import()),
877 size(imported_tags)
878 = cmul(ret.num_imported_tags, ret.size_of_vmtag_import()),
879 size(defined_tables)
880 = cmul(ret.num_defined_tables, ret.size_of_vmtable_definition()),
881 align(16),
882 size(defined_globals)
883 = cmul(ret.num_defined_globals, ret.ptr.size_of_vmglobal_definition()),
884 size(defined_tags)
885 = cmul(ret.num_defined_tags, ret.ptr.size_of_vmtag_definition()),
886 size(defined_func_refs) = cmul(
887 ret.num_escaped_funcs,
888 ret.ptr.size_of_vm_func_ref(),
889 ),
890 size(startup_func_ref) = if ret.has_startup_func {
891 ret.ptr.size_of_vm_func_ref()
892 } else {
893 0
894 },
895 size(runtime_data_bases) = cmul(ret.num_runtime_data, ret.ptr.size()),
896 size(runtime_data_lengths) = cmul(ret.num_runtime_data, 4),
897 }
898
899 ret.size = next_field_offset;
900
901 return ret;
902 }
903}
904
905impl<P: PtrSize> VMOffsets<P> {
906 #[inline]
908 pub fn vmfunction_import_array_call(&self) -> u8 {
909 0 * self.pointer_size()
910 }
911
912 #[inline]
914 pub fn vmfunction_import_wasm_call(&self) -> u8 {
915 1 * self.pointer_size()
916 }
917
918 #[inline]
920 pub fn vmfunction_import_type_index(&self) -> u8 {
921 2 * self.pointer_size()
922 }
923
924 #[inline]
926 pub fn vmfunction_import_vmctx(&self) -> u8 {
927 3 * self.pointer_size()
928 }
929
930 #[inline]
932 pub fn size_of_vmfunction_import(&self) -> u8 {
933 4 * self.pointer_size()
934 }
935}
936
937impl<P: PtrSize> VMOffsets<P> {
939 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
941 1 * self.pointer_size()
942 }
943}
944
945impl<P: PtrSize> VMOffsets<P> {
947 #[inline]
949 pub fn vmtable_import_from(&self) -> u8 {
950 0 * self.pointer_size()
951 }
952
953 #[inline]
955 pub fn vmtable_import_vmctx(&self) -> u8 {
956 1 * self.pointer_size()
957 }
958
959 #[inline]
961 pub fn vmtable_import_index(&self) -> u8 {
962 2 * self.pointer_size()
963 }
964
965 #[inline]
967 pub fn size_of_vmtable_import(&self) -> u8 {
968 3 * self.pointer_size()
969 }
970}
971
972impl<P: PtrSize> VMOffsets<P> {
974 #[inline]
976 pub fn vmtable_definition_base(&self) -> u8 {
977 0 * self.pointer_size()
978 }
979
980 pub fn vmtable_definition_current_elements(&self) -> u8 {
982 1 * self.pointer_size()
983 }
984
985 #[inline]
987 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
988 self.pointer_size()
989 }
990
991 #[inline]
993 pub fn size_of_vmtable_definition(&self) -> u8 {
994 2 * self.pointer_size()
995 }
996}
997
998impl<P: PtrSize> VMOffsets<P> {
1000 #[inline]
1002 pub fn vmmemory_import_from(&self) -> u8 {
1003 0 * self.pointer_size()
1004 }
1005
1006 #[inline]
1008 pub fn vmmemory_import_vmctx(&self) -> u8 {
1009 1 * self.pointer_size()
1010 }
1011
1012 #[inline]
1014 pub fn vmmemory_import_index(&self) -> u8 {
1015 2 * self.pointer_size()
1016 }
1017
1018 #[inline]
1020 pub fn size_of_vmmemory_import(&self) -> u8 {
1021 3 * self.pointer_size()
1022 }
1023}
1024
1025impl<P: PtrSize> VMOffsets<P> {
1027 #[inline]
1029 pub fn vmglobal_import_from(&self) -> u8 {
1030 0 * self.pointer_size()
1031 }
1032
1033 #[inline]
1035 pub fn size_of_vmglobal_import(&self) -> u8 {
1036 2 * self.pointer_size() + 8
1038 }
1039}
1040
1041impl<P: PtrSize> VMOffsets<P> {
1043 #[inline]
1045 pub fn size_of_vmshared_type_index(&self) -> u8 {
1046 self.ptr.size_of_vmshared_type_index()
1047 }
1048}
1049
1050impl<P: PtrSize> VMOffsets<P> {
1052 #[inline]
1054 pub fn vmtag_import_from(&self) -> u8 {
1055 0 * self.pointer_size()
1056 }
1057
1058 #[inline]
1060 pub fn vmtag_import_vmctx(&self) -> u8 {
1061 1 * self.pointer_size()
1062 }
1063
1064 #[inline]
1066 pub fn vmtag_import_index(&self) -> u8 {
1067 2 * self.pointer_size()
1068 }
1069
1070 #[inline]
1072 pub fn size_of_vmtag_import(&self) -> u8 {
1073 3 * self.pointer_size()
1074 }
1075}
1076
1077impl<P: PtrSize> VMOffsets<P> {
1079 #[inline]
1081 pub fn vmctx_imported_functions_begin(&self) -> u32 {
1082 self.imported_functions
1083 }
1084
1085 #[inline]
1087 pub fn vmctx_imported_tables_begin(&self) -> u32 {
1088 self.imported_tables
1089 }
1090
1091 #[inline]
1093 pub fn vmctx_imported_memories_begin(&self) -> u32 {
1094 self.imported_memories
1095 }
1096
1097 #[inline]
1099 pub fn vmctx_imported_globals_begin(&self) -> u32 {
1100 self.imported_globals
1101 }
1102
1103 #[inline]
1105 pub fn vmctx_imported_tags_begin(&self) -> u32 {
1106 self.imported_tags
1107 }
1108
1109 #[inline]
1111 pub fn vmctx_tables_begin(&self) -> u32 {
1112 self.defined_tables
1113 }
1114
1115 #[inline]
1117 pub fn vmctx_memories_begin(&self) -> u32 {
1118 self.defined_memories
1119 }
1120
1121 #[inline]
1123 pub fn vmctx_owned_memories_begin(&self) -> u32 {
1124 self.owned_memories
1125 }
1126
1127 #[inline]
1129 pub fn vmctx_globals_begin(&self) -> u32 {
1130 self.defined_globals
1131 }
1132
1133 #[inline]
1135 pub fn vmctx_tags_begin(&self) -> u32 {
1136 self.defined_tags
1137 }
1138
1139 #[inline]
1141 pub fn vmctx_func_refs_begin(&self) -> u32 {
1142 self.defined_func_refs
1143 }
1144
1145 #[inline]
1147 pub fn vmctx_runtime_data_bases_begin(&self) -> u32 {
1148 self.runtime_data_bases
1149 }
1150
1151 #[inline]
1153 pub fn vmctx_runtime_data_lengths_begin(&self) -> u32 {
1154 self.runtime_data_lengths
1155 }
1156
1157 #[inline]
1159 pub fn size_of_vmctx(&self) -> u32 {
1160 self.size
1161 }
1162
1163 #[inline]
1165 pub fn vmctx_vmfunction_import(&self, index: FuncIndex) -> u32 {
1166 assert!(index.as_u32() < self.num_imported_functions);
1167 self.vmctx_imported_functions_begin()
1168 + index.as_u32() * u32::from(self.size_of_vmfunction_import())
1169 }
1170
1171 #[inline]
1173 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
1174 assert!(index.as_u32() < self.num_imported_tables);
1175 self.vmctx_imported_tables_begin()
1176 + index.as_u32() * u32::from(self.size_of_vmtable_import())
1177 }
1178
1179 #[inline]
1181 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
1182 assert!(index.as_u32() < self.num_imported_memories);
1183 self.vmctx_imported_memories_begin()
1184 + index.as_u32() * u32::from(self.size_of_vmmemory_import())
1185 }
1186
1187 #[inline]
1189 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
1190 assert!(index.as_u32() < self.num_imported_globals);
1191 self.vmctx_imported_globals_begin()
1192 + index.as_u32() * u32::from(self.size_of_vmglobal_import())
1193 }
1194
1195 #[inline]
1197 pub fn vmctx_vmtag_import(&self, index: TagIndex) -> u32 {
1198 assert!(index.as_u32() < self.num_imported_tags);
1199 self.vmctx_imported_tags_begin() + index.as_u32() * u32::from(self.size_of_vmtag_import())
1200 }
1201
1202 #[inline]
1204 pub fn vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32 {
1205 assert!(index.as_u32() < self.num_defined_tables);
1206 self.vmctx_tables_begin() + index.as_u32() * u32::from(self.size_of_vmtable_definition())
1207 }
1208
1209 #[inline]
1211 pub fn vmctx_vmmemory_pointer(&self, index: DefinedMemoryIndex) -> u32 {
1212 assert!(index.as_u32() < self.num_defined_memories);
1213 self.vmctx_memories_begin()
1214 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_pointer())
1215 }
1216
1217 #[inline]
1219 pub fn vmctx_vmmemory_definition(&self, index: OwnedMemoryIndex) -> u32 {
1220 assert!(index.as_u32() < self.num_owned_memories);
1221 self.vmctx_owned_memories_begin()
1222 + index.as_u32() * u32::from(self.ptr.size_of_vmmemory_definition())
1223 }
1224
1225 #[inline]
1227 pub fn vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32 {
1228 assert!(index.as_u32() < self.num_defined_globals);
1229 self.vmctx_globals_begin()
1230 + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())
1231 }
1232
1233 #[inline]
1235 pub fn vmctx_vmtag_definition(&self, index: DefinedTagIndex) -> u32 {
1236 assert!(index.as_u32() < self.num_defined_tags);
1237 self.vmctx_tags_begin() + index.as_u32() * u32::from(self.ptr.size_of_vmtag_definition())
1238 }
1239
1240 #[inline]
1243 pub fn vmctx_func_ref(&self, index: FuncRefIndex) -> u32 {
1244 assert!(!index.is_reserved_value());
1245 assert!(index.as_u32() < self.num_escaped_funcs);
1246 self.vmctx_func_refs_begin() + index.as_u32() * u32::from(self.ptr.size_of_vm_func_ref())
1247 }
1248
1249 #[inline]
1253 pub fn vmctx_startup_func_ref(&self) -> u32 {
1254 assert!(self.has_startup_func);
1255 self.startup_func_ref
1256 }
1257
1258 #[inline]
1260 pub fn vmctx_runtime_data_base(&self, index: RuntimeDataIndex) -> u32 {
1261 assert!(!index.is_reserved_value());
1262 assert!(index.as_u32() < self.num_runtime_data);
1263 self.vmctx_runtime_data_bases_begin() + index.as_u32() * u32::from(self.ptr.size())
1264 }
1265
1266 #[inline]
1268 pub fn vmctx_runtime_data_length(&self, index: RuntimeDataIndex) -> u32 {
1269 assert!(!index.is_reserved_value());
1270 assert!(index.as_u32() < self.num_runtime_data);
1271 self.vmctx_runtime_data_lengths_begin() + index.as_u32() * 4
1272 }
1273
1274 #[inline]
1276 pub fn vmctx_vmfunction_import_wasm_call(&self, index: FuncIndex) -> u32 {
1277 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_wasm_call())
1278 }
1279
1280 #[inline]
1282 pub fn vmctx_vmfunction_import_array_call(&self, index: FuncIndex) -> u32 {
1283 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_array_call())
1284 }
1285
1286 #[inline]
1288 pub fn vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32 {
1289 self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx())
1290 }
1291
1292 #[inline]
1295 pub fn vmctx_vmtable_from(&self, index: TableIndex) -> u32 {
1296 self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_from())
1297 }
1298
1299 #[inline]
1301 pub fn vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32 {
1302 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base())
1303 }
1304
1305 #[inline]
1307 pub fn vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32 {
1308 self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements())
1309 }
1310
1311 #[inline]
1313 pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 {
1314 self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_from())
1315 }
1316
1317 #[inline]
1319 pub fn vmctx_vmmemory_definition_base(&self, index: OwnedMemoryIndex) -> u32 {
1320 self.vmctx_vmmemory_definition(index) + u32::from(self.ptr.vmmemory_definition_base())
1321 }
1322
1323 #[inline]
1325 pub fn vmctx_vmmemory_definition_current_length(&self, index: OwnedMemoryIndex) -> u32 {
1326 self.vmctx_vmmemory_definition(index)
1327 + u32::from(self.ptr.vmmemory_definition_current_length())
1328 }
1329
1330 #[inline]
1332 pub fn vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32 {
1333 self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_from())
1334 }
1335
1336 #[inline]
1338 pub fn vmctx_vmtag_import_from(&self, index: TagIndex) -> u32 {
1339 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_from())
1340 }
1341
1342 #[inline]
1344 pub fn vmctx_vmtag_import_vmctx(&self, index: TagIndex) -> u32 {
1345 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_vmctx())
1346 }
1347
1348 #[inline]
1350 pub fn vmctx_vmtag_import_index(&self, index: TagIndex) -> u32 {
1351 self.vmctx_vmtag_import(index) + u32::from(self.vmtag_import_index())
1352 }
1353}
1354
1355impl<P: PtrSize> VMOffsets<P> {
1357 #[inline]
1359 pub fn vm_gc_header_kind(&self) -> u32 {
1360 0
1361 }
1362
1363 #[inline]
1365 pub fn vm_gc_header_reserved_bits(&self) -> u32 {
1366 self.vm_gc_header_kind()
1368 }
1369
1370 #[inline]
1372 pub fn vm_gc_header_ty(&self) -> u32 {
1373 self.vm_gc_header_kind() + 4
1374 }
1375}
1376
1377impl<P: PtrSize> VMOffsets<P> {
1381 #[inline]
1383 pub fn vm_drc_header_ref_count(&self) -> u32 {
1384 8
1385 }
1386
1387 #[inline]
1389 pub fn vm_drc_header_next_over_approximated_stack_root(&self) -> u32 {
1390 self.vm_drc_header_ref_count() + 8
1391 }
1392}
1393
1394pub const VMCONTEXT_MAGIC: u32 = u32::from_le_bytes(*b"core");
1398
1399pub const VM_ARRAY_CALL_HOST_FUNC_MAGIC: u32 = u32::from_le_bytes(*b"ACHF");
1404
1405#[cfg(test)]
1406mod tests {
1407 use crate::vmoffsets::align;
1408
1409 #[test]
1410 fn alignment() {
1411 fn is_aligned(x: u32) -> bool {
1412 x % 16 == 0
1413 }
1414 assert!(is_aligned(align(0, 16)));
1415 assert!(is_aligned(align(32, 16)));
1416 assert!(is_aligned(align(33, 16)));
1417 assert!(is_aligned(align(31, 16)));
1418 }
1419}
1420
1421pub const VM_LAZY_THREAD_FORCED: u64 = 1;