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