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 core::mem::offset_of;
27use itertools::Itertools;
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, Option<Arc<[u8]>>>>,
95
96 funcrefs: BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
99
100 imported_funcrefs: BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
103
104 vmctx: VMContext,
109}
110
111impl fmt::Debug for Instance {
112 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
113 formatter.debug_struct("Instance").finish()
114 }
115}
116
117#[allow(clippy::cast_ptr_alignment)]
118impl Instance {
119 unsafe fn vmctx_plus_offset<T>(&self, offset: u32) -> *mut T {
122 unsafe {
123 (self.vmctx_ptr() as *mut u8)
124 .add(usize::try_from(offset).unwrap())
125 .cast()
126 }
127 }
128
129 fn module(&self) -> &Arc<ModuleInfo> {
130 &self.module
131 }
132
133 pub(crate) fn module_ref(&self) -> &ModuleInfo {
134 &self.module
135 }
136
137 pub(crate) fn context(&self) -> &StoreObjects {
138 unsafe { &*self.context }
139 }
140
141 pub(crate) fn context_mut(&mut self) -> &mut StoreObjects {
142 unsafe { &mut *self.context }
143 }
144
145 fn offsets(&self) -> &VMOffsets {
147 &self.offsets
148 }
149
150 fn imported_function(&self, index: FunctionIndex) -> &VMFunctionImport {
152 let index = usize::try_from(index.as_u32()).unwrap();
153 unsafe { &*self.imported_functions_ptr().add(index) }
154 }
155
156 fn imported_functions_ptr(&self) -> *mut VMFunctionImport {
158 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_functions_begin()) }
159 }
160
161 fn imported_table(&self, index: TableIndex) -> &VMTableImport {
163 let index = usize::try_from(index.as_u32()).unwrap();
164 unsafe { &*self.imported_tables_ptr().add(index) }
165 }
166
167 fn imported_tables_ptr(&self) -> *mut VMTableImport {
169 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_tables_begin()) }
170 }
171
172 fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
174 let index = usize::try_from(index.as_u32()).unwrap();
175 unsafe { &*self.imported_memories_ptr().add(index) }
176 }
177
178 fn imported_memories_ptr(&self) -> *mut VMMemoryImport {
180 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_memories_begin()) }
181 }
182
183 fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
185 let index = usize::try_from(index.as_u32()).unwrap();
186 unsafe { &*self.imported_globals_ptr().add(index) }
187 }
188
189 fn imported_globals_ptr(&self) -> *mut VMGlobalImport {
191 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_globals_begin()) }
192 }
193
194 #[cfg_attr(target_os = "windows", allow(dead_code))]
196 pub(crate) fn shared_tag_ptr(&self, index: TagIndex) -> &VMSharedTagIndex {
197 let index = usize::try_from(index.as_u32()).unwrap();
198 unsafe { &*self.shared_tags_ptr().add(index) }
199 }
200
201 pub(crate) fn shared_tags_ptr(&self) -> *mut VMSharedTagIndex {
203 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tag_ids_begin()) }
204 }
205
206 #[allow(dead_code)]
208 fn table(&self, index: LocalTableIndex) -> VMTableDefinition {
209 unsafe { *self.table_ptr(index).as_ref() }
210 }
211
212 #[allow(dead_code)]
213 fn set_table(&self, index: LocalTableIndex, table: &VMTableDefinition) {
215 unsafe {
216 *self.table_ptr(index).as_ptr() = *table;
217 }
218 }
219
220 fn table_ptr(&self, index: LocalTableIndex) -> NonNull<VMTableDefinition> {
222 let index = usize::try_from(index.as_u32()).unwrap();
223 NonNull::new(unsafe { self.tables_ptr().add(index) }).unwrap()
224 }
225
226 fn tables_ptr(&self) -> *mut VMTableDefinition {
228 unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tables_begin()) }
229 }
230
231 fn fixed_funcref_table_ptr(
232 &self,
233 index: LocalTableIndex,
234 ) -> Option<NonNull<VMCallerCheckedAnyfunc>> {
235 let offset = self.offsets.vmctx_fixed_funcref_table_anyfuncs(index)?;
236 Some(NonNull::new(unsafe { self.vmctx_plus_offset(offset) }).unwrap())
237 }
238
239 fn sync_fixed_funcref_table_element(
240 &self,
241 table_index: LocalTableIndex,
242 index: u32,
243 funcref: Option<VMFuncRef>,
244 ) {
245 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
246 return;
247 };
248 unsafe {
249 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
250 }
251 }
252
253 fn sync_fixed_funcref_table(&self, table_index: LocalTableIndex) {
254 let Some(base) = self.fixed_funcref_table_ptr(table_index) else {
255 return;
256 };
257 let table = self.tables[table_index].get(self.context());
258 for index in 0..table.size() {
259 let TableElement::FuncRef(funcref) = table.get(index).unwrap() else {
260 unreachable!("fixed funcref tables cannot contain externrefs");
261 };
262 unsafe {
263 *base.as_ptr().add(index as usize) = anyfunc_from_funcref(funcref);
264 }
265 }
266 }
267
268 fn sync_fixed_funcref_table_by_index(&self, table_index: TableIndex) {
269 if let Some(local_table_index) = self.module.local_table_index(table_index) {
270 self.sync_fixed_funcref_table(local_table_index);
271 }
272 }
273
274 #[allow(dead_code)]
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 local_memory_copy(
788 &self,
789 memory_index: LocalMemoryIndex,
790 dst: u32,
791 src: u32,
792 len: u32,
793 ) -> Result<(), Trap> {
794 let memory = self.memory(memory_index);
797 unsafe { memory_copy(&memory, dst, src, len) }
799 }
800
801 pub(crate) fn imported_memory_copy(
803 &self,
804 memory_index: MemoryIndex,
805 dst: u32,
806 src: u32,
807 len: u32,
808 ) -> Result<(), Trap> {
809 let import = self.imported_memory(memory_index);
810 let memory = unsafe { import.definition.as_ref() };
811 unsafe { memory_copy(memory, dst, src, len) }
813 }
814
815 pub(crate) fn local_memory_fill(
821 &self,
822 memory_index: LocalMemoryIndex,
823 dst: u32,
824 val: u32,
825 len: u32,
826 ) -> Result<(), Trap> {
827 let memory = self.memory(memory_index);
828 unsafe { memory_fill(&memory, dst, val, len) }
830 }
831
832 pub(crate) fn imported_memory_fill(
838 &self,
839 memory_index: MemoryIndex,
840 dst: u32,
841 val: u32,
842 len: u32,
843 ) -> Result<(), Trap> {
844 let import = self.imported_memory(memory_index);
845 let memory = unsafe { import.definition.as_ref() };
846 unsafe { memory_fill(memory, dst, val, len) }
848 }
849
850 pub(crate) fn memory_init(
858 &self,
859 memory_index: MemoryIndex,
860 data_index: DataIndex,
861 dst: u32,
862 src: u32,
863 len: u32,
864 ) -> Result<(), Trap> {
865 let memory = self.get_vmmemory(memory_index);
868 let passive_data = self.passive_data.borrow();
869 let data = passive_data
873 .get(&data_index)
874 .and_then(|d| d.as_deref())
875 .unwrap_or(&[]);
876
877 let current_length = unsafe { memory.vmmemory().as_ref().current_length };
878 if src.checked_add(len).is_none_or(|n| n as usize > data.len())
879 || dst
880 .checked_add(len)
881 .is_none_or(|m| usize::try_from(m).unwrap() > current_length)
882 {
883 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
884 }
885 let src_slice = &data[src as usize..(src + len) as usize];
886 unsafe { memory.initialize_with_data(dst as usize, src_slice) }
887 }
888
889 pub(crate) fn data_drop(&self, data_index: DataIndex) {
891 let mut passive_data = self.passive_data.borrow_mut();
892 if let Some(slot) = passive_data.get_mut(&data_index) {
895 *slot = None;
896 }
897 }
898
899 pub(crate) fn get_table(&mut self, table_index: TableIndex) -> &mut VMTable {
902 if let Some(local_table_index) = self.module.local_table_index(table_index) {
903 self.get_local_table(local_table_index)
904 } else {
905 self.get_foreign_table(table_index)
906 }
907 }
908
909 pub(crate) fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
911 let table = self.tables[index];
912 table.get_mut(self.context_mut())
913 }
914
915 pub(crate) fn get_foreign_table(&mut self, index: TableIndex) -> &mut VMTable {
917 let import = self.imported_table(index);
918 let table = import.handle;
919 table.get_mut(self.context_mut())
920 }
921
922 pub(crate) fn get_table_handle(
925 &mut self,
926 table_index: TableIndex,
927 ) -> InternalStoreHandle<VMTable> {
928 if let Some(local_table_index) = self.module.local_table_index(table_index) {
929 self.tables[local_table_index]
930 } else {
931 self.imported_table(table_index).handle
932 }
933 }
934
935 unsafe fn memory_wait(
938 memory: &mut VMMemory,
939 dst: u32,
940 expected: ExpectedValue,
941 timeout: i64,
942 ) -> Result<u32, Trap> {
943 let timeout = if timeout < 0 {
944 None
945 } else {
946 Some(std::time::Duration::from_nanos(timeout as u64))
947 };
948 match unsafe { memory.do_wait(dst, expected, timeout) } {
949 Ok(count) => Ok(count),
950 Err(_err) => Err(Trap::lib(TrapCode::HostInterrupt)),
951 }
952 }
953
954 pub(crate) fn local_memory_wait32(
956 &mut self,
957 memory_index: LocalMemoryIndex,
958 dst: u32,
959 val: u32,
960 timeout: i64,
961 ) -> Result<u32, Trap> {
962 let memory = self.memory(memory_index);
963 let ret = unsafe { memory32_atomic_check32(&memory, dst, val) };
969
970 if let Ok(mut ret) = ret {
971 if ret == 0 {
972 let memory = self.get_local_vmmemory_mut(memory_index);
973 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
975 }
976 Ok(ret)
977 } else {
978 ret
979 }
980 }
981
982 pub(crate) fn imported_memory_wait32(
984 &mut self,
985 memory_index: MemoryIndex,
986 dst: u32,
987 val: u32,
988 timeout: i64,
989 ) -> Result<u32, Trap> {
990 let import = self.imported_memory(memory_index);
991 let memory = unsafe { import.definition.as_ref() };
992 let ret = unsafe { memory32_atomic_check32(memory, dst, val) };
998
999 if let Ok(mut ret) = ret {
1000 if ret == 0 {
1001 let memory = self.get_vmmemory_mut(memory_index);
1002 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U32(val), timeout)? };
1004 }
1005 Ok(ret)
1006 } else {
1007 ret
1008 }
1009 }
1010
1011 pub(crate) fn local_memory_wait64(
1013 &mut self,
1014 memory_index: LocalMemoryIndex,
1015 dst: u32,
1016 val: u64,
1017 timeout: i64,
1018 ) -> Result<u32, Trap> {
1019 let memory = self.memory(memory_index);
1020 let ret = unsafe { memory32_atomic_check64(&memory, dst, val) };
1026
1027 if let Ok(mut ret) = ret {
1028 if ret == 0 {
1029 let memory = self.get_local_vmmemory_mut(memory_index);
1030 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1032 }
1033 Ok(ret)
1034 } else {
1035 ret
1036 }
1037 }
1038
1039 pub(crate) fn imported_memory_wait64(
1041 &mut self,
1042 memory_index: MemoryIndex,
1043 dst: u32,
1044 val: u64,
1045 timeout: i64,
1046 ) -> Result<u32, Trap> {
1047 let import = self.imported_memory(memory_index);
1048 let memory = unsafe { import.definition.as_ref() };
1049 let ret = unsafe { memory32_atomic_check64(memory, dst, val) };
1055
1056 if let Ok(mut ret) = ret {
1057 if ret == 0 {
1058 let memory = self.get_vmmemory_mut(memory_index);
1059 ret = unsafe { Self::memory_wait(memory, dst, ExpectedValue::U64(val), timeout)? };
1061 }
1062 Ok(ret)
1063 } else {
1064 ret
1065 }
1066 }
1067
1068 pub(crate) fn local_memory_notify(
1070 &mut self,
1071 memory_index: LocalMemoryIndex,
1072 dst: u32,
1073 count: u32,
1074 ) -> Result<u32, Trap> {
1075 let memory = self.get_local_vmmemory_mut(memory_index);
1076 Ok(memory.do_notify(dst, count))
1077 }
1078
1079 pub(crate) fn imported_memory_notify(
1081 &mut self,
1082 memory_index: MemoryIndex,
1083 dst: u32,
1084 count: u32,
1085 ) -> Result<u32, Trap> {
1086 let memory = self.get_vmmemory_mut(memory_index);
1087 Ok(memory.do_notify(dst, count))
1088 }
1089}
1090
1091#[derive(Debug, Eq, PartialEq)]
1096pub struct VMInstance {
1097 instance_layout: Layout,
1099
1100 instance: NonNull<Instance>,
1110}
1111
1112impl Drop for VMInstance {
1116 fn drop(&mut self) {
1117 let instance_ptr = self.instance.as_ptr();
1118
1119 unsafe {
1120 instance_ptr.drop_in_place();
1122 std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
1124 }
1125 }
1126}
1127
1128impl VMInstance {
1129 #[allow(clippy::too_many_arguments)]
1151 pub unsafe fn new(
1152 allocator: InstanceAllocator,
1153 module: Arc<ModuleInfo>,
1154 context: &mut StoreObjects,
1155 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1156 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
1157 finished_memories: BoxedSlice<LocalMemoryIndex, InternalStoreHandle<VMMemory>>,
1158 finished_tables: BoxedSlice<LocalTableIndex, InternalStoreHandle<VMTable>>,
1159 finished_globals: BoxedSlice<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>,
1160 tags: BoxedSlice<TagIndex, InternalStoreHandle<VMTag>>,
1161 imports: Imports,
1162 vmshared_signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
1163 ) -> Result<Self, Trap> {
1164 unsafe {
1165 let vmctx_tags = tags
1166 .values()
1167 .map(|m: &InternalStoreHandle<VMTag>| VMSharedTagIndex::new(m.index() as u32))
1168 .collect::<PrimaryMap<TagIndex, VMSharedTagIndex>>()
1169 .into_boxed_slice();
1170 let passive_data = RefCell::new(
1173 module
1174 .passive_data
1175 .iter()
1176 .map(|(&idx, bytes)| (idx, Some(Arc::clone(bytes))))
1177 .collect::<HashMap<_, _>>(),
1178 );
1179
1180 let handle = {
1181 let offsets = allocator.offsets().clone();
1182 let funcrefs = PrimaryMap::new().into_boxed_slice();
1184 let imported_funcrefs = PrimaryMap::new().into_boxed_slice();
1185 let instance = Instance {
1187 module,
1188 context,
1189 offsets,
1190 memories: finished_memories,
1191 tables: finished_tables,
1192 tags,
1193 globals: finished_globals,
1194 functions: finished_functions,
1195 function_call_trampolines: finished_function_call_trampolines,
1196 passive_elements: Default::default(),
1197 passive_data,
1198 funcrefs,
1199 imported_funcrefs,
1200 vmctx: VMContext {},
1201 };
1202
1203 let mut instance_handle = allocator.into_vminstance(instance);
1204
1205 {
1207 let instance = instance_handle.instance_mut();
1208 let vmctx_ptr = instance.vmctx_ptr();
1209 (instance.funcrefs, instance.imported_funcrefs) = build_funcrefs(
1210 &instance.module,
1211 context,
1212 &imports,
1213 &instance.functions,
1214 &vmshared_signatures,
1215 &instance.function_call_trampolines,
1216 vmctx_ptr,
1217 );
1218 for local_table_index in instance.tables.keys() {
1219 instance.sync_fixed_funcref_table(local_table_index);
1220 }
1221 }
1222
1223 instance_handle
1224 };
1225 let instance = handle.instance();
1226
1227 ptr::copy(
1228 vmctx_tags.values().as_slice().as_ptr(),
1229 instance.shared_tags_ptr(),
1230 vmctx_tags.len(),
1231 );
1232 ptr::copy(
1233 imports.functions.values().as_slice().as_ptr(),
1234 instance.imported_functions_ptr(),
1235 imports.functions.len(),
1236 );
1237 ptr::copy(
1238 imports.tables.values().as_slice().as_ptr(),
1239 instance.imported_tables_ptr(),
1240 imports.tables.len(),
1241 );
1242 ptr::copy(
1243 imports.memories.values().as_slice().as_ptr(),
1244 instance.imported_memories_ptr(),
1245 imports.memories.len(),
1246 );
1247 ptr::copy(
1248 imports.globals.values().as_slice().as_ptr(),
1249 instance.imported_globals_ptr(),
1250 imports.globals.len(),
1251 );
1252 ptr::write(
1256 instance.builtin_functions_ptr(),
1257 VMBuiltinFunctionsArray::initialized(),
1258 );
1259
1260 initialize_passive_elements(instance);
1263 initialize_globals(instance);
1264
1265 Ok(handle)
1266 }
1267 }
1268
1269 pub(crate) fn instance(&self) -> &Instance {
1271 unsafe { self.instance.as_ref() }
1272 }
1273
1274 pub(crate) fn instance_mut(&mut self) -> &mut Instance {
1276 unsafe { self.instance.as_mut() }
1277 }
1278
1279 pub unsafe fn finish_instantiation(
1285 &mut self,
1286 config: &VMConfig,
1287 trap_handler: Option<*const TrapHandlerFn<'static>>,
1288 data_initializers: &[DataInitializer<'_>],
1289 ) -> Result<(), Trap> {
1290 let instance = self.instance_mut();
1291
1292 initialize_tables(instance)?;
1294 initialize_memories(instance, data_initializers)?;
1295
1296 instance.invoke_start_function(config, trap_handler)?;
1299 Ok(())
1300 }
1301
1302 pub fn vmctx(&self) -> &VMContext {
1304 self.instance().vmctx()
1305 }
1306
1307 pub fn vmctx_ptr(&self) -> *mut VMContext {
1309 self.instance().vmctx_ptr()
1310 }
1311
1312 pub fn vmoffsets(&self) -> &VMOffsets {
1316 self.instance().offsets()
1317 }
1318
1319 pub fn module(&self) -> &Arc<ModuleInfo> {
1321 self.instance().module()
1322 }
1323
1324 pub fn module_ref(&self) -> &ModuleInfo {
1326 self.instance().module_ref()
1327 }
1328
1329 pub fn lookup(&mut self, field: &str) -> Option<VMExtern> {
1331 let export = *self.module_ref().exports.get(field)?;
1332
1333 Some(self.lookup_by_declaration(export))
1334 }
1335
1336 pub fn lookup_by_declaration(&mut self, export: ExportIndex) -> VMExtern {
1338 let instance = self.instance();
1339
1340 match export {
1341 ExportIndex::Function(index) => {
1342 let sig_index = &instance.module.functions[index];
1343 let handle = if let Some(def_index) = instance.module.local_func_index(index) {
1344 let signature = instance.module.signatures[*sig_index].clone();
1347 let vm_function = VMFunction {
1348 anyfunc: MaybeInstanceOwned::Instance(NonNull::from(
1349 &instance.funcrefs[def_index],
1350 )),
1351 signature,
1352 kind: VMFunctionKind::Static,
1357 host_data: Box::new(()),
1358 };
1359 InternalStoreHandle::new(self.instance_mut().context_mut(), vm_function)
1360 } else {
1361 let import = instance.imported_function(index);
1362 import.handle
1363 };
1364
1365 VMExtern::Function(handle)
1366 }
1367 ExportIndex::Table(index) => {
1368 let handle = if let Some(def_index) = instance.module.local_table_index(index) {
1369 instance.tables[def_index]
1370 } else {
1371 let import = instance.imported_table(index);
1372 import.handle
1373 };
1374 VMExtern::Table(handle)
1375 }
1376 ExportIndex::Memory(index) => {
1377 let handle = if let Some(def_index) = instance.module.local_memory_index(index) {
1378 instance.memories[def_index]
1379 } else {
1380 let import = instance.imported_memory(index);
1381 import.handle
1382 };
1383 VMExtern::Memory(handle)
1384 }
1385 ExportIndex::Global(index) => {
1386 let handle = if let Some(def_index) = instance.module.local_global_index(index) {
1387 instance.globals[def_index]
1388 } else {
1389 let import = instance.imported_global(index);
1390 import.handle
1391 };
1392 VMExtern::Global(handle)
1393 }
1394
1395 ExportIndex::Tag(index) => {
1396 let handle = instance.tags[index];
1397 VMExtern::Tag(handle)
1398 }
1399 }
1400 }
1401
1402 pub fn exports(&self) -> indexmap::map::Iter<'_, String, ExportIndex> {
1408 self.module().exports.iter()
1409 }
1410
1411 pub fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex {
1413 self.instance().memory_index(memory)
1414 }
1415
1416 pub fn memory_grow<IntoPages>(
1421 &mut self,
1422 memory_index: LocalMemoryIndex,
1423 delta: IntoPages,
1424 ) -> Result<Pages, MemoryError>
1425 where
1426 IntoPages: Into<Pages>,
1427 {
1428 self.instance_mut().memory_grow(memory_index, delta)
1429 }
1430
1431 pub fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex {
1433 self.instance().table_index(table)
1434 }
1435
1436 pub fn table_grow(
1441 &mut self,
1442 table_index: LocalTableIndex,
1443 delta: u32,
1444 init_value: TableElement,
1445 ) -> Option<u32> {
1446 self.instance_mut()
1447 .table_grow(table_index, delta, init_value)
1448 }
1449
1450 pub fn table_get(&self, table_index: LocalTableIndex, index: u32) -> Option<TableElement> {
1454 self.instance().table_get(table_index, index)
1455 }
1456
1457 pub fn table_set(
1461 &mut self,
1462 table_index: LocalTableIndex,
1463 index: u32,
1464 val: TableElement,
1465 ) -> Result<(), Trap> {
1466 self.instance_mut().table_set(table_index, index, val)
1467 }
1468
1469 pub fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable {
1471 self.instance_mut().get_local_table(index)
1472 }
1473}
1474
1475#[allow(clippy::mut_from_ref)]
1476#[allow(dead_code)]
1477unsafe fn get_memory_slice<'instance>(
1479 init: &DataInitializer<'_>,
1480 instance: &'instance Instance,
1481) -> &'instance mut [u8] {
1482 unsafe {
1483 let memory = if let Some(local_memory_index) = instance
1484 .module
1485 .local_memory_index(init.location.memory_index)
1486 {
1487 instance.memory(local_memory_index)
1488 } else {
1489 let import = instance.imported_memory(init.location.memory_index);
1490 *import.definition.as_ref()
1491 };
1492 slice::from_raw_parts_mut(memory.base, memory.current_length)
1493 }
1494}
1495
1496fn get_global(index: GlobalIndex, instance: &Instance) -> RawValue {
1497 unsafe {
1498 if let Some(local_global_index) = instance.module.local_global_index(index) {
1499 instance.global(local_global_index).val
1500 } else {
1501 instance.imported_global(index).definition.as_ref().val
1502 }
1503 }
1504}
1505
1506enum EvaluatedInitExpr {
1507 I32(i32),
1508 I64(i64),
1509}
1510
1511fn eval_init_expr(expr: &InitExpr, instance: &Instance) -> EvaluatedInitExpr {
1512 if expr
1513 .ops()
1514 .first()
1515 .expect("missing expression")
1516 .is_32bit_expression()
1517 {
1518 let mut stack = Vec::with_capacity(expr.ops().len());
1519 for op in expr.ops() {
1520 match *op {
1521 InitExprOp::I32Const(value) => stack.push(value),
1522 InitExprOp::GlobalGetI32(global) => {
1523 stack.push(unsafe { get_global(global, instance).i32 })
1524 }
1525 InitExprOp::I32Add => {
1526 let rhs = stack.pop().expect("invalid init expr stack for i32.add");
1527 let lhs = stack.pop().expect("invalid init expr stack for i32.add");
1528 stack.push(lhs.wrapping_add(rhs));
1529 }
1530 InitExprOp::I32Sub => {
1531 let rhs = stack.pop().expect("invalid init expr stack for i32.sub");
1532 let lhs = stack.pop().expect("invalid init expr stack for i32.sub");
1533 stack.push(lhs.wrapping_sub(rhs));
1534 }
1535 InitExprOp::I32Mul => {
1536 let rhs = stack.pop().expect("invalid init expr stack for i32.mul");
1537 let lhs = stack.pop().expect("invalid init expr stack for i32.mul");
1538 stack.push(lhs.wrapping_mul(rhs));
1539 }
1540 _ => {
1541 panic!("unexpected init expr statement: {op:?}");
1542 }
1543 }
1544 }
1545 EvaluatedInitExpr::I32(
1546 stack
1547 .into_iter()
1548 .exactly_one()
1549 .expect("invalid init expr stack shape"),
1550 )
1551 } else {
1552 let mut stack = Vec::with_capacity(expr.ops().len());
1553 for op in expr.ops() {
1554 match *op {
1555 InitExprOp::I64Const(value) => stack.push(value),
1556 InitExprOp::GlobalGetI64(global) => {
1557 stack.push(unsafe { get_global(global, instance).i64 })
1558 }
1559 InitExprOp::I64Add => {
1560 let rhs = stack.pop().expect("invalid init expr stack for i64.add");
1561 let lhs = stack.pop().expect("invalid init expr stack for i64.add");
1562 stack.push(lhs.wrapping_add(rhs));
1563 }
1564 InitExprOp::I64Sub => {
1565 let rhs = stack.pop().expect("invalid init expr stack for i64.sub");
1566 let lhs = stack.pop().expect("invalid init expr stack for i64.sub");
1567 stack.push(lhs.wrapping_sub(rhs));
1568 }
1569 InitExprOp::I64Mul => {
1570 let rhs = stack.pop().expect("invalid init expr stack for i64.mul");
1571 let lhs = stack.pop().expect("invalid init expr stack for i64.mul");
1572 stack.push(lhs.wrapping_mul(rhs));
1573 }
1574 _ => {
1575 panic!("unexpected init expr statement: {op:?}");
1576 }
1577 }
1578 }
1579 EvaluatedInitExpr::I64(
1580 stack
1581 .into_iter()
1582 .exactly_one()
1583 .expect("invalid init expr stack shape"),
1584 )
1585 }
1586}
1587
1588fn initialize_tables(instance: &mut Instance) -> Result<(), Trap> {
1590 let module = Arc::clone(&instance.module);
1591 for init in &module.table_initializers {
1592 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.offset_expr, instance) else {
1593 panic!("unexpected expression type, expected i32");
1594 };
1595 if start < 0 {
1596 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1597 }
1598 let start = start as usize;
1599 let table = instance.get_table_handle(init.table_index);
1600 let table = unsafe { table.get_mut(&mut *instance.context) };
1601
1602 if start
1603 .checked_add(init.elements.len())
1604 .is_none_or(|end| end > table.size() as usize)
1605 {
1606 return Err(Trap::lib(TrapCode::TableAccessOutOfBounds));
1607 }
1608
1609 if let wasmer_types::Type::FuncRef = table.ty().ty {
1610 for (i, func_idx) in init.elements.iter().enumerate() {
1611 let anyfunc = instance.func_ref(*func_idx);
1612 table
1613 .set_with_construction(
1614 u32::try_from(start + i).unwrap(),
1615 TableElement::FuncRef(anyfunc),
1616 true,
1617 )
1618 .unwrap();
1619 }
1620 } else {
1621 for i in 0..init.elements.len() {
1622 table
1623 .set_with_construction(
1624 u32::try_from(start + i).unwrap(),
1625 TableElement::ExternRef(None),
1626 true,
1627 )
1628 .unwrap();
1629 }
1630 }
1631
1632 instance.sync_fixed_funcref_table_by_index(init.table_index);
1633 }
1634
1635 Ok(())
1636}
1637
1638fn initialize_passive_elements(instance: &Instance) {
1642 let mut passive_elements = instance.passive_elements.borrow_mut();
1643 debug_assert!(
1644 passive_elements.is_empty(),
1645 "should only be called once, at initialization time"
1646 );
1647
1648 passive_elements.extend(instance.module.passive_elements.iter().filter_map(
1649 |(&idx, segments)| -> Option<(ElemIndex, Box<[Option<VMFuncRef>]>)> {
1650 if segments.is_empty() {
1651 None
1652 } else {
1653 Some((
1654 idx,
1655 segments
1656 .iter()
1657 .map(|s| instance.func_ref(*s))
1658 .collect::<Box<[Option<VMFuncRef>]>>(),
1659 ))
1660 }
1661 },
1662 ));
1663}
1664
1665fn initialize_memories(
1667 instance: &mut Instance,
1668 data_initializers: &[DataInitializer<'_>],
1669) -> Result<(), Trap> {
1670 for init in data_initializers {
1671 let memory = instance.get_vmmemory(init.location.memory_index);
1672
1673 let EvaluatedInitExpr::I32(start) = eval_init_expr(&init.location.offset_expr, instance)
1674 else {
1675 panic!("unexpected expression type, expected i32");
1676 };
1677 if start < 0 {
1678 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1679 }
1680 let start = start as usize;
1681 unsafe {
1682 let current_length = memory.vmmemory().as_ref().current_length;
1683 if start
1684 .checked_add(init.data.len())
1685 .is_none_or(|end| end > current_length)
1686 {
1687 return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
1688 }
1689 memory.initialize_with_data(start, init.data)?;
1690 }
1691 }
1692
1693 Ok(())
1694}
1695
1696fn initialize_globals(instance: &Instance) {
1697 let module = Arc::clone(&instance.module);
1698 for (index, initializer) in module.global_initializers.iter() {
1699 unsafe {
1700 let to = instance.global_ptr(index).as_ptr();
1701 match initializer {
1702 GlobalInit::I32Const(x) => (*to).val.i32 = *x,
1703 GlobalInit::I64Const(x) => (*to).val.i64 = *x,
1704 GlobalInit::F32Const(x) => (*to).val.f32 = *x,
1705 GlobalInit::F64Const(x) => (*to).val.f64 = *x,
1706 GlobalInit::V128Const(x) => (*to).val.bytes = *x.bytes(),
1707 GlobalInit::GetGlobal(x) => {
1708 let from: VMGlobalDefinition =
1709 if let Some(def_x) = module.local_global_index(*x) {
1710 instance.global(def_x)
1711 } else {
1712 instance.imported_global(*x).definition.as_ref().clone()
1713 };
1714 *to = from;
1715 }
1716 GlobalInit::RefNullConst => (*to).val.funcref = 0,
1717 GlobalInit::RefFunc(func_idx) => {
1718 let funcref = instance.func_ref(*func_idx).unwrap();
1719 (*to).val = funcref.into_raw();
1720 }
1721 GlobalInit::Expr(expr) => match eval_init_expr(expr, instance) {
1722 EvaluatedInitExpr::I32(value) => (*to).val.i32 = value,
1723 EvaluatedInitExpr::I64(value) => (*to).val.i64 = value,
1724 },
1725 }
1726 }
1727 }
1728}
1729
1730fn anyfunc_from_funcref(funcref: Option<VMFuncRef>) -> VMCallerCheckedAnyfunc {
1731 match funcref {
1732 Some(funcref) => unsafe { *funcref.0.as_ptr() },
1733 None => VMCallerCheckedAnyfunc::null(),
1734 }
1735}
1736
1737fn build_funcrefs(
1740 module_info: &ModuleInfo,
1741 ctx: &StoreObjects,
1742 imports: &Imports,
1743 finished_functions: &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
1744 vmshared_signatures: &BoxedSlice<SignatureIndex, VMSignatureHash>,
1745 function_call_trampolines: &BoxedSlice<SignatureIndex, VMTrampoline>,
1746 vmctx_ptr: *mut VMContext,
1747) -> (
1748 BoxedSlice<LocalFunctionIndex, VMCallerCheckedAnyfunc>,
1749 BoxedSlice<FunctionIndex, NonNull<VMCallerCheckedAnyfunc>>,
1750) {
1751 let mut func_refs =
1752 PrimaryMap::with_capacity(module_info.functions.len() - module_info.num_imported_functions);
1753 let mut imported_func_refs = PrimaryMap::with_capacity(module_info.num_imported_functions);
1754
1755 for import in imports.functions.values() {
1757 imported_func_refs.push(import.handle.get(ctx).anyfunc.as_ptr());
1758 }
1759
1760 for (local_index, func_ptr) in finished_functions.iter() {
1762 let index = module_info.func_index(local_index);
1763 let sig_index = module_info.functions[index];
1764 let type_signature_hash = vmshared_signatures[sig_index];
1765 let call_trampoline = function_call_trampolines[sig_index];
1766 let anyfunc = VMCallerCheckedAnyfunc {
1767 func_ptr: func_ptr.0,
1768 type_signature_hash,
1769 vmctx: VMFunctionContext { vmctx: vmctx_ptr },
1770 call_trampoline,
1771 };
1772 func_refs.push(anyfunc);
1773 }
1774 (
1775 func_refs.into_boxed_slice(),
1776 imported_func_refs.into_boxed_slice(),
1777 )
1778}