1mod allocator;
10
11use crate::LinearMemory;
12use crate::imports::Imports;
13use crate::store::{InternalStoreHandle, StoreObjects};
14use crate::table::TableElement;
15use crate::trap::{Trap, TrapCode};
16use crate::vmcontext::{
17 VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionContext,
18 VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition,
19 VMMemoryImport, VMSharedTagIndex, VMSignatureHash, VMTableDefinition, VMTableImport,
20 VMTrampoline, memory_copy, memory_fill, memory32_atomic_check32, memory32_atomic_check64,
21};
22use crate::{FunctionBodyPtr, MaybeInstanceOwned, TrapHandlerFn, VMTag, wasmer_call_trampoline};
23use crate::{VMConfig, VMFuncRef, VMFunction, VMGlobal, VMMemory, VMTable};
24use crate::{export::VMExtern, threadconditions::ExpectedValue};
25pub use allocator::InstanceAllocator;
26use itertools::Itertools;
27use memoffset::offset_of;
28use more_asserts::assert_lt;
29use std::alloc::Layout;
30use std::cell::RefCell;
31use std::collections::HashMap;
32use std::convert::TryFrom;
33use std::fmt;
34use std::mem;
35use std::ptr::{self, NonNull};
36use std::slice;
37use std::sync::Arc;
38use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap, packed_option::ReservedValue};
39use wasmer_types::{
40 DataIndex, DataInitializer, ElemIndex, ExportIndex, FunctionIndex, GlobalIndex, GlobalInit,
41 InitExpr, InitExprOp, LocalFunctionIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex,
42 MemoryError, MemoryIndex, ModuleInfo, Pages, RawValue, SignatureIndex, TableIndex, TagIndex,
43 VMOffsets,
44};
45
46#[repr(C)]
53#[allow(clippy::type_complexity)]
54pub(crate) struct Instance {
55 module: Arc<ModuleInfo>,
57
58 context: *mut StoreObjects,
60
61 offsets: VMOffsets,
63
64 memories: BoxedSlice<LocalMemoryIndex, InternalStoreHandle<VMMemory>>,
66
67 tables: BoxedSlice<LocalTableIndex, InternalStoreHandle<VMTable>>,
69
70 globals: BoxedSlice<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>,
72
73 tags: BoxedSlice<TagIndex, InternalStoreHandle<VMTag>>,
75
76 functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
78
79 function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
81
82 passive_elements: RefCell<HashMap<ElemIndex, Box<[Option<VMFuncRef>]>>>,
85
86 passive_data: RefCell<HashMap<DataIndex, Arc<[u8]>>>,
89
90 funcrefs: BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
93
94 imported_funcrefs: BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
97
98 vmctx: VMContext,
103}
104
105impl fmt::Debug for Instance {
106 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107 formatter.debug_struct("Instance").finish()
108 }
109}
110
111#[allow(clippy::cast_ptr_alignment)]
112impl Instance {
113 unsafe fn vmctx_plus_offset<T>(&self, offset: u32) -> *mut T {
116 unsafe {
117 (self.vmctx_ptr() as *mut u8)
118 .add(usize::try_from(offset).unwrap())
119 .cast()
120 }
121 }
122
123 fn module(&self) -> &Arc<ModuleInfo> {
124 &self.module
125 }
126
127 pub(crate) fn module_ref(&self) -> &ModuleInfo {
128 &self.module
129 }
130
131 pub(crate) fn context(&self) -> &StoreObjects {
132 unsafe { &*self.context }
133 }
134
135 pub(crate) fn context_mut(&mut self) -> &mut StoreObjects {
136 unsafe { &mut *self.context }
137 }
138
139 fn offsets(&self) -> &VMOffsets {
141 &self.offsets
142 }
143
144 fn imported_function(&self, index: FunctionIndex) -> &VMFunctionImport {
146 let index = usize::try_from(index.as_u32()).unwrap();
147 unsafe { &*self.imported_functions_ptr().add(index) }
148 }
149
150 fn imported_functions_ptr(&self) -> *mut VMFunctionImport {
152 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_functions_begin()) }
153 }
154
155 fn imported_table(&self, index: TableIndex) -> &VMTableImport {
157 let index = usize::try_from(index.as_u32()).unwrap();
158 unsafe { &*self.imported_tables_ptr().add(index) }
159 }
160
161 fn imported_tables_ptr(&self) -> *mut VMTableImport {
163 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_tables_begin()) }
164 }
165
166 fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
168 let index = usize::try_from(index.as_u32()).unwrap();
169 unsafe { &*self.imported_memories_ptr().add(index) }
170 }
171
172 fn imported_memories_ptr(&self) -> *mut VMMemoryImport {
174 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_memories_begin()) }
175 }
176
177 fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
179 let index = usize::try_from(index.as_u32()).unwrap();
180 unsafe { &*self.imported_globals_ptr().add(index) }
181 }
182
183 fn imported_globals_ptr(&self) -> *mut VMGlobalImport {
185 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_globals_begin()) }
186 }
187
188 #[cfg_attr(target_os = "windows", allow(dead_code))]
190 pub(crate) fn shared_tag_ptr(&self, index: TagIndex) -> &VMSharedTagIndex {
191 let index = usize::try_from(index.as_u32()).unwrap();
192 unsafe { &*self.shared_tags_ptr().add(index) }
193 }
194
195 pub(crate) fn shared_tags_ptr(&self) -> *mut VMSharedTagIndex {
197 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tag_ids_begin()) }
198 }
199
200 #[allow(dead_code)]
202 fn table(&self, index: LocalTableIndex) -> VMTableDefinition {
203 unsafe { *self.table_ptr(index).as_ref() }
204 }
205
206 #[allow(dead_code)]
207 fn set_table(&self, index: LocalTableIndex, table: &VMTableDefinition) {
209 unsafe {
210 *self.table_ptr(index).as_ptr() = *table;
211 }
212 }
213
214 fn table_ptr(&self, index: LocalTableIndex) -> NonNull<VMTableDefinition> {
216 let index = usize::try_from(index.as_u32()).unwrap();
217 NonNull::new(unsafe { self.tables_ptr().add(index) }).unwrap()
218 }
219
220 fn tables_ptr(&self) -> *mut VMTableDefinition {
222 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tables_begin()) }
223 }
224
225 fn fixed_funcref_table_ptr(
226 &self,
227 index: LocalTableIndex,
228 ) -> Option<NonNull<VMCallerCheckedAnyfunc>> {
229 let offset = self.offsets.vmctx_fixed_funcref_table_anyfuncs(index)?;
230 Some(NonNull::new(unsafe { self.vmctx_plus_offset(offset) }).unwrap())
231 }
232
233 fn sync_fixed_funcref_table_element(
234 &self,
235 table_index: LocalTableIndex,
236 index: u32,
237 funcref: Option<VMFuncRef>,
238 ) {
239 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
240 return;
241 };
242 unsafe {
243 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
244 }
245 }
246
247 fn sync_fixed_funcref_table(&self, table_index: LocalTableIndex) {
248 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
249 return;
250 };
251 let table = self.tables[table_index].get(self.context());
252 for index in 0..table.size() {
253 let TableElement::FuncRef(funcref) = table.get(index).unwrap() else {
254 unreachable!("fixed funcref tables cannot contain externrefs");
255 };
256 unsafe {
257 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
258 }
259 }
260 }
261
262 fn sync_fixed_funcref_table_by_index(&self, table_index: TableIndex) {
263 if let Some(local_table_index) = self.module.local_table_index(table_index) {
264 self.sync_fixed_funcref_table(local_table_index);
265 }
266 }
267
268 #[allow(dead_code)]
269 fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition {
271 if let Some(local_index) = self.module.local_memory_index(index) {
272 self.memory(local_index)
273 } else {
274 let import = self.imported_memory(index);
275 unsafe { *import.definition.as_ref() }
276 }
277 }
278
279 fn memory(&self, index: LocalMemoryIndex) -> VMMemoryDefinition {
281 unsafe { *self.memory_ptr(index).as_ref() }
282 }
283
284 #[allow(dead_code)]
285 fn set_memory(&self, index: LocalMemoryIndex, mem: &VMMemoryDefinition) {
287 unsafe {
288 *self.memory_ptr(index).as_ptr() = *mem;
289 }
290 }
291
292 fn memory_ptr(&self, index: LocalMemoryIndex) -> NonNull<VMMemoryDefinition> {
294 let index = usize::try_from(index.as_u32()).unwrap();
295 NonNull::new(unsafe { self.memories_ptr().add(index) }).unwrap()
296 }
297
298 fn memories_ptr(&self) -> *mut VMMemoryDefinition {
300 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_memories_begin()) }
301 }
302
303 fn get_vmmemory(&self, index: MemoryIndex) -> &VMMemory {
305 if let Some(local_index) = self.module.local_memory_index(index) {
306 unsafe {
307 self.memories
308 .get(local_index)
309 .unwrap()
310 .get(self.context.as_ref().unwrap())
311 }
312 } else {
313 let import = self.imported_memory(index);
314 unsafe { import.handle.get(self.context.as_ref().unwrap()) }
315 }
316 }
317
318 fn get_vmmemory_mut(&mut self, index: MemoryIndex) -> &mut VMMemory {
320 if let Some(local_index) = self.module.local_memory_index(index) {
321 unsafe {
322 self.memories
323 .get_mut(local_index)
324 .unwrap()
325 .get_mut(self.context.as_mut().unwrap())
326 }
327 } else {
328 let import = self.imported_memory(index);
329 unsafe { import.handle.get_mut(self.context.as_mut().unwrap()) }
330 }
331 }
332
333 fn get_local_vmmemory_mut(&mut self, local_index: LocalMemoryIndex) -> &mut VMMemory {
335 unsafe {
336 self.memories
337 .get_mut(local_index)
338 .unwrap()
339 .get_mut(self.context.as_mut().unwrap())
340 }
341 }
342
343 fn global(&self, index: LocalGlobalIndex) -> VMGlobalDefinition {
345 unsafe { self.global_ptr(index).as_ref().clone() }
346 }
347
348 #[allow(dead_code)]
350 fn set_global(&self, index: LocalGlobalIndex, global: &VMGlobalDefinition) {
351 unsafe {
352 *self.global_ptr(index).as_ptr() = global.clone();
353 }
354 }
355
356 fn global_ptr(&self, index: LocalGlobalIndex) -> NonNull<VMGlobalDefinition> {
358 let index = usize::try_from(index.as_u32()).unwrap();
359 NonNull::new(unsafe { self.globals_ptr().add(index) }).unwrap()
360 }
361
362 fn globals_ptr(&self) -> *mut VMGlobalDefinition {
364 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_globals_begin()) }
365 }
366
367 fn builtin_functions_ptr(&self) -> *mut VMBuiltinFunctionsArray {
369 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_builtin_functions_begin()) }
370 }
371
372 fn vmctx(&self) -> &VMContext {
374 &self.vmctx
375 }
376
377 fn vmctx_ptr(&self) -> *mut VMContext {
379 self.vmctx() as *const VMContext as *mut VMContext
380 }
381
382 fn invoke_start_function(
384 &self,
385 config: &VMConfig,
386 trap_handler: Option<*const TrapHandlerFn<'static>>,
387 ) -> Result<(), Trap> {
388 let start_index = match self.module.start_function {
389 Some(idx) => idx,
390 None => return Ok(()),
391 };
392
393 let (callee_address, callee_vmctx) = match self.module.local_func_index(start_index) {
394 Some(local_index) => {
395 let body = self
396 .functions
397 .get(local_index)
398 .expect("function index is out of bounds")
399 .0;
400 (
401 body as *const _,
402 VMFunctionContext {
403 vmctx: self.vmctx_ptr(),
404 },
405 )
406 }
407 None => {
408 assert_lt!(start_index.index(), self.module.num_imported_functions);
409 let import = self.imported_function(start_index);
410 (import.body, import.environment)
411 }
412 };
413
414 let sig = self.module.functions[start_index];
415 let trampoline = self.function_call_trampolines[sig];
416 let mut values_vec = vec![];
417
418 unsafe {
419 wasmer_call_trampoline(
423 trap_handler,
424 config,
425 callee_vmctx,
426 trampoline,
427 callee_address,
428 values_vec.as_mut_ptr(),
429 )
430 }
431 }
432
433 #[inline]
435 pub(crate) fn vmctx_offset() -> isize {
436 offset_of!(Self, vmctx) as isize
437 }
438
439 pub(crate) fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex {
441 let begin: *const VMTableDefinition = self.tables_ptr() as *const _;
442 let end: *const VMTableDefinition = table;
443 let index = LocalTableIndex::new(
445 (end as usize - begin as usize) / mem::size_of::<VMTableDefinition>(),
446 );
447 assert_lt!(index.index(), self.tables.len());
448 index
449 }
450
451 pub(crate) fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex {
453 let begin: *const VMMemoryDefinition = self.memories_ptr() as *const _;
454 let end: *const VMMemoryDefinition = memory;
455 let index = LocalMemoryIndex::new(
457 (end as usize - begin as usize) / mem::size_of::<VMMemoryDefinition>(),
458 );
459 assert_lt!(index.index(), self.memories.len());
460 index
461 }
462
463 pub(crate) fn memory_grow<IntoPages>(
468 &mut self,
469 memory_index: LocalMemoryIndex,
470 delta: IntoPages,
471 ) -> Result<Pages, MemoryError>
472 where
473 IntoPages: Into<Pages>,
474 {
475 let mem = *self
476 .memories
477 .get(memory_index)
478 .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
479 mem.get_mut(self.context_mut()).grow(delta.into())
480 }
481
482 pub(crate) unsafe fn imported_memory_grow<IntoPages>(
491 &mut self,
492 memory_index: MemoryIndex,
493 delta: IntoPages,
494 ) -> Result<Pages, MemoryError>
495 where
496 IntoPages: Into<Pages>,
497 {
498 let import = self.imported_memory(memory_index);
499 let mem = import.handle;
500 mem.get_mut(self.context_mut()).grow(delta.into())
501 }
502
503 pub(crate) fn memory_size(&self, memory_index: LocalMemoryIndex) -> Pages {
505 let mem = *self
506 .memories
507 .get(memory_index)
508 .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
509 mem.get(self.context()).size()
510 }
511
512 pub(crate) unsafe fn imported_memory_size(&self, memory_index: MemoryIndex) -> Pages {
518 let import = self.imported_memory(memory_index);
519 let mem = import.handle;
520 mem.get(self.context()).size()
521 }
522
523 pub(crate) fn table_size(&self, table_index: LocalTableIndex) -> u32 {
525 let table = self
526 .tables
527 .get(table_index)
528 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
529 table.get(self.context()).size()
530 }
531
532 pub(crate) unsafe fn imported_table_size(&self, table_index: TableIndex) -> u32 {
537 let import = self.imported_table(table_index);
538 let table = import.handle;
539 table.get(self.context()).size()
540 }
541
542 pub(crate) fn table_grow(
547 &mut self,
548 table_index: LocalTableIndex,
549 delta: u32,
550 init_value: TableElement,
551 ) -> Option<u32> {
552 let table = *self
553 .tables
554 .get(table_index)
555 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
556 table.get_mut(self.context_mut()).grow(delta, init_value)
557 }
558
559 pub(crate) unsafe fn imported_table_grow(
564 &mut self,
565 table_index: TableIndex,
566 delta: u32,
567 init_value: TableElement,
568 ) -> Option<u32> {
569 let import = self.imported_table(table_index);
570 let table = import.handle;
571 table.get_mut(self.context_mut()).grow(delta, init_value)
572 }
573
574 pub(crate) fn table_get(
576 &self,
577 table_index: LocalTableIndex,
578 index: u32,
579 ) -> Option<TableElement> {
580 let table = self
581 .tables
582 .get(table_index)
583 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
584 table.get(self.context()).get(index)
585 }
586
587 pub(crate) unsafe fn imported_table_get(
592 &self,
593 table_index: TableIndex,
594 index: u32,
595 ) -> Option<TableElement> {
596 let import = self.imported_table(table_index);
597 let table = import.handle;
598 table.get(self.context()).get(index)
599 }
600
601 pub(crate) fn table_set(
603 &mut self,
604 table_index: LocalTableIndex,
605 index: u32,
606 val: TableElement,
607 ) -> Result<(), Trap> {
608 let table = *self
609 .tables
610 .get(table_index)
611 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
612 let funcref = match &val {
613 TableElement::FuncRef(funcref) => Some(*funcref),
614 TableElement::ExternRef(_) => None,
615 };
616 table.get_mut(self.context_mut()).set(index, val)?;
617 if let Some(funcref) = funcref {
618 self.sync_fixed_funcref_table_element(table_index, index, funcref);
619 }
620 Ok(())
621 }
622
623 pub(crate) unsafe fn imported_table_set(
628 &mut self,
629 table_index: TableIndex,
630 index: u32,
631 val: TableElement,
632 ) -> Result<(), Trap> {
633 let import = self.imported_table(table_index);
634 let table = import.handle;
635 table.get_mut(self.context_mut()).set(index, val)
636 }
637
638 pub(crate) fn func_ref(&self, function_index: FunctionIndex) -> Option<VMFuncRef> {
640 if function_index == FunctionIndex::reserved_value() {
641 None
642 } else if let Some(local_function_index) = self.module.local_func_index(function_index) {
643 Some(VMFuncRef(NonNull::from(
644 &self.funcrefs[local_function_index],
645 )))
646 } else {
647 Some(VMFuncRef(self.imported_funcrefs[function_index]))
648 }
649 }
650
651 pub(crate) fn table_init(
659 &mut self,
660 table_index: TableIndex,
661 elem_index: ElemIndex,
662 dst: u32,
663 src: u32,
664 len: u32,
665 ) -> Result<(), Trap> {
666 let table = self.get_table_handle(table_index);
669 let table = unsafe { table.get_mut(&mut *self.context) };
670 let passive_elements = self.passive_elements.borrow();
671 let elem = passive_elements
672 .get(&elem_index)
673 .map_or::<&[Option<VMFuncRef>], _>(&[], |e| &**e);
674
675 if src.checked_add(len).is_none_or(|n| n as usize > elem.len())
676 || dst.checked_add(len).is_none_or(|m| m > table.size())
677 {
678 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
679 }
680
681 for (dst, src) in (dst..dst + len).zip(src..src + len) {
682 table
683 .set(dst, TableElement::FuncRef(elem[src as usize]))
684 .expect("should never panic because we already did the bounds check above");
685 }
686
687 self.sync_fixed_funcref_table_by_index(table_index);
688
689 Ok(())
690 }
691
692 pub(crate) fn table_fill(
698 &mut self,
699 table_index: TableIndex,
700 start_index: u32,
701 item: TableElement,
702 len: u32,
703 ) -> Result<(), Trap> {
704 let table = self.get_table(table_index);
707 let table_size = table.size() as usize;
708
709 if start_index
710 .checked_add(len)
711 .is_none_or(|n| n as usize > table_size)
712 {
713 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
714 }
715
716 for i in start_index..(start_index + len) {
717 table
718 .set(i, item.clone())
719 .expect("should never panic because we already did the bounds check above");
720 }
721
722 self.sync_fixed_funcref_table_by_index(table_index);
723
724 Ok(())
725 }
726
727 pub(crate) fn table_copy(
729 &mut self,
730 dst_table_index: TableIndex,
731 src_table_index: TableIndex,
732 dst: u32,
733 src: u32,
734 len: u32,
735 ) -> Result<(), Trap> {
736 let result = if dst_table_index == src_table_index {
737 let table = self.get_table(dst_table_index);
738 table.copy_within(dst, src, len)
739 } else {
740 let dst_table = self.get_table_handle(dst_table_index);
741 let src_table = self.get_table_handle(src_table_index);
742 if dst_table == src_table {
743 unsafe {
744 dst_table
745 .get_mut(&mut *self.context)
746 .copy_within(dst, src, len)
747 }
748 } else {
749 unsafe {
750 dst_table.get_mut(&mut *self.context).copy(
751 src_table.get(&*self.context),
752 dst,
753 src,
754 len,
755 )
756 }
757 }
758 };
759 result?;
760 self.sync_fixed_funcref_table_by_index(dst_table_index);
761
762 Ok(())
763 }
764
765 pub(crate) fn elem_drop(&self, elem_index: ElemIndex) {
767 let mut passive_elements = self.passive_elements.borrow_mut();
770 passive_elements.remove(&elem_index);
771 }
774
775 pub(crate) fn local_memory_copy(
782 &self,
783 memory_index: LocalMemoryIndex,
784 dst: u32,
785 src: u32,
786 len: u32,
787 ) -> Result<(), Trap> {
788 let memory = self.memory(memory_index);
791 unsafe { memory_copy(&memory, dst, src, len) }
793 }
794
795 pub(crate) fn imported_memory_copy(
797 &self,
798 memory_index: MemoryIndex,
799 dst: u32,
800 src: u32,
801 len: u32,
802 ) -> Result<(), Trap> {
803 let import = self.imported_memory(memory_index);
804 let memory = unsafe { import.definition.as_ref() };
805 unsafe { memory_copy(memory, dst, src, len) }
807 }
808
809 pub(crate) fn local_memory_fill(
815 &self,
816 memory_index: LocalMemoryIndex,
817 dst: u32,
818 val: u32,
819 len: u32,
820 ) -> Result<(), Trap> {
821 let memory = self.memory(memory_index);
822 unsafe { memory_fill(&memory, dst, val, len) }
824 }
825
826 pub(crate) fn imported_memory_fill(
832 &self,
833 memory_index: MemoryIndex,
834 dst: u32,
835 val: u32,
836 len: u32,
837 ) -> Result<(), Trap> {
838 let import = self.imported_memory(memory_index);
839 let memory = unsafe { import.definition.as_ref() };
840 unsafe { memory_fill(memory, dst, val, len) }
842 }
843
844 pub(crate) fn memory_init(
852 &self,
853 memory_index: MemoryIndex,
854 data_index: DataIndex,
855 dst: u32,
856 src: u32,
857 len: u32,
858 ) -> Result<(), Trap> {
859 let memory = self.get_vmmemory(memory_index);
862 let passive_data = self.passive_data.borrow();
863 let data = passive_data.get(&data_index).map_or(&[][..], |d| &**d);
864
865 let current_length = unsafe { memory.vmmemory().as_ref().current_length };
866 if src.checked_add(len).is_none_or(|n| n as usize > data.len())
867 || dst
868 .checked_add(len)
869 .is_none_or(|m| usize::try_from(m).unwrap() > current_length)
870 {
871 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
872 }
873 let src_slice = &data[src as usize..(src + len) as usize];
874 unsafe { memory.initialize_with_data(dst as usize, src_slice) }
875 }
876
877 pub(crate) fn data_drop(&self, data_index: DataIndex) {
879 let mut passive_data = self.passive_data.borrow_mut();
880 passive_data.remove(&data_index);
881 }
882
883 pub(crate) fn get_table(&mut self, table_index: TableIndex) -> &mut VMTable {
886 if let Some(local_table_index) = self.module.local_table_index(table_index) {
887 self.get_local_table(local_table_index)
888 } else {
889 self.get_foreign_table(table_index)
890 }
891 }
892
893 pub(crate) fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
895 let table = self.tables[index];
896 table.get_mut(self.context_mut())
897 }
898
899 pub(crate) fn get_foreign_table(&mut self, index: TableIndex) -> &mut VMTable {
901 let import = self.imported_table(index);
902 let table = import.handle;
903 table.get_mut(self.context_mut())
904 }
905
906 pub(crate) fn get_table_handle(
909 &mut self,
910 table_index: TableIndex,
911 ) -> InternalStoreHandle<VMTable> {
912 if let Some(local_table_index) = self.module.local_table_index(table_index) {
913 self.tables[local_table_index]
914 } else {
915 self.imported_table(table_index).handle
916 }
917 }
918
919 unsafe fn memory_wait(
922 memory: &mut VMMemory,
923 dst: u32,
924 expected: ExpectedValue,
925 timeout: i64,
926 ) -> Result<u32, Trap> {
927 let timeout = if timeout < 0 {
928 None
929 } else {
930 Some(std::time::Duration::from_nanos(timeout as u64))
931 };
932 match unsafe { memory.do_wait(dst, expected, timeout) } {
933 Ok(count) => Ok(count),
934 Err(_err) => Err(Trap::lib(TrapCode::HostInterrupt)),
935 }
936 }
937
938 pub(crate) fn local_memory_wait32(
940 &mut self,
941 memory_index: LocalMemoryIndex,
942 dst: u32,
943 val: u32,
944 timeout: i64,
945 ) -> Result<u32, Trap> {
946 let memory = self.memory(memory_index);
947 let ret = unsafe { memory32_atomic_check32(&memory, dst, val) };
953
954 if let Ok(mut ret) = ret {
955 if ret == 0 {
956 let memory = self.get_local_vmmemory_mut(memory_index);
957 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
959 }
960 Ok(ret)
961 } else {
962 ret
963 }
964 }
965
966 pub(crate) fn imported_memory_wait32(
968 &mut self,
969 memory_index: MemoryIndex,
970 dst: u32,
971 val: u32,
972 timeout: i64,
973 ) -> Result<u32, Trap> {
974 let import = self.imported_memory(memory_index);
975 let memory = unsafe { import.definition.as_ref() };
976 let ret = unsafe { memory32_atomic_check32(memory, dst, val) };
982
983 if let Ok(mut ret) = ret {
984 if ret == 0 {
985 let memory = self.get_vmmemory_mut(memory_index);
986 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
988 }
989 Ok(ret)
990 } else {
991 ret
992 }
993 }
994
995 pub(crate) fn local_memory_wait64(
997 &mut self,
998 memory_index: LocalMemoryIndex,
999 dst: u32,
1000 val: u64,
1001 timeout: i64,
1002 ) -> Result<u32, Trap> {
1003 let memory = self.memory(memory_index);
1004 let ret = unsafe { memory32_atomic_check64(&memory, dst, val) };
1010
1011 if let Ok(mut ret) = ret {
1012 if ret == 0 {
1013 let memory = self.get_local_vmmemory_mut(memory_index);
1014 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1016 }
1017 Ok(ret)
1018 } else {
1019 ret
1020 }
1021 }
1022
1023 pub(crate) fn imported_memory_wait64(
1025 &mut self,
1026 memory_index: MemoryIndex,
1027 dst: u32,
1028 val: u64,
1029 timeout: i64,
1030 ) -> Result<u32, Trap> {
1031 let import = self.imported_memory(memory_index);
1032 let memory = unsafe { import.definition.as_ref() };
1033 let ret = unsafe { memory32_atomic_check64(memory, dst, val) };
1039
1040 if let Ok(mut ret) = ret {
1041 if ret == 0 {
1042 let memory = self.get_vmmemory_mut(memory_index);
1043 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1045 }
1046 Ok(ret)
1047 } else {
1048 ret
1049 }
1050 }
1051
1052 pub(crate) fn local_memory_notify(
1054 &mut self,
1055 memory_index: LocalMemoryIndex,
1056 dst: u32,
1057 count: u32,
1058 ) -> Result<u32, Trap> {
1059 let memory = self.get_local_vmmemory_mut(memory_index);
1060 Ok(memory.do_notify(dst, count))
1061 }
1062
1063 pub(crate) fn imported_memory_notify(
1065 &mut self,
1066 memory_index: MemoryIndex,
1067 dst: u32,
1068 count: u32,
1069 ) -> Result<u32, Trap> {
1070 let memory = self.get_vmmemory_mut(memory_index);
1071 Ok(memory.do_notify(dst, count))
1072 }
1073}
1074
1075#[derive(Debug, Eq, PartialEq)]
1080pub struct VMInstance {
1081 instance_layout: Layout,
1083
1084 instance: NonNull<Instance>,
1094}
1095
1096impl Drop for VMInstance {
1100 fn drop(&mut self) {
1101 let instance_ptr = self.instance.as_ptr();
1102
1103 unsafe {
1104 instance_ptr.drop_in_place();
1106 std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
1108 }
1109 }
1110}
1111
1112impl VMInstance {
1113 #[allow(clippy::too_many_arguments)]
1135 pub unsafe fn new(
1136 allocator: InstanceAllocator,
1137 module: Arc<ModuleInfo>,
1138 context: &mut StoreObjects,
1139 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1140 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
1141 finished_memories: BoxedSlice<LocalMemoryIndex, InternalStoreHandle<VMMemory>>,
1142 finished_tables: BoxedSlice<LocalTableIndex, InternalStoreHandle<VMTable>>,
1143 finished_globals: BoxedSlice<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>,
1144 tags: BoxedSlice<TagIndex, InternalStoreHandle<VMTag>>,
1145 imports: Imports,
1146 vmshared_signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
1147 ) -> Result<Self, Trap> {
1148 unsafe {
1149 let vmctx_tags = tags
1150 .values()
1151 .map(|m: &InternalStoreHandle<VMTag>| VMSharedTagIndex::new(m.index() as u32))
1152 .collect::<PrimaryMap<TagIndex, VMSharedTagIndex>>()
1153 .into_boxed_slice();
1154 let passive_data = RefCell::new(
1155 module
1156 .passive_data
1157 .clone()
1158 .into_iter()
1159 .map(|(idx, bytes)| (idx, Arc::from(bytes)))
1160 .collect::<HashMap<_, _>>(),
1161 );
1162
1163 let handle = {
1164 let offsets = allocator.offsets().clone();
1165 let funcrefs = PrimaryMap::new().into_boxed_slice();
1167 let imported_funcrefs = PrimaryMap::new().into_boxed_slice();
1168 let instance = Instance {
1170 module,
1171 context,
1172 offsets,
1173 memories: finished_memories,
1174 tables: finished_tables,
1175 tags,
1176 globals: finished_globals,
1177 functions: finished_functions,
1178 function_call_trampolines: finished_function_call_trampolines,
1179 passive_elements: Default::default(),
1180 passive_data,
1181 funcrefs,
1182 imported_funcrefs,
1183 vmctx: VMContext {},
1184 };
1185
1186 let mut instance_handle = allocator.into_vminstance(instance);
1187
1188 {
1190 let instance = instance_handle.instance_mut();
1191 let vmctx_ptr = instance.vmctx_ptr();
1192 (instance.funcrefs, instance.imported_funcrefs) = build_funcrefs(
1193 &instance.module,
1194 context,
1195 &imports,
1196 &instance.functions,
1197 &vmshared_signatures,
1198 &instance.function_call_trampolines,
1199 vmctx_ptr,
1200 );
1201 for local_table_index in instance.tables.keys() {
1202 instance.sync_fixed_funcref_table(local_table_index);
1203 }
1204 }
1205
1206 instance_handle
1207 };
1208 let instance = handle.instance();
1209
1210 ptr::copy(
1211 vmctx_tags.values().as_slice().as_ptr(),
1212 instance.shared_tags_ptr(),
1213 vmctx_tags.len(),
1214 );
1215 ptr::copy(
1216 imports.functions.values().as_slice().as_ptr(),
1217 instance.imported_functions_ptr(),
1218 imports.functions.len(),
1219 );
1220 ptr::copy(
1221 imports.tables.values().as_slice().as_ptr(),
1222 instance.imported_tables_ptr(),
1223 imports.tables.len(),
1224 );
1225 ptr::copy(
1226 imports.memories.values().as_slice().as_ptr(),
1227 instance.imported_memories_ptr(),
1228 imports.memories.len(),
1229 );
1230 ptr::copy(
1231 imports.globals.values().as_slice().as_ptr(),
1232 instance.imported_globals_ptr(),
1233 imports.globals.len(),
1234 );
1235 ptr::write(
1239 instance.builtin_functions_ptr(),
1240 VMBuiltinFunctionsArray::initialized(),
1241 );
1242
1243 initialize_passive_elements(instance);
1246 initialize_globals(instance);
1247
1248 Ok(handle)
1249 }
1250 }
1251
1252 pub(crate) fn instance(&self) -> &Instance {
1254 unsafe { self.instance.as_ref() }
1255 }
1256
1257 pub(crate) fn instance_mut(&mut self) -> &mut Instance {
1259 unsafe { self.instance.as_mut() }
1260 }
1261
1262 pub unsafe fn finish_instantiation(
1268 &mut self,
1269 config: &VMConfig,
1270 trap_handler: Option<*const TrapHandlerFn<'static>>,
1271 data_initializers: &[DataInitializer<'_>],
1272 ) -> Result<(), Trap> {
1273 let instance = self.instance_mut();
1274
1275 initialize_tables(instance)?;
1277 initialize_memories(instance, data_initializers)?;
1278
1279 instance.invoke_start_function(config, trap_handler)?;
1282 Ok(())
1283 }
1284
1285 pub fn vmctx(&self) -> &VMContext {
1287 self.instance().vmctx()
1288 }
1289
1290 pub fn vmctx_ptr(&self) -> *mut VMContext {
1292 self.instance().vmctx_ptr()
1293 }
1294
1295 pub fn vmoffsets(&self) -> &VMOffsets {
1299 self.instance().offsets()
1300 }
1301
1302 pub fn module(&self) -> &Arc<ModuleInfo> {
1304 self.instance().module()
1305 }
1306
1307 pub fn module_ref(&self) -> &ModuleInfo {
1309 self.instance().module_ref()
1310 }
1311
1312 pub fn lookup(&mut self, field: &str) -> Option<VMExtern> {
1314 let export = *self.module_ref().exports.get(field)?;
1315
1316 Some(self.lookup_by_declaration(export))
1317 }
1318
1319 pub fn lookup_by_declaration(&mut self, export: ExportIndex) -> VMExtern {
1321 let instance = self.instance();
1322
1323 match export {
1324 ExportIndex::Function(index) => {
1325 let sig_index = &instance.module.functions[index];
1326 let handle = if let Some(def_index) = instance.module.local_func_index(index) {
1327 let signature = instance.module.signatures[*sig_index].clone();
1330 let vm_function = VMFunction {
1331 anyfunc: MaybeInstanceOwned::Instance(NonNull::from(
1332 &instance.funcrefs[def_index],
1333 )),
1334 signature,
1335 kind: VMFunctionKind::Static,
1340 host_data: Box::new(()),
1341 };
1342 InternalStoreHandle::new(self.instance_mut().context_mut(), vm_function)
1343 } else {
1344 let import = instance.imported_function(index);
1345 import.handle
1346 };
1347
1348 VMExtern::Function(handle)
1349 }
1350 ExportIndex::Table(index) => {
1351 let handle = if let Some(def_index) = instance.module.local_table_index(index) {
1352 instance.tables[def_index]
1353 } else {
1354 let import = instance.imported_table(index);
1355 import.handle
1356 };
1357 VMExtern::Table(handle)
1358 }
1359 ExportIndex::Memory(index) => {
1360 let handle = if let Some(def_index) = instance.module.local_memory_index(index) {
1361 instance.memories[def_index]
1362 } else {
1363 let import = instance.imported_memory(index);
1364 import.handle
1365 };
1366 VMExtern::Memory(handle)
1367 }
1368 ExportIndex::Global(index) => {
1369 let handle = if let Some(def_index) = instance.module.local_global_index(index) {
1370 instance.globals[def_index]
1371 } else {
1372 let import = instance.imported_global(index);
1373 import.handle
1374 };
1375 VMExtern::Global(handle)
1376 }
1377
1378 ExportIndex::Tag(index) => {
1379 let handle = instance.tags[index];
1380 VMExtern::Tag(handle)
1381 }
1382 }
1383 }
1384
1385 pub fn exports(&self) -> indexmap::map::Iter<'_, String, ExportIndex> {
1391 self.module().exports.iter()
1392 }
1393
1394 pub fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex {
1396 self.instance().memory_index(memory)
1397 }
1398
1399 pub fn memory_grow<IntoPages>(
1404 &mut self,
1405 memory_index: LocalMemoryIndex,
1406 delta: IntoPages,
1407 ) -> Result<Pages, MemoryError>
1408 where
1409 IntoPages: Into<Pages>,
1410 {
1411 self.instance_mut().memory_grow(memory_index, delta)
1412 }
1413
1414 pub fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex {
1416 self.instance().table_index(table)
1417 }
1418
1419 pub fn table_grow(
1424 &mut self,
1425 table_index: LocalTableIndex,
1426 delta: u32,
1427 init_value: TableElement,
1428 ) -> Option<u32> {
1429 self.instance_mut()
1430 .table_grow(table_index, delta, init_value)
1431 }
1432
1433 pub fn table_get(&self, table_index: LocalTableIndex, index: u32) -> Option<TableElement> {
1437 self.instance().table_get(table_index, index)
1438 }
1439
1440 pub fn table_set(
1444 &mut self,
1445 table_index: LocalTableIndex,
1446 index: u32,
1447 val: TableElement,
1448 ) -> Result<(), Trap> {
1449 self.instance_mut().table_set(table_index, index, val)
1450 }
1451
1452 pub fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
1454 self.instance_mut().get_local_table(index)
1455 }
1456}
1457
1458#[allow(clippy::mut_from_ref)]
1459#[allow(dead_code)]
1460unsafe fn get_memory_slice<'instance>(
1462 init: &DataInitializer<'_>,
1463 instance: &'instance Instance,
1464) -> &'instance mut [u8] {
1465 unsafe {
1466 let memory = if let Some(local_memory_index) = instance
1467 .module
1468 .local_memory_index(init.location.memory_index)
1469 {
1470 instance.memory(local_memory_index)
1471 } else {
1472 let import = instance.imported_memory(init.location.memory_index);
1473 *import.definition.as_ref()
1474 };
1475 slice::from_raw_parts_mut(memory.base, memory.current_length)
1476 }
1477}
1478
1479fn get_global(index: GlobalIndex, instance: &Instance) -> RawValue {
1480 unsafe {
1481 if let Some(local_global_index) = instance.module.local_global_index(index) {
1482 instance.global(local_global_index).val
1483 } else {
1484 instance.imported_global(index).definition.as_ref().val
1485 }
1486 }
1487}
1488
1489enum EvaluatedInitExpr {
1490 I32(i32),
1491 I64(i64),
1492}
1493
1494fn eval_init_expr(expr: &InitExpr, instance: &Instance) -> EvaluatedInitExpr {
1495 if expr
1496 .ops()
1497 .first()
1498 .expect("missing expression")
1499 .is_32bit_expression()
1500 {
1501 let mut stack = Vec::with_capacity(expr.ops().len());
1502 for op in expr.ops() {
1503 match *op {
1504 InitExprOp::I32Const(value) => stack.push(value),
1505 InitExprOp::GlobalGetI32(global) => {
1506 stack.push(unsafe { get_global(global, instance).i32 })
1507 }
1508 InitExprOp::I32Add => {
1509 let rhs = stack.pop().expect("invalid init expr stack for i32.add");
1510 let lhs = stack.pop().expect("invalid init expr stack for i32.add");
1511 stack.push(lhs.wrapping_add(rhs));
1512 }
1513 InitExprOp::I32Sub => {
1514 let rhs = stack.pop().expect("invalid init expr stack for i32.sub");
1515 let lhs = stack.pop().expect("invalid init expr stack for i32.sub");
1516 stack.push(lhs.wrapping_sub(rhs));
1517 }
1518 InitExprOp::I32Mul => {
1519 let rhs = stack.pop().expect("invalid init expr stack for i32.mul");
1520 let lhs = stack.pop().expect("invalid init expr stack for i32.mul");
1521 stack.push(lhs.wrapping_mul(rhs));
1522 }
1523 _ => {
1524 panic!("unexpected init expr statement: {op:?}");
1525 }
1526 }
1527 }
1528 EvaluatedInitExpr::I32(
1529 stack
1530 .into_iter()
1531 .exactly_one()
1532 .expect("invalid init expr stack shape"),
1533 )
1534 } else {
1535 let mut stack = Vec::with_capacity(expr.ops().len());
1536 for op in expr.ops() {
1537 match *op {
1538 InitExprOp::I64Const(value) => stack.push(value),
1539 InitExprOp::GlobalGetI64(global) => {
1540 stack.push(unsafe { get_global(global, instance).i64 })
1541 }
1542 InitExprOp::I64Add => {
1543 let rhs = stack.pop().expect("invalid init expr stack for i64.add");
1544 let lhs = stack.pop().expect("invalid init expr stack for i64.add");
1545 stack.push(lhs.wrapping_add(rhs));
1546 }
1547 InitExprOp::I64Sub => {
1548 let rhs = stack.pop().expect("invalid init expr stack for i64.sub");
1549 let lhs = stack.pop().expect("invalid init expr stack for i64.sub");
1550 stack.push(lhs.wrapping_sub(rhs));
1551 }
1552 InitExprOp::I64Mul => {
1553 let rhs = stack.pop().expect("invalid init expr stack for i64.mul");
1554 let lhs = stack.pop().expect("invalid init expr stack for i64.mul");
1555 stack.push(lhs.wrapping_mul(rhs));
1556 }
1557 _ => {
1558 panic!("unexpected init expr statement: {op:?}");
1559 }
1560 }
1561 }
1562 EvaluatedInitExpr::I64(
1563 stack
1564 .into_iter()
1565 .exactly_one()
1566 .expect("invalid init expr stack shape"),
1567 )
1568 }
1569}
1570
1571fn initialize_tables(instance: &mut Instance) -> Result<(), Trap> {
1573 let module = Arc::clone(&instance.module);
1574 for init in &module.table_initializers {
1575 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.offset_expr, instance) else {
1576 panic!("unexpected expression type, expected i32");
1577 };
1578 if start < 0 {
1579 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1580 }
1581 let start = start as usize;
1582 let table = instance.get_table_handle(init.table_index);
1583 let table = unsafe { table.get_mut(&mut *instance.context) };
1584
1585 if start
1586 .checked_add(init.elements.len())
1587 .is_none_or(|end| end > table.size() as usize)
1588 {
1589 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1590 }
1591
1592 if let wasmer_types::Type::FuncRef = table.ty().ty {
1593 for (i, func_idx) in init.elements.iter().enumerate() {
1594 let anyfunc = instance.func_ref(*func_idx);
1595 table
1596 .set_with_construction(
1597 u32::try_from(start + i).unwrap(),
1598 TableElement::FuncRef(anyfunc),
1599 true,
1600 )
1601 .unwrap();
1602 }
1603 } else {
1604 for i in 0..init.elements.len() {
1605 table
1606 .set_with_construction(
1607 u32::try_from(start + i).unwrap(),
1608 TableElement::ExternRef(None),
1609 true,
1610 )
1611 .unwrap();
1612 }
1613 }
1614
1615 instance.sync_fixed_funcref_table_by_index(init.table_index);
1616 }
1617
1618 Ok(())
1619}
1620
1621fn initialize_passive_elements(instance: &Instance) {
1625 let mut passive_elements = instance.passive_elements.borrow_mut();
1626 debug_assert!(
1627 passive_elements.is_empty(),
1628 "should only be called once, at initialization time"
1629 );
1630
1631 passive_elements.extend(instance.module.passive_elements.iter().filter_map(
1632 |(&idx, segments)| -> Option<(ElemIndex, Box<[Option<VMFuncRef>]>)> {
1633 if segments.is_empty() {
1634 None
1635 } else {
1636 Some((
1637 idx,
1638 segments
1639 .iter()
1640 .map(|s| instance.func_ref(*s))
1641 .collect::<Box<[Option<VMFuncRef>]>>(),
1642 ))
1643 }
1644 },
1645 ));
1646}
1647
1648fn initialize_memories(
1650 instance: &mut Instance,
1651 data_initializers: &[DataInitializer<'_>],
1652) -> Result<(), Trap> {
1653 for init in data_initializers {
1654 let memory = instance.get_vmmemory(init.location.memory_index);
1655
1656 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.location.offset_expr, instance)
1657 else {
1658 panic!("unexpected expression type, expected i32");
1659 };
1660 if start < 0 {
1661 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1662 }
1663 let start = start as usize;
1664 unsafe {
1665 let current_length = memory.vmmemory().as_ref().current_length;
1666 if start
1667 .checked_add(init.data.len())
1668 .is_none_or(|end| end > current_length)
1669 {
1670 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1671 }
1672 memory.initialize_with_data(start, init.data)?;
1673 }
1674 }
1675
1676 Ok(())
1677}
1678
1679fn initialize_globals(instance: &Instance) {
1680 let module = Arc::clone(&instance.module);
1681 for (index, initializer) in module.global_initializers.iter() {
1682 unsafe {
1683 let to = instance.global_ptr(index).as_ptr();
1684 match initializer {
1685 GlobalInit::I32Const(x) => (*to).val.i32 = *x,
1686 GlobalInit::I64Const(x) => (*to).val.i64 = *x,
1687 GlobalInit::F32Const(x) => (*to).val.f32 = *x,
1688 GlobalInit::F64Const(x) => (*to).val.f64 = *x,
1689 GlobalInit::V128Const(x) => (*to).val.bytes = *x.bytes(),
1690 GlobalInit::GetGlobal(x) => {
1691 let from: VMGlobalDefinition =
1692 if let Some(def_x) = module.local_global_index(*x) {
1693 instance.global(def_x)
1694 } else {
1695 instance.imported_global(*x).definition.as_ref().clone()
1696 };
1697 *to = from;
1698 }
1699 GlobalInit::RefNullConst => (*to).val.funcref = 0,
1700 GlobalInit::RefFunc(func_idx) => {
1701 let funcref = instance.func_ref(*func_idx).unwrap();
1702 (*to).val = funcref.into_raw();
1703 }
1704 GlobalInit::Expr(expr) => match eval_init_expr(expr, instance) {
1705 EvaluatedInitExpr::I32(value) => (*to).val.i32 = value,
1706 EvaluatedInitExpr::I64(value) => (*to).val.i64 = value,
1707 },
1708 }
1709 }
1710 }
1711}
1712
1713fn anyfunc_from_funcref(funcref: Option<VMFuncRef>) -> VMCallerCheckedAnyfunc {
1714 match funcref {
1715 Some(funcref) => unsafe { *funcref.0.as_ptr() },
1716 None => VMCallerCheckedAnyfunc::null(),
1717 }
1718}
1719
1720fn build_funcrefs(
1723 module_info: &ModuleInfo,
1724 ctx: &StoreObjects,
1725 imports: &Imports,
1726 finished_functions: &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1727 vmshared_signatures: &BoxedSlice<SignatureIndex, VMSignatureHash>,
1728 function_call_trampolines: &BoxedSlice<SignatureIndex, VMTrampoline>,
1729 vmctx_ptr: *mut VMContext,
1730) -> (
1731 BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
1732 BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
1733) {
1734 let mut func_refs =
1735 PrimaryMap::with_capacity(module_info.functions.len() - module_info.num_imported_functions);
1736 let mut imported_func_refs = PrimaryMap::with_capacity(module_info.num_imported_functions);
1737
1738 for import in imports.functions.values() {
1740 imported_func_refs.push(import.handle.get(ctx).anyfunc.as_ptr());
1741 }
1742
1743 for (local_index, func_ptr) in finished_functions.iter() {
1745 let index = module_info.func_index(local_index);
1746 let sig_index = module_info.functions[index];
1747 let type_signature_hash = vmshared_signatures[sig_index];
1748 let call_trampoline = function_call_trampolines[sig_index];
1749 let anyfunc = VMCallerCheckedAnyfunc {
1750 func_ptr: func_ptr.0,
1751 type_signature_hash,
1752 vmctx: VMFunctionContext { vmctx: vmctx_ptr },
1753 call_trampoline,
1754 };
1755 func_refs.push(anyfunc);
1756 }
1757 (
1758 func_refs.into_boxed_slice(),
1759 imported_func_refs.into_boxed_slice(),
1760 )
1761}