wasmer_engine/
tunables.rs

1use crate::error::LinkError;
2use loupe::MemoryUsage;
3use std::ptr::NonNull;
4use std::sync::Arc;
5use wasmer_types::entity::{EntityRef, PrimaryMap};
6use wasmer_types::{
7    GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType,
8    ModuleInfo, TableIndex, TableType,
9};
10use wasmer_vm::MemoryError;
11use wasmer_vm::{Global, Memory, Table};
12use wasmer_vm::{MemoryStyle, TableStyle};
13use wasmer_vm::{VMMemoryDefinition, VMTableDefinition};
14
15/// An engine delegates the creation of memories, tables, and globals
16/// to a foreign implementor of this trait.
17pub trait Tunables: MemoryUsage {
18    /// Construct a `MemoryStyle` for the provided `MemoryType`
19    fn memory_style(&self, memory: &MemoryType) -> MemoryStyle;
20
21    /// Construct a `TableStyle` for the provided `TableType`
22    fn table_style(&self, table: &TableType) -> TableStyle;
23
24    /// Create a memory owned by the host given a [`MemoryType`] and a [`MemoryStyle`].
25    fn create_host_memory(
26        &self,
27        ty: &MemoryType,
28        style: &MemoryStyle,
29    ) -> Result<Arc<dyn Memory>, MemoryError>;
30
31    /// Create a memory owned by the VM given a [`MemoryType`] and a [`MemoryStyle`].
32    ///
33    /// # Safety
34    /// - `vm_definition_location` must point to a valid location in VM memory.
35    unsafe fn create_vm_memory(
36        &self,
37        ty: &MemoryType,
38        style: &MemoryStyle,
39        vm_definition_location: NonNull<VMMemoryDefinition>,
40    ) -> Result<Arc<dyn Memory>, MemoryError>;
41
42    /// Create a table owned by the host given a [`TableType`] and a [`TableStyle`].
43    fn create_host_table(
44        &self,
45        ty: &TableType,
46        style: &TableStyle,
47    ) -> Result<Arc<dyn Table>, String>;
48
49    /// Create a table owned by the VM given a [`TableType`] and a [`TableStyle`].
50    ///
51    /// # Safety
52    /// - `vm_definition_location` must point to a valid location in VM memory.
53    unsafe fn create_vm_table(
54        &self,
55        ty: &TableType,
56        style: &TableStyle,
57        vm_definition_location: NonNull<VMTableDefinition>,
58    ) -> Result<Arc<dyn Table>, String>;
59
60    /// Create a global with an unset value.
61    fn create_global(&self, ty: GlobalType) -> Result<Arc<Global>, String> {
62        Ok(Arc::new(Global::new(ty)))
63    }
64
65    /// Allocate memory for just the memories of the current module.
66    unsafe fn create_memories(
67        &self,
68        module: &ModuleInfo,
69        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
70        memory_definition_locations: &[NonNull<VMMemoryDefinition>],
71    ) -> Result<PrimaryMap<LocalMemoryIndex, Arc<dyn Memory>>, LinkError> {
72        let num_imports = module.num_imported_memories;
73        let mut memories: PrimaryMap<LocalMemoryIndex, _> =
74            PrimaryMap::with_capacity(module.memories.len() - num_imports);
75        for index in num_imports..module.memories.len() {
76            let mi = MemoryIndex::new(index);
77            let ty = &module.memories[mi];
78            let style = &memory_styles[mi];
79            let mdl = memory_definition_locations[index];
80            memories.push(
81                self.create_vm_memory(ty, style, mdl)
82                    .map_err(|e| LinkError::Resource(format!("Failed to create memory: {}", e)))?,
83            );
84        }
85        Ok(memories)
86    }
87
88    /// Allocate memory for just the tables of the current module.
89    unsafe fn create_tables(
90        &self,
91        module: &ModuleInfo,
92        table_styles: &PrimaryMap<TableIndex, TableStyle>,
93        table_definition_locations: &[NonNull<VMTableDefinition>],
94    ) -> Result<PrimaryMap<LocalTableIndex, Arc<dyn Table>>, LinkError> {
95        let num_imports = module.num_imported_tables;
96        let mut tables: PrimaryMap<LocalTableIndex, _> =
97            PrimaryMap::with_capacity(module.tables.len() - num_imports);
98        for index in num_imports..module.tables.len() {
99            let ti = TableIndex::new(index);
100            let ty = &module.tables[ti];
101            let style = &table_styles[ti];
102            let tdl = table_definition_locations[index];
103            tables.push(
104                self.create_vm_table(ty, style, tdl)
105                    .map_err(LinkError::Resource)?,
106            );
107        }
108        Ok(tables)
109    }
110
111    /// Allocate memory for just the globals of the current module,
112    /// with initializers applied.
113    fn create_globals(
114        &self,
115        module: &ModuleInfo,
116    ) -> Result<PrimaryMap<LocalGlobalIndex, Arc<Global>>, LinkError> {
117        let num_imports = module.num_imported_globals;
118        let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
119
120        for &global_type in module.globals.values().skip(num_imports) {
121            vmctx_globals.push(
122                self.create_global(global_type)
123                    .map_err(LinkError::Resource)?,
124            );
125        }
126
127        Ok(vmctx_globals)
128    }
129}