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_check_notify, memory32_atomic_check32,
21 memory32_atomic_check64,
22};
23use crate::{FunctionBodyPtr, MaybeInstanceOwned, TrapHandlerFn, VMTag, wasmer_call_trampoline};
24use crate::{VMConfig, VMFuncRef, VMFunction, VMGlobal, VMMemory, VMTable};
25use crate::{export::VMExtern, threadconditions::ExpectedValue};
26pub use allocator::InstanceAllocator;
27use core::mem::offset_of;
28use itertools::Itertools;
29use more_asserts::assert_lt;
30use std::alloc::Layout;
31use std::cell::RefCell;
32use std::collections::HashMap;
33use std::convert::TryFrom;
34use std::fmt;
35use std::mem;
36use std::ptr::{self, NonNull};
37use std::slice;
38use std::sync::Arc;
39use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap, packed_option::ReservedValue};
40use wasmer_types::{
41 DataIndex, DataInitializer, ElemIndex, ExportIndex, FunctionIndex, GlobalIndex, GlobalInit,
42 InitExpr, InitExprOp, LocalFunctionIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex,
43 MemoryError, MemoryIndex, ModuleInfo, Pages, RawValue, SignatureIndex, TableIndex, TagIndex,
44 VMOffsets,
45};
46
47#[repr(C)]
54#[allow(clippy::type_complexity)]
55pub(crate) struct Instance {
56 module: Arc<ModuleInfo>,
58
59 context: *mut StoreObjects,
61
62 offsets: VMOffsets,
64
65 memories: BoxedSlice<LocalMemoryIndex, InternalStoreHandle<VMMemory>>,
67
68 tables: BoxedSlice<LocalTableIndex, InternalStoreHandle<VMTable>>,
70
71 globals: BoxedSlice<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>,
73
74 tags: BoxedSlice<TagIndex, InternalStoreHandle<VMTag>>,
76
77 functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
79
80 function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
82
83 passive_elements: RefCell<HashMap<ElemIndex, Box<[Option<VMFuncRef>]>>>,
86
87 passive_data: RefCell<HashMap<DataIndex, Option<Arc<[u8]>>>>,
96
97 funcrefs: BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
100
101 imported_funcrefs: BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
104
105 vmctx: VMContext,
110}
111
112impl fmt::Debug for Instance {
113 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114 formatter.debug_struct("Instance").finish()
115 }
116}
117
118#[allow(clippy::cast_ptr_alignment)]
119impl Instance {
120 unsafe fn vmctx_plus_offset<T>(&self, offset: u32) -> *mut T {
123 unsafe {
124 (self.vmctx_ptr() as *mut u8)
125 .add(usize::try_from(offset).unwrap())
126 .cast()
127 }
128 }
129
130 fn module(&self) -> &Arc<ModuleInfo> {
131 &self.module
132 }
133
134 pub(crate) fn module_ref(&self) -> &ModuleInfo {
135 &self.module
136 }
137
138 pub(crate) fn context(&self) -> &StoreObjects {
139 unsafe { &*self.context }
140 }
141
142 pub(crate) fn context_mut(&mut self) -> &mut StoreObjects {
143 unsafe { &mut *self.context }
144 }
145
146 fn offsets(&self) -> &VMOffsets {
148 &self.offsets
149 }
150
151 fn imported_function(&self, index: FunctionIndex) -> &VMFunctionImport {
153 let index = usize::try_from(index.as_u32()).unwrap();
154 unsafe { &*self.imported_functions_ptr().add(index) }
155 }
156
157 fn imported_functions_ptr(&self) -> *mut VMFunctionImport {
159 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_functions_begin()) }
160 }
161
162 fn imported_table(&self, index: TableIndex) -> &VMTableImport {
164 let index = usize::try_from(index.as_u32()).unwrap();
165 unsafe { &*self.imported_tables_ptr().add(index) }
166 }
167
168 fn imported_tables_ptr(&self) -> *mut VMTableImport {
170 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_tables_begin()) }
171 }
172
173 fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
175 let index = usize::try_from(index.as_u32()).unwrap();
176 unsafe { &*self.imported_memories_ptr().add(index) }
177 }
178
179 fn imported_memories_ptr(&self) -> *mut VMMemoryImport {
181 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_memories_begin()) }
182 }
183
184 fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
186 let index = usize::try_from(index.as_u32()).unwrap();
187 unsafe { &*self.imported_globals_ptr().add(index) }
188 }
189
190 fn imported_globals_ptr(&self) -> *mut VMGlobalImport {
192 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_globals_begin()) }
193 }
194
195 #[cfg_attr(target_os = "windows", allow(dead_code))]
197 pub(crate) fn shared_tag_ptr(&self, index: TagIndex) -> &VMSharedTagIndex {
198 let index = usize::try_from(index.as_u32()).unwrap();
199 unsafe { &*self.shared_tags_ptr().add(index) }
200 }
201
202 pub(crate) fn shared_tags_ptr(&self) -> *mut VMSharedTagIndex {
204 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tag_ids_begin()) }
205 }
206
207 #[allow(dead_code)]
209 fn table(&self, index: LocalTableIndex) -> VMTableDefinition {
210 unsafe { *self.table_ptr(index).as_ref() }
211 }
212
213 #[allow(dead_code)]
214 fn set_table(&self, index: LocalTableIndex, table: &VMTableDefinition) {
216 unsafe {
217 *self.table_ptr(index).as_ptr() = *table;
218 }
219 }
220
221 fn table_ptr(&self, index: LocalTableIndex) -> NonNull<VMTableDefinition> {
223 let index = usize::try_from(index.as_u32()).unwrap();
224 NonNull::new(unsafe { self.tables_ptr().add(index) }).unwrap()
225 }
226
227 fn tables_ptr(&self) -> *mut VMTableDefinition {
229 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tables_begin()) }
230 }
231
232 fn fixed_funcref_table_ptr(
233 &self,
234 index: LocalTableIndex,
235 ) -> Option<NonNull<VMCallerCheckedAnyfunc>> {
236 let offset = self.offsets.vmctx_fixed_funcref_table_anyfuncs(index)?;
237 Some(NonNull::new(unsafe { self.vmctx_plus_offset(offset) }).unwrap())
238 }
239
240 fn sync_fixed_funcref_table_element(
241 &self,
242 table_index: LocalTableIndex,
243 index: u32,
244 funcref: Option<VMFuncRef>,
245 ) {
246 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
247 return;
248 };
249 unsafe {
250 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
251 }
252 }
253
254 fn sync_fixed_funcref_table(&self, table_index: LocalTableIndex) {
255 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
256 return;
257 };
258 let table = self.tables[table_index].get(self.context());
259 for index in 0..table.size() {
260 let TableElement::FuncRef(funcref) = table.get(index).unwrap() else {
261 unreachable!("fixed funcref tables cannot contain externrefs");
262 };
263 unsafe {
264 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
265 }
266 }
267 }
268
269 fn sync_fixed_funcref_table_by_index(&self, table_index: TableIndex) {
270 if let Some(local_table_index) = self.module.local_table_index(table_index) {
271 self.sync_fixed_funcref_table(local_table_index);
272 }
273 }
274
275 fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition {
277 if let Some(local_index) = self.module.local_memory_index(index) {
278 self.memory(local_index)
279 } else {
280 let import = self.imported_memory(index);
281 unsafe { *import.definition.as_ref() }
282 }
283 }
284
285 fn memory(&self, index: LocalMemoryIndex) -> VMMemoryDefinition {
287 unsafe { *self.memory_ptr(index).as_ref() }
288 }
289
290 #[allow(dead_code)]
291 fn set_memory(&self, index: LocalMemoryIndex, mem: &VMMemoryDefinition) {
293 unsafe {
294 *self.memory_ptr(index).as_ptr() = *mem;
295 }
296 }
297
298 fn memory_ptr(&self, index: LocalMemoryIndex) -> NonNull<VMMemoryDefinition> {
300 let index = usize::try_from(index.as_u32()).unwrap();
301 NonNull::new(unsafe { self.memories_ptr().add(index) }).unwrap()
302 }
303
304 fn memories_ptr(&self) -> *mut VMMemoryDefinition {
306 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_memories_begin()) }
307 }
308
309 fn get_vmmemory(&self, index: MemoryIndex) -> &VMMemory {
311 if let Some(local_index) = self.module.local_memory_index(index) {
312 unsafe {
313 self.memories
314 .get(local_index)
315 .unwrap()
316 .get(self.context.as_ref().unwrap())
317 }
318 } else {
319 let import = self.imported_memory(index);
320 unsafe { import.handle.get(self.context.as_ref().unwrap()) }
321 }
322 }
323
324 fn get_vmmemory_mut(&mut self, index: MemoryIndex) -> &mut VMMemory {
326 if let Some(local_index) = self.module.local_memory_index(index) {
327 unsafe {
328 self.memories
329 .get_mut(local_index)
330 .unwrap()
331 .get_mut(self.context.as_mut().unwrap())
332 }
333 } else {
334 let import = self.imported_memory(index);
335 unsafe { import.handle.get_mut(self.context.as_mut().unwrap()) }
336 }
337 }
338
339 fn get_local_vmmemory_mut(&mut self, local_index: LocalMemoryIndex) -> &mut VMMemory {
341 unsafe {
342 self.memories
343 .get_mut(local_index)
344 .unwrap()
345 .get_mut(self.context.as_mut().unwrap())
346 }
347 }
348
349 fn global(&self, index: LocalGlobalIndex) -> VMGlobalDefinition {
351 unsafe { self.global_ptr(index).as_ref().clone() }
352 }
353
354 #[allow(dead_code)]
356 fn set_global(&self, index: LocalGlobalIndex, global: &VMGlobalDefinition) {
357 unsafe {
358 *self.global_ptr(index).as_ptr() = global.clone();
359 }
360 }
361
362 fn global_ptr(&self, index: LocalGlobalIndex) -> NonNull<VMGlobalDefinition> {
364 let index = usize::try_from(index.as_u32()).unwrap();
365 NonNull::new(unsafe { self.globals_ptr().add(index) }).unwrap()
366 }
367
368 fn globals_ptr(&self) -> *mut VMGlobalDefinition {
370 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_globals_begin()) }
371 }
372
373 fn builtin_functions_ptr(&self) -> *mut VMBuiltinFunctionsArray {
375 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_builtin_functions_begin()) }
376 }
377
378 fn vmctx(&self) -> &VMContext {
380 &self.vmctx
381 }
382
383 fn vmctx_ptr(&self) -> *mut VMContext {
385 self.vmctx() as *const VMContext as *mut VMContext
386 }
387
388 fn invoke_start_function(
390 &self,
391 config: &VMConfig,
392 trap_handler: Option<*const TrapHandlerFn<'static>>,
393 ) -> Result<(), Trap> {
394 let start_index = match self.module.start_function {
395 Some(idx) => idx,
396 None => return Ok(()),
397 };
398
399 let (callee_address, callee_vmctx) = match self.module.local_func_index(start_index) {
400 Some(local_index) => {
401 let body = self
402 .functions
403 .get(local_index)
404 .expect("function index is out of bounds")
405 .0;
406 (
407 body as *const _,
408 VMFunctionContext {
409 vmctx: self.vmctx_ptr(),
410 },
411 )
412 }
413 None => {
414 assert_lt!(start_index.index(), self.module.num_imported_functions);
415 let import = self.imported_function(start_index);
416 (import.body, import.environment)
417 }
418 };
419
420 let sig = self.module.functions[start_index];
421 let trampoline = self.function_call_trampolines[sig];
422 let mut values_vec = vec![];
423
424 unsafe {
425 wasmer_call_trampoline(
429 trap_handler,
430 config,
431 callee_vmctx,
432 trampoline,
433 callee_address,
434 values_vec.as_mut_ptr(),
435 )
436 }
437 }
438
439 #[inline]
441 pub(crate) fn vmctx_offset() -> isize {
442 offset_of!(Self, vmctx) as isize
443 }
444
445 pub(crate) fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex {
447 let begin: *const VMTableDefinition = self.tables_ptr() as *const _;
448 let end: *const VMTableDefinition = table;
449 let index = LocalTableIndex::new(
451 (end as usize - begin as usize) / mem::size_of::<VMTableDefinition>(),
452 );
453 assert_lt!(index.index(), self.tables.len());
454 index
455 }
456
457 pub(crate) fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex {
459 let begin: *const VMMemoryDefinition = self.memories_ptr() as *const _;
460 let end: *const VMMemoryDefinition = memory;
461 let index = LocalMemoryIndex::new(
463 (end as usize - begin as usize) / mem::size_of::<VMMemoryDefinition>(),
464 );
465 assert_lt!(index.index(), self.memories.len());
466 index
467 }
468
469 pub(crate) fn memory_grow<IntoPages>(
474 &mut self,
475 memory_index: LocalMemoryIndex,
476 delta: IntoPages,
477 ) -> Result<Pages, MemoryError>
478 where
479 IntoPages: Into<Pages>,
480 {
481 let mem = *self
482 .memories
483 .get(memory_index)
484 .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
485 mem.get_mut(self.context_mut()).grow(delta.into())
486 }
487
488 pub(crate) unsafe fn imported_memory_grow<IntoPages>(
497 &mut self,
498 memory_index: MemoryIndex,
499 delta: IntoPages,
500 ) -> Result<Pages, MemoryError>
501 where
502 IntoPages: Into<Pages>,
503 {
504 let import = self.imported_memory(memory_index);
505 let mem = import.handle;
506 mem.get_mut(self.context_mut()).grow(delta.into())
507 }
508
509 pub(crate) fn memory_size(&self, memory_index: LocalMemoryIndex) -> Pages {
511 let mem = *self
512 .memories
513 .get(memory_index)
514 .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
515 mem.get(self.context()).size()
516 }
517
518 pub(crate) unsafe fn imported_memory_size(&self, memory_index: MemoryIndex) -> Pages {
524 let import = self.imported_memory(memory_index);
525 let mem = import.handle;
526 mem.get(self.context()).size()
527 }
528
529 pub(crate) fn table_size(&self, table_index: LocalTableIndex) -> u32 {
531 let table = self
532 .tables
533 .get(table_index)
534 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
535 table.get(self.context()).size()
536 }
537
538 pub(crate) unsafe fn imported_table_size(&self, table_index: TableIndex) -> u32 {
543 let import = self.imported_table(table_index);
544 let table = import.handle;
545 table.get(self.context()).size()
546 }
547
548 pub(crate) fn table_grow(
553 &mut self,
554 table_index: LocalTableIndex,
555 delta: u32,
556 init_value: TableElement,
557 ) -> Option<u32> {
558 let table = *self
559 .tables
560 .get(table_index)
561 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
562 table.get_mut(self.context_mut()).grow(delta, init_value)
563 }
564
565 pub(crate) unsafe fn imported_table_grow(
570 &mut self,
571 table_index: TableIndex,
572 delta: u32,
573 init_value: TableElement,
574 ) -> Option<u32> {
575 let import = self.imported_table(table_index);
576 let table = import.handle;
577 table.get_mut(self.context_mut()).grow(delta, init_value)
578 }
579
580 pub(crate) fn table_get(
582 &self,
583 table_index: LocalTableIndex,
584 index: u32,
585 ) -> Option<TableElement> {
586 let table = self
587 .tables
588 .get(table_index)
589 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
590 table.get(self.context()).get(index)
591 }
592
593 pub(crate) unsafe fn imported_table_get(
598 &self,
599 table_index: TableIndex,
600 index: u32,
601 ) -> Option<TableElement> {
602 let import = self.imported_table(table_index);
603 let table = import.handle;
604 table.get(self.context()).get(index)
605 }
606
607 pub(crate) fn table_set(
609 &mut self,
610 table_index: LocalTableIndex,
611 index: u32,
612 val: TableElement,
613 ) -> Result<(), Trap> {
614 let table = *self
615 .tables
616 .get(table_index)
617 .unwrap_or_else(|| panic!("no table for index {}", table_index.index()));
618 let funcref = match &val {
619 TableElement::FuncRef(funcref) => Some(*funcref),
620 TableElement::ExternRef(_) => None,
621 };
622 table.get_mut(self.context_mut()).set(index, val)?;
623 if let Some(funcref) = funcref {
624 self.sync_fixed_funcref_table_element(table_index, index, funcref);
625 }
626 Ok(())
627 }
628
629 pub(crate) unsafe fn imported_table_set(
634 &mut self,
635 table_index: TableIndex,
636 index: u32,
637 val: TableElement,
638 ) -> Result<(), Trap> {
639 let import = self.imported_table(table_index);
640 let table = import.handle;
641 table.get_mut(self.context_mut()).set(index, val)
642 }
643
644 pub(crate) fn func_ref(&self, function_index: FunctionIndex) -> Option<VMFuncRef> {
646 if function_index == FunctionIndex::reserved_value() {
647 None
648 } else if let Some(local_function_index) = self.module.local_func_index(function_index) {
649 Some(VMFuncRef(NonNull::from(
650 &self.funcrefs[local_function_index],
651 )))
652 } else {
653 Some(VMFuncRef(self.imported_funcrefs[function_index]))
654 }
655 }
656
657 pub(crate) fn table_init(
665 &mut self,
666 table_index: TableIndex,
667 elem_index: ElemIndex,
668 dst: u32,
669 src: u32,
670 len: u32,
671 ) -> Result<(), Trap> {
672 let table = self.get_table_handle(table_index);
675 let table = unsafe { table.get_mut(&mut *self.context) };
676 let passive_elements = self.passive_elements.borrow();
677 let elem = passive_elements
678 .get(&elem_index)
679 .map_or::<&[Option<VMFuncRef>], _>(&[], |e| &**e);
680
681 if src.checked_add(len).is_none_or(|n| n as usize > elem.len())
682 || dst.checked_add(len).is_none_or(|m| m > table.size())
683 {
684 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
685 }
686
687 for (dst, src) in (dst..dst + len).zip(src..src + len) {
688 table
689 .set(dst, TableElement::FuncRef(elem[src as usize]))
690 .expect("should never panic because we already did the bounds check above");
691 }
692
693 self.sync_fixed_funcref_table_by_index(table_index);
694
695 Ok(())
696 }
697
698 pub(crate) fn table_fill(
704 &mut self,
705 table_index: TableIndex,
706 start_index: u32,
707 item: TableElement,
708 len: u32,
709 ) -> Result<(), Trap> {
710 let table = self.get_table(table_index);
713 let table_size = table.size() as usize;
714
715 if start_index
716 .checked_add(len)
717 .is_none_or(|n| n as usize > table_size)
718 {
719 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
720 }
721
722 for i in start_index..(start_index + len) {
723 table
724 .set(i, item.clone())
725 .expect("should never panic because we already did the bounds check above");
726 }
727
728 self.sync_fixed_funcref_table_by_index(table_index);
729
730 Ok(())
731 }
732
733 pub(crate) fn table_copy(
735 &mut self,
736 dst_table_index: TableIndex,
737 src_table_index: TableIndex,
738 dst: u32,
739 src: u32,
740 len: u32,
741 ) -> Result<(), Trap> {
742 let result = if dst_table_index == src_table_index {
743 let table = self.get_table(dst_table_index);
744 table.copy_within(dst, src, len)
745 } else {
746 let dst_table = self.get_table_handle(dst_table_index);
747 let src_table = self.get_table_handle(src_table_index);
748 if dst_table == src_table {
749 unsafe {
750 dst_table
751 .get_mut(&mut *self.context)
752 .copy_within(dst, src, len)
753 }
754 } else {
755 unsafe {
756 dst_table.get_mut(&mut *self.context).copy(
757 src_table.get(&*self.context),
758 dst,
759 src,
760 len,
761 )
762 }
763 }
764 };
765 result?;
766 self.sync_fixed_funcref_table_by_index(dst_table_index);
767
768 Ok(())
769 }
770
771 pub(crate) fn elem_drop(&self, elem_index: ElemIndex) {
773 let mut passive_elements = self.passive_elements.borrow_mut();
776 passive_elements.remove(&elem_index);
777 }
780
781 pub(crate) fn memory_copy(
788 &self,
789 dst_memory_index: MemoryIndex,
790 src_memory_index: MemoryIndex,
791 dst: u32,
792 src: u32,
793 len: u32,
794 ) -> Result<(), Trap> {
795 let dst_memory = self.get_memory(dst_memory_index);
796 let src_memory = self.get_memory(src_memory_index);
797 unsafe { memory_copy(&dst_memory, &src_memory, dst, src, len) }
799 }
800
801 pub(crate) fn local_memory_fill(
807 &self,
808 memory_index: LocalMemoryIndex,
809 dst: u32,
810 val: u32,
811 len: u32,
812 ) -> Result<(), Trap> {
813 let memory = self.memory(memory_index);
814 unsafe { memory_fill(&memory, dst, val, len) }
816 }
817
818 pub(crate) fn imported_memory_fill(
824 &self,
825 memory_index: MemoryIndex,
826 dst: u32,
827 val: u32,
828 len: u32,
829 ) -> Result<(), Trap> {
830 let import = self.imported_memory(memory_index);
831 let memory = unsafe { import.definition.as_ref() };
832 unsafe { memory_fill(memory, dst, val, len) }
834 }
835
836 pub(crate) fn memory_init(
844 &self,
845 memory_index: MemoryIndex,
846 data_index: DataIndex,
847 dst: u32,
848 src: u32,
849 len: u32,
850 ) -> Result<(), Trap> {
851 let memory = self.get_vmmemory(memory_index);
854 let passive_data = self.passive_data.borrow();
855 let data = passive_data
859 .get(&data_index)
860 .and_then(|d| d.as_deref())
861 .unwrap_or(&[]);
862
863 let current_length = unsafe { memory.vmmemory().as_ref().current_length };
864 if src.checked_add(len).is_none_or(|n| n as usize > data.len())
865 || dst
866 .checked_add(len)
867 .is_none_or(|m| usize::try_from(m).unwrap() > current_length)
868 {
869 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
870 }
871 let src_slice = &data[src as usize..(src + len) as usize];
872 unsafe { memory.initialize_with_data(dst as usize, src_slice) }
873 }
874
875 pub(crate) fn data_drop(&self, data_index: DataIndex) {
877 let mut passive_data = self.passive_data.borrow_mut();
878 if let Some(slot) = passive_data.get_mut(&data_index) {
881 *slot = None;
882 }
883 }
884
885 pub(crate) fn get_table(&mut self, table_index: TableIndex) -> &mut VMTable {
888 if let Some(local_table_index) = self.module.local_table_index(table_index) {
889 self.get_local_table(local_table_index)
890 } else {
891 self.get_foreign_table(table_index)
892 }
893 }
894
895 pub(crate) fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
897 let table = self.tables[index];
898 table.get_mut(self.context_mut())
899 }
900
901 pub(crate) fn get_foreign_table(&mut self, index: TableIndex) -> &mut VMTable {
903 let import = self.imported_table(index);
904 let table = import.handle;
905 table.get_mut(self.context_mut())
906 }
907
908 pub(crate) fn get_table_handle(
911 &mut self,
912 table_index: TableIndex,
913 ) -> InternalStoreHandle<VMTable> {
914 if let Some(local_table_index) = self.module.local_table_index(table_index) {
915 self.tables[local_table_index]
916 } else {
917 self.imported_table(table_index).handle
918 }
919 }
920
921 unsafe fn memory_wait(
924 memory: &mut VMMemory,
925 dst: u32,
926 expected: ExpectedValue,
927 timeout: i64,
928 ) -> Result<u32, Trap> {
929 let timeout = if timeout < 0 {
930 None
931 } else {
932 Some(std::time::Duration::from_nanos(timeout as u64))
933 };
934 match unsafe { memory.do_wait(dst, expected, timeout) } {
935 Ok(count) => Ok(count),
936 Err(_err) => Err(Trap::lib(TrapCode::HostInterrupt)),
937 }
938 }
939
940 pub(crate) fn local_memory_wait32(
942 &mut self,
943 memory_index: LocalMemoryIndex,
944 dst: u32,
945 val: u32,
946 timeout: i64,
947 ) -> Result<u32, Trap> {
948 let memory = self.memory(memory_index);
949 let ret = unsafe { memory32_atomic_check32(&memory, dst, val) };
955
956 if let Ok(mut ret) = ret {
957 if ret == 0 {
958 let memory = self.get_local_vmmemory_mut(memory_index);
959 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
961 }
962 Ok(ret)
963 } else {
964 ret
965 }
966 }
967
968 pub(crate) fn imported_memory_wait32(
970 &mut self,
971 memory_index: MemoryIndex,
972 dst: u32,
973 val: u32,
974 timeout: i64,
975 ) -> Result<u32, Trap> {
976 let import = self.imported_memory(memory_index);
977 let memory = unsafe { import.definition.as_ref() };
978 let ret = unsafe { memory32_atomic_check32(memory, dst, val) };
984
985 if let Ok(mut ret) = ret {
986 if ret == 0 {
987 let memory = self.get_vmmemory_mut(memory_index);
988 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
990 }
991 Ok(ret)
992 } else {
993 ret
994 }
995 }
996
997 pub(crate) fn local_memory_wait64(
999 &mut self,
1000 memory_index: LocalMemoryIndex,
1001 dst: u32,
1002 val: u64,
1003 timeout: i64,
1004 ) -> Result<u32, Trap> {
1005 let memory = self.memory(memory_index);
1006 let ret = unsafe { memory32_atomic_check64(&memory, dst, val) };
1012
1013 if let Ok(mut ret) = ret {
1014 if ret == 0 {
1015 let memory = self.get_local_vmmemory_mut(memory_index);
1016 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1018 }
1019 Ok(ret)
1020 } else {
1021 ret
1022 }
1023 }
1024
1025 pub(crate) fn imported_memory_wait64(
1027 &mut self,
1028 memory_index: MemoryIndex,
1029 dst: u32,
1030 val: u64,
1031 timeout: i64,
1032 ) -> Result<u32, Trap> {
1033 let import = self.imported_memory(memory_index);
1034 let memory = unsafe { import.definition.as_ref() };
1035 let ret = unsafe { memory32_atomic_check64(memory, dst, val) };
1041
1042 if let Ok(mut ret) = ret {
1043 if ret == 0 {
1044 let memory = self.get_vmmemory_mut(memory_index);
1045 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1047 }
1048 Ok(ret)
1049 } else {
1050 ret
1051 }
1052 }
1053
1054 pub(crate) fn local_memory_notify(
1056 &mut self,
1057 memory_index: LocalMemoryIndex,
1058 dst: u32,
1059 count: u32,
1060 ) -> Result<u32, Trap> {
1061 let memory = self.memory(memory_index);
1062 memory32_atomic_check_notify(&memory, dst)?;
1063 let memory = self.get_local_vmmemory_mut(memory_index);
1064 Ok(memory.do_notify(dst, count))
1065 }
1066
1067 pub(crate) fn imported_memory_notify(
1069 &mut self,
1070 memory_index: MemoryIndex,
1071 dst: u32,
1072 count: u32,
1073 ) -> Result<u32, Trap> {
1074 let import = self.imported_memory(memory_index);
1075 let memory = unsafe { import.definition.as_ref() };
1076 memory32_atomic_check_notify(memory, dst)?;
1077 let memory = self.get_vmmemory_mut(memory_index);
1078 Ok(memory.do_notify(dst, count))
1079 }
1080}
1081
1082#[derive(Debug, Eq, PartialEq)]
1087pub struct VMInstance {
1088 instance_layout: Layout,
1090
1091 instance: NonNull<Instance>,
1101}
1102
1103impl Drop for VMInstance {
1107 fn drop(&mut self) {
1108 let instance_ptr = self.instance.as_ptr();
1109
1110 unsafe {
1111 instance_ptr.drop_in_place();
1113 std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
1115 }
1116 }
1117}
1118
1119impl VMInstance {
1120 #[allow(clippy::too_many_arguments)]
1142 pub unsafe fn new(
1143 allocator: InstanceAllocator,
1144 module: Arc<ModuleInfo>,
1145 context: &mut StoreObjects,
1146 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1147 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
1148 finished_memories: BoxedSlice<LocalMemoryIndex, InternalStoreHandle<VMMemory>>,
1149 finished_tables: BoxedSlice<LocalTableIndex, InternalStoreHandle<VMTable>>,
1150 finished_globals: BoxedSlice<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>,
1151 tags: BoxedSlice<TagIndex, InternalStoreHandle<VMTag>>,
1152 imports: Imports,
1153 vmshared_signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
1154 ) -> Result<Self, Trap> {
1155 unsafe {
1156 let vmctx_tags = tags
1157 .values()
1158 .map(|m: &InternalStoreHandle<VMTag>| VMSharedTagIndex::new(m.index() as u32))
1159 .collect::<PrimaryMap<TagIndex, VMSharedTagIndex>>()
1160 .into_boxed_slice();
1161 let passive_data = RefCell::new(
1164 module
1165 .passive_data
1166 .iter()
1167 .map(|(&idx, bytes)| (idx, Some(Arc::clone(bytes))))
1168 .collect::<HashMap<_, _>>(),
1169 );
1170
1171 let handle = {
1172 let offsets = allocator.offsets().clone();
1173 let funcrefs = PrimaryMap::new().into_boxed_slice();
1175 let imported_funcrefs = PrimaryMap::new().into_boxed_slice();
1176 let instance = Instance {
1178 module,
1179 context,
1180 offsets,
1181 memories: finished_memories,
1182 tables: finished_tables,
1183 tags,
1184 globals: finished_globals,
1185 functions: finished_functions,
1186 function_call_trampolines: finished_function_call_trampolines,
1187 passive_elements: Default::default(),
1188 passive_data,
1189 funcrefs,
1190 imported_funcrefs,
1191 vmctx: VMContext {},
1192 };
1193
1194 let mut instance_handle = allocator.into_vminstance(instance);
1195
1196 {
1198 let instance = instance_handle.instance_mut();
1199 let vmctx_ptr = instance.vmctx_ptr();
1200 (instance.funcrefs, instance.imported_funcrefs) = build_funcrefs(
1201 &instance.module,
1202 context,
1203 &imports,
1204 &instance.functions,
1205 &vmshared_signatures,
1206 &instance.function_call_trampolines,
1207 vmctx_ptr,
1208 );
1209 for local_table_index in instance.tables.keys() {
1210 instance.sync_fixed_funcref_table(local_table_index);
1211 }
1212 }
1213
1214 instance_handle
1215 };
1216 let instance = handle.instance();
1217
1218 ptr::copy(
1219 vmctx_tags.values().as_slice().as_ptr(),
1220 instance.shared_tags_ptr(),
1221 vmctx_tags.len(),
1222 );
1223 ptr::copy(
1224 imports.functions.values().as_slice().as_ptr(),
1225 instance.imported_functions_ptr(),
1226 imports.functions.len(),
1227 );
1228 ptr::copy(
1229 imports.tables.values().as_slice().as_ptr(),
1230 instance.imported_tables_ptr(),
1231 imports.tables.len(),
1232 );
1233 ptr::copy(
1234 imports.memories.values().as_slice().as_ptr(),
1235 instance.imported_memories_ptr(),
1236 imports.memories.len(),
1237 );
1238 ptr::copy(
1239 imports.globals.values().as_slice().as_ptr(),
1240 instance.imported_globals_ptr(),
1241 imports.globals.len(),
1242 );
1243 ptr::write(
1247 instance.builtin_functions_ptr(),
1248 VMBuiltinFunctionsArray::initialized(),
1249 );
1250
1251 initialize_passive_elements(instance);
1254 initialize_globals(instance);
1255
1256 Ok(handle)
1257 }
1258 }
1259
1260 pub(crate) fn instance(&self) -> &Instance {
1262 unsafe { self.instance.as_ref() }
1263 }
1264
1265 pub(crate) fn instance_mut(&mut self) -> &mut Instance {
1267 unsafe { self.instance.as_mut() }
1268 }
1269
1270 pub unsafe fn finish_instantiation(
1276 &mut self,
1277 config: &VMConfig,
1278 trap_handler: Option<*const TrapHandlerFn<'static>>,
1279 data_initializers: &[DataInitializer<'_>],
1280 ) -> Result<(), Trap> {
1281 let instance = self.instance_mut();
1282
1283 initialize_tables(instance)?;
1285 initialize_memories(instance, data_initializers)?;
1286
1287 instance.invoke_start_function(config, trap_handler)?;
1290 Ok(())
1291 }
1292
1293 pub fn vmctx(&self) -> &VMContext {
1295 self.instance().vmctx()
1296 }
1297
1298 pub fn vmctx_ptr(&self) -> *mut VMContext {
1300 self.instance().vmctx_ptr()
1301 }
1302
1303 pub fn vmoffsets(&self) -> &VMOffsets {
1307 self.instance().offsets()
1308 }
1309
1310 pub fn module(&self) -> &Arc<ModuleInfo> {
1312 self.instance().module()
1313 }
1314
1315 pub fn module_ref(&self) -> &ModuleInfo {
1317 self.instance().module_ref()
1318 }
1319
1320 pub fn lookup(&mut self, field: &str) -> Option<VMExtern> {
1322 let export = *self.module_ref().exports.get(field)?;
1323
1324 Some(self.lookup_by_declaration(export))
1325 }
1326
1327 pub fn lookup_by_declaration(&mut self, export: ExportIndex) -> VMExtern {
1329 let instance = self.instance();
1330
1331 match export {
1332 ExportIndex::Function(index) => {
1333 let sig_index = &instance.module.functions[index];
1334 let handle = if let Some(def_index) = instance.module.local_func_index(index) {
1335 let signature = instance.module.signatures[*sig_index].clone();
1338 let vm_function = VMFunction {
1339 anyfunc: MaybeInstanceOwned::Instance(NonNull::from(
1340 &instance.funcrefs[def_index],
1341 )),
1342 signature,
1343 kind: VMFunctionKind::Static,
1348 host_data: Box::new(()),
1349 };
1350 InternalStoreHandle::new(self.instance_mut().context_mut(), vm_function)
1351 } else {
1352 let import = instance.imported_function(index);
1353 import.handle
1354 };
1355
1356 VMExtern::Function(handle)
1357 }
1358 ExportIndex::Table(index) => {
1359 let handle = if let Some(def_index) = instance.module.local_table_index(index) {
1360 instance.tables[def_index]
1361 } else {
1362 let import = instance.imported_table(index);
1363 import.handle
1364 };
1365 VMExtern::Table(handle)
1366 }
1367 ExportIndex::Memory(index) => {
1368 let handle = if let Some(def_index) = instance.module.local_memory_index(index) {
1369 instance.memories[def_index]
1370 } else {
1371 let import = instance.imported_memory(index);
1372 import.handle
1373 };
1374 VMExtern::Memory(handle)
1375 }
1376 ExportIndex::Global(index) => {
1377 let handle = if let Some(def_index) = instance.module.local_global_index(index) {
1378 instance.globals[def_index]
1379 } else {
1380 let import = instance.imported_global(index);
1381 import.handle
1382 };
1383 VMExtern::Global(handle)
1384 }
1385
1386 ExportIndex::Tag(index) => {
1387 let handle = instance.tags[index];
1388 VMExtern::Tag(handle)
1389 }
1390 }
1391 }
1392
1393 pub fn exports(&self) -> indexmap::map::Iter<'_, String, ExportIndex> {
1399 self.module().exports.iter()
1400 }
1401
1402 pub fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex {
1404 self.instance().memory_index(memory)
1405 }
1406
1407 pub fn memory_grow<IntoPages>(
1412 &mut self,
1413 memory_index: LocalMemoryIndex,
1414 delta: IntoPages,
1415 ) -> Result<Pages, MemoryError>
1416 where
1417 IntoPages: Into<Pages>,
1418 {
1419 self.instance_mut().memory_grow(memory_index, delta)
1420 }
1421
1422 pub fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex {
1424 self.instance().table_index(table)
1425 }
1426
1427 pub fn table_grow(
1432 &mut self,
1433 table_index: LocalTableIndex,
1434 delta: u32,
1435 init_value: TableElement,
1436 ) -> Option<u32> {
1437 self.instance_mut()
1438 .table_grow(table_index, delta, init_value)
1439 }
1440
1441 pub fn table_get(&self, table_index: LocalTableIndex, index: u32) -> Option<TableElement> {
1445 self.instance().table_get(table_index, index)
1446 }
1447
1448 pub fn table_set(
1452 &mut self,
1453 table_index: LocalTableIndex,
1454 index: u32,
1455 val: TableElement,
1456 ) -> Result<(), Trap> {
1457 self.instance_mut().table_set(table_index, index, val)
1458 }
1459
1460 pub fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
1462 self.instance_mut().get_local_table(index)
1463 }
1464}
1465
1466#[allow(clippy::mut_from_ref)]
1467#[allow(dead_code)]
1468unsafe fn get_memory_slice<'instance>(
1470 init: &DataInitializer<'_>,
1471 instance: &'instance Instance,
1472) -> &'instance mut [u8] {
1473 unsafe {
1474 let memory = if let Some(local_memory_index) = instance
1475 .module
1476 .local_memory_index(init.location.memory_index)
1477 {
1478 instance.memory(local_memory_index)
1479 } else {
1480 let import = instance.imported_memory(init.location.memory_index);
1481 *import.definition.as_ref()
1482 };
1483 slice::from_raw_parts_mut(memory.base, memory.current_length)
1484 }
1485}
1486
1487fn get_global(index: GlobalIndex, instance: &Instance) -> RawValue {
1488 unsafe {
1489 if let Some(local_global_index) = instance.module.local_global_index(index) {
1490 instance.global(local_global_index).val
1491 } else {
1492 instance.imported_global(index).definition.as_ref().val
1493 }
1494 }
1495}
1496
1497enum EvaluatedInitExpr {
1498 I32(i32),
1499 I64(i64),
1500}
1501
1502fn eval_init_expr(expr: &InitExpr, instance: &Instance) -> EvaluatedInitExpr {
1503 if expr
1504 .ops()
1505 .first()
1506 .expect("missing expression")
1507 .is_32bit_expression()
1508 {
1509 let mut stack = Vec::with_capacity(expr.ops().len());
1510 for op in expr.ops() {
1511 match *op {
1512 InitExprOp::I32Const(value) => stack.push(value),
1513 InitExprOp::GlobalGetI32(global) => {
1514 stack.push(unsafe { get_global(global, instance).i32 })
1515 }
1516 InitExprOp::I32Add => {
1517 let rhs = stack.pop().expect("invalid init expr stack for i32.add");
1518 let lhs = stack.pop().expect("invalid init expr stack for i32.add");
1519 stack.push(lhs.wrapping_add(rhs));
1520 }
1521 InitExprOp::I32Sub => {
1522 let rhs = stack.pop().expect("invalid init expr stack for i32.sub");
1523 let lhs = stack.pop().expect("invalid init expr stack for i32.sub");
1524 stack.push(lhs.wrapping_sub(rhs));
1525 }
1526 InitExprOp::I32Mul => {
1527 let rhs = stack.pop().expect("invalid init expr stack for i32.mul");
1528 let lhs = stack.pop().expect("invalid init expr stack for i32.mul");
1529 stack.push(lhs.wrapping_mul(rhs));
1530 }
1531 _ => {
1532 panic!("unexpected init expr statement: {op:?}");
1533 }
1534 }
1535 }
1536 EvaluatedInitExpr::I32(
1537 stack
1538 .into_iter()
1539 .exactly_one()
1540 .expect("invalid init expr stack shape"),
1541 )
1542 } else {
1543 let mut stack = Vec::with_capacity(expr.ops().len());
1544 for op in expr.ops() {
1545 match *op {
1546 InitExprOp::I64Const(value) => stack.push(value),
1547 InitExprOp::GlobalGetI64(global) => {
1548 stack.push(unsafe { get_global(global, instance).i64 })
1549 }
1550 InitExprOp::I64Add => {
1551 let rhs = stack.pop().expect("invalid init expr stack for i64.add");
1552 let lhs = stack.pop().expect("invalid init expr stack for i64.add");
1553 stack.push(lhs.wrapping_add(rhs));
1554 }
1555 InitExprOp::I64Sub => {
1556 let rhs = stack.pop().expect("invalid init expr stack for i64.sub");
1557 let lhs = stack.pop().expect("invalid init expr stack for i64.sub");
1558 stack.push(lhs.wrapping_sub(rhs));
1559 }
1560 InitExprOp::I64Mul => {
1561 let rhs = stack.pop().expect("invalid init expr stack for i64.mul");
1562 let lhs = stack.pop().expect("invalid init expr stack for i64.mul");
1563 stack.push(lhs.wrapping_mul(rhs));
1564 }
1565 _ => {
1566 panic!("unexpected init expr statement: {op:?}");
1567 }
1568 }
1569 }
1570 EvaluatedInitExpr::I64(
1571 stack
1572 .into_iter()
1573 .exactly_one()
1574 .expect("invalid init expr stack shape"),
1575 )
1576 }
1577}
1578
1579fn initialize_tables(instance: &mut Instance) -> Result<(), Trap> {
1581 let module = Arc::clone(&instance.module);
1582 for init in &module.table_initializers {
1583 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.offset_expr, instance) else {
1584 panic!("unexpected expression type, expected i32");
1585 };
1586 if start < 0 {
1587 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1588 }
1589 let start = start as usize;
1590 let table = instance.get_table_handle(init.table_index);
1591 let table = unsafe { table.get_mut(&mut *instance.context) };
1592
1593 if start
1594 .checked_add(init.elements.len())
1595 .is_none_or(|end| end > table.size() as usize)
1596 {
1597 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1598 }
1599
1600 if let wasmer_types::Type::FuncRef = table.ty().ty {
1601 for (i, func_idx) in init.elements.iter().enumerate() {
1602 let anyfunc = instance.func_ref(*func_idx);
1603 table
1604 .set_with_construction(
1605 u32::try_from(start + i).unwrap(),
1606 TableElement::FuncRef(anyfunc),
1607 true,
1608 )
1609 .unwrap();
1610 }
1611 } else {
1612 for i in 0..init.elements.len() {
1613 table
1614 .set_with_construction(
1615 u32::try_from(start + i).unwrap(),
1616 TableElement::ExternRef(None),
1617 true,
1618 )
1619 .unwrap();
1620 }
1621 }
1622
1623 instance.sync_fixed_funcref_table_by_index(init.table_index);
1624 }
1625
1626 Ok(())
1627}
1628
1629fn initialize_passive_elements(instance: &Instance) {
1633 let mut passive_elements = instance.passive_elements.borrow_mut();
1634 debug_assert!(
1635 passive_elements.is_empty(),
1636 "should only be called once, at initialization time"
1637 );
1638
1639 passive_elements.extend(instance.module.passive_elements.iter().filter_map(
1640 |(&idx, segments)| -> Option<(ElemIndex, Box<[Option<VMFuncRef>]>)> {
1641 if segments.is_empty() {
1642 None
1643 } else {
1644 Some((
1645 idx,
1646 segments
1647 .iter()
1648 .map(|s| instance.func_ref(*s))
1649 .collect::<Box<[Option<VMFuncRef>]>>(),
1650 ))
1651 }
1652 },
1653 ));
1654}
1655
1656fn initialize_memories(
1658 instance: &mut Instance,
1659 data_initializers: &[DataInitializer<'_>],
1660) -> Result<(), Trap> {
1661 for init in data_initializers {
1662 let memory = instance.get_vmmemory(init.location.memory_index);
1663
1664 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.location.offset_expr, instance)
1665 else {
1666 panic!("unexpected expression type, expected i32");
1667 };
1668 if start < 0 {
1669 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1670 }
1671 let start = start as usize;
1672 unsafe {
1673 let current_length = memory.vmmemory().as_ref().current_length;
1674 if start
1675 .checked_add(init.data.len())
1676 .is_none_or(|end| end > current_length)
1677 {
1678 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1679 }
1680 memory.initialize_with_data(start, init.data)?;
1681 }
1682 }
1683
1684 Ok(())
1685}
1686
1687fn initialize_globals(instance: &Instance) {
1688 let module = Arc::clone(&instance.module);
1689 for (index, initializer) in module.global_initializers.iter() {
1690 unsafe {
1691 let to = instance.global_ptr(index).as_ptr();
1692 match initializer {
1693 GlobalInit::I32Const(x) => (*to).val.i32 = *x,
1694 GlobalInit::I64Const(x) => (*to).val.i64 = *x,
1695 GlobalInit::F32Const(x) => (*to).val.f32 = *x,
1696 GlobalInit::F64Const(x) => (*to).val.f64 = *x,
1697 GlobalInit::V128Const(x) => (*to).val.bytes = *x.bytes(),
1698 GlobalInit::GetGlobal(x) => {
1699 let from: VMGlobalDefinition =
1700 if let Some(def_x) = module.local_global_index(*x) {
1701 instance.global(def_x)
1702 } else {
1703 instance.imported_global(*x).definition.as_ref().clone()
1704 };
1705 *to = from;
1706 }
1707 GlobalInit::RefNullConst => (*to).val.funcref = 0,
1708 GlobalInit::RefFunc(func_idx) => {
1709 let funcref = instance.func_ref(*func_idx).unwrap();
1710 (*to).val = funcref.into_raw();
1711 }
1712 GlobalInit::Expr(expr) => match eval_init_expr(expr, instance) {
1713 EvaluatedInitExpr::I32(value) => (*to).val.i32 = value,
1714 EvaluatedInitExpr::I64(value) => (*to).val.i64 = value,
1715 },
1716 }
1717 }
1718 }
1719}
1720
1721fn anyfunc_from_funcref(funcref: Option<VMFuncRef>) -> VMCallerCheckedAnyfunc {
1722 match funcref {
1723 Some(funcref) => unsafe { *funcref.0.as_ptr() },
1724 None => VMCallerCheckedAnyfunc::null(),
1725 }
1726}
1727
1728fn build_funcrefs(
1731 module_info: &ModuleInfo,
1732 ctx: &StoreObjects,
1733 imports: &Imports,
1734 finished_functions: &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1735 vmshared_signatures: &BoxedSlice<SignatureIndex, VMSignatureHash>,
1736 function_call_trampolines: &BoxedSlice<SignatureIndex, VMTrampoline>,
1737 vmctx_ptr: *mut VMContext,
1738) -> (
1739 BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
1740 BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
1741) {
1742 let mut func_refs =
1743 PrimaryMap::with_capacity(module_info.functions.len() - module_info.num_imported_functions);
1744 let mut imported_func_refs = PrimaryMap::with_capacity(module_info.num_imported_functions);
1745
1746 for import in imports.functions.values() {
1748 imported_func_refs.push(import.handle.get(ctx).anyfunc.as_ptr());
1749 }
1750
1751 for (local_index, func_ptr) in finished_functions.iter() {
1753 let index = module_info.func_index(local_index);
1754 let sig_index = module_info.functions[index];
1755 let type_signature_hash = vmshared_signatures[sig_index];
1756 let call_trampoline = function_call_trampolines[sig_index];
1757 let anyfunc = VMCallerCheckedAnyfunc {
1758 func_ptr: func_ptr.0,
1759 type_signature_hash,
1760 vmctx: VMFunctionContext { vmctx: vmctx_ptr },
1761 call_trampoline,
1762 };
1763 func_refs.push(anyfunc);
1764 }
1765 (
1766 func_refs.into_boxed_slice(),
1767 imported_func_refs.into_boxed_slice(),
1768 )
1769}