1use crate::engine::error::LinkError;
2use crate::types::target::{PointerWidth, Target};
3use std::ptr::NonNull;
4use wasmer_types::entity::{EntityRef, PrimaryMap};
5use wasmer_types::{
6 GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType,
7 ModuleInfo, Pages, TableIndex, TableType,
8};
9use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects};
10use wasmer_vm::{MemoryStyle, TableStyle};
11use wasmer_vm::{VMConfig, VMGlobal, VMMemory, VMTable};
12use wasmer_vm::{VMMemoryDefinition, VMTableDefinition};
13
14pub trait Tunables {
17 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle;
19
20 fn table_style(&self, table: &TableType) -> TableStyle;
22
23 fn create_host_memory(
25 &self,
26 ty: &MemoryType,
27 style: &MemoryStyle,
28 ) -> Result<VMMemory, MemoryError>;
29
30 unsafe fn create_vm_memory(
35 &self,
36 ty: &MemoryType,
37 style: &MemoryStyle,
38 vm_definition_location: NonNull<VMMemoryDefinition>,
39 ) -> Result<VMMemory, MemoryError>;
40
41 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String>;
43
44 unsafe fn create_vm_table(
49 &self,
50 ty: &TableType,
51 style: &TableStyle,
52 vm_definition_location: NonNull<VMTableDefinition>,
53 ) -> Result<VMTable, String>;
54
55 fn create_global(&self, ty: GlobalType) -> Result<VMGlobal, String> {
57 Ok(VMGlobal::new(ty))
58 }
59
60 #[allow(clippy::result_large_err)]
65 unsafe fn create_memories(
66 &self,
67 context: &mut StoreObjects,
68 module: &ModuleInfo,
69 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
70 memory_definition_locations: &[NonNull<VMMemoryDefinition>],
71 ) -> Result<PrimaryMap<LocalMemoryIndex, InternalStoreHandle<VMMemory>>, 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, mdl) in memory_definition_locations
76 .iter()
77 .enumerate()
78 .take(module.memories.len())
79 .skip(num_imports)
80 {
81 let mi = MemoryIndex::new(index);
82 let ty = &module.memories[mi];
83 let style = &memory_styles[mi];
84 memories.push(InternalStoreHandle::new(
85 context,
86 self.create_vm_memory(ty, style, *mdl)
87 .map_err(|e| LinkError::Resource(format!("Failed to create memory: {}", e)))?,
88 ));
89 }
90 Ok(memories)
91 }
92
93 #[allow(clippy::result_large_err)]
99 unsafe fn create_tables(
100 &self,
101 context: &mut StoreObjects,
102 module: &ModuleInfo,
103 table_styles: &PrimaryMap<TableIndex, TableStyle>,
104 table_definition_locations: &[NonNull<VMTableDefinition>],
105 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
106 let num_imports = module.num_imported_tables;
107 let mut tables: PrimaryMap<LocalTableIndex, _> =
108 PrimaryMap::with_capacity(module.tables.len() - num_imports);
109 for (index, tdl) in table_definition_locations
110 .iter()
111 .enumerate()
112 .take(module.tables.len())
113 .skip(num_imports)
114 {
115 let ti = TableIndex::new(index);
116 let ty = &module.tables[ti];
117 let style = &table_styles[ti];
118 tables.push(InternalStoreHandle::new(
119 context,
120 self.create_vm_table(ty, style, *tdl)
121 .map_err(LinkError::Resource)?,
122 ));
123 }
124 Ok(tables)
125 }
126
127 #[allow(clippy::result_large_err)]
130 fn create_globals(
131 &self,
132 context: &mut StoreObjects,
133 module: &ModuleInfo,
134 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
135 let num_imports = module.num_imported_globals;
136 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
137
138 for &global_type in module.globals.values().skip(num_imports) {
139 vmctx_globals.push(InternalStoreHandle::new(
140 context,
141 self.create_global(global_type)
142 .map_err(LinkError::Resource)?,
143 ));
144 }
145
146 Ok(vmctx_globals)
147 }
148
149 fn vmconfig(&self) -> &VMConfig {
156 &VMConfig {
157 wasm_stack_size: None,
158 }
159 }
160}
161
162#[derive(Clone)]
171pub struct BaseTunables {
172 pub static_memory_bound: Pages,
174
175 pub static_memory_offset_guard_size: u64,
177
178 pub dynamic_memory_offset_guard_size: u64,
180}
181
182impl BaseTunables {
183 pub fn for_target(target: &Target) -> Self {
185 let triple = target.triple();
186 let pointer_width: PointerWidth = triple.pointer_width().unwrap();
187 let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
188 match pointer_width {
189 PointerWidth::U16 => (0x400.into(), 0x1000),
190 PointerWidth::U32 => (0x4000.into(), 0x1_0000),
191 PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
198 };
199
200 #[cfg(target_os = "windows")]
206 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
207 #[cfg(not(target_os = "windows"))]
208 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
209
210 Self {
211 static_memory_bound,
212 static_memory_offset_guard_size,
213 dynamic_memory_offset_guard_size,
214 }
215 }
216}
217
218impl Tunables for BaseTunables {
219 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
221 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
226 if maximum <= self.static_memory_bound {
227 MemoryStyle::Static {
228 bound: self.static_memory_bound,
230 offset_guard_size: self.static_memory_offset_guard_size,
231 }
232 } else {
233 MemoryStyle::Dynamic {
234 offset_guard_size: self.dynamic_memory_offset_guard_size,
235 }
236 }
237 }
238
239 fn table_style(&self, _table: &TableType) -> TableStyle {
241 TableStyle::CallerChecksSignature
242 }
243
244 fn create_host_memory(
246 &self,
247 ty: &MemoryType,
248 style: &MemoryStyle,
249 ) -> Result<VMMemory, MemoryError> {
250 VMMemory::new(ty, style)
251 }
252
253 unsafe fn create_vm_memory(
259 &self,
260 ty: &MemoryType,
261 style: &MemoryStyle,
262 vm_definition_location: NonNull<VMMemoryDefinition>,
263 ) -> Result<VMMemory, MemoryError> {
264 VMMemory::from_definition(ty, style, vm_definition_location)
265 }
266
267 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
269 VMTable::new(ty, style)
270 }
271
272 unsafe fn create_vm_table(
278 &self,
279 ty: &TableType,
280 style: &TableStyle,
281 vm_definition_location: NonNull<VMTableDefinition>,
282 ) -> Result<VMTable, String> {
283 VMTable::from_definition(ty, style, vm_definition_location)
284 }
285}
286
287impl Tunables for Box<dyn Tunables + Send + Sync> {
288 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
289 self.as_ref().memory_style(memory)
290 }
291
292 fn table_style(&self, table: &TableType) -> TableStyle {
293 self.as_ref().table_style(table)
294 }
295
296 fn create_host_memory(
297 &self,
298 ty: &MemoryType,
299 style: &MemoryStyle,
300 ) -> Result<VMMemory, MemoryError> {
301 self.as_ref().create_host_memory(ty, style)
302 }
303
304 unsafe fn create_vm_memory(
305 &self,
306 ty: &MemoryType,
307 style: &MemoryStyle,
308 vm_definition_location: NonNull<VMMemoryDefinition>,
309 ) -> Result<VMMemory, MemoryError> {
310 self.as_ref()
311 .create_vm_memory(ty, style, vm_definition_location)
312 }
313
314 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
315 self.as_ref().create_host_table(ty, style)
316 }
317
318 unsafe fn create_vm_table(
319 &self,
320 ty: &TableType,
321 style: &TableStyle,
322 vm_definition_location: NonNull<VMTableDefinition>,
323 ) -> Result<VMTable, String> {
324 self.as_ref()
325 .create_vm_table(ty, style, vm_definition_location)
326 }
327}
328
329impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
330 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
331 self.as_ref().memory_style(memory)
332 }
333
334 fn table_style(&self, table: &TableType) -> TableStyle {
335 self.as_ref().table_style(table)
336 }
337
338 fn create_host_memory(
339 &self,
340 ty: &MemoryType,
341 style: &MemoryStyle,
342 ) -> Result<VMMemory, MemoryError> {
343 self.as_ref().create_host_memory(ty, style)
344 }
345
346 unsafe fn create_vm_memory(
347 &self,
348 ty: &MemoryType,
349 style: &MemoryStyle,
350 vm_definition_location: NonNull<VMMemoryDefinition>,
351 ) -> Result<VMMemory, MemoryError> {
352 self.as_ref()
353 .create_vm_memory(ty, style, vm_definition_location)
354 }
355
356 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
357 self.as_ref().create_host_table(ty, style)
358 }
359
360 unsafe fn create_vm_table(
361 &self,
362 ty: &TableType,
363 style: &TableStyle,
364 vm_definition_location: NonNull<VMTableDefinition>,
365 ) -> Result<VMTable, String> {
366 self.as_ref()
367 .create_vm_table(ty, style, vm_definition_location)
368 }
369}