1use crate::engine::error::LinkError;
2use std::ptr::NonNull;
3use wasmer_types::{
4 FunctionType, GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
5 MemoryType, ModuleInfo, Pages, TableIndex, TableType, TagKind,
6 entity::{EntityRef, PrimaryMap},
7 target::{PointerWidth, Target},
8};
9use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects, VMTag};
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 fn create_tag(&self, kind: TagKind, ty: FunctionType) -> Result<VMTag, String> {
62 Ok(VMTag::new(kind, ty))
63 }
64
65 #[allow(clippy::result_large_err)]
70 unsafe fn create_memories(
71 &self,
72 context: &mut StoreObjects,
73 module: &ModuleInfo,
74 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
75 memory_definition_locations: &[NonNull<VMMemoryDefinition>],
76 ) -> Result<PrimaryMap<LocalMemoryIndex, InternalStoreHandle<VMMemory>>, LinkError> {
77 unsafe {
78 let num_imports = module.num_imported_memories;
79 let mut memories: PrimaryMap<LocalMemoryIndex, _> =
80 PrimaryMap::with_capacity(module.memories.len() - num_imports);
81 for (index, mdl) in memory_definition_locations
82 .iter()
83 .enumerate()
84 .take(module.memories.len())
85 .skip(num_imports)
86 {
87 let mi = MemoryIndex::new(index);
88 let ty = &module.memories[mi];
89 let style = &memory_styles[mi];
90 memories.push(InternalStoreHandle::new(
91 context,
92 self.create_vm_memory(ty, style, *mdl).map_err(|e| {
93 LinkError::Resource(format!("Failed to create memory: {e}"))
94 })?,
95 ));
96 }
97 Ok(memories)
98 }
99 }
100
101 #[allow(clippy::result_large_err)]
107 unsafe fn create_tables(
108 &self,
109 context: &mut StoreObjects,
110 module: &ModuleInfo,
111 table_styles: &PrimaryMap<TableIndex, TableStyle>,
112 table_definition_locations: &[NonNull<VMTableDefinition>],
113 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
114 unsafe {
115 let num_imports = module.num_imported_tables;
116 let mut tables: PrimaryMap<LocalTableIndex, _> =
117 PrimaryMap::with_capacity(module.tables.len() - num_imports);
118 for (index, tdl) in table_definition_locations
119 .iter()
120 .enumerate()
121 .take(module.tables.len())
122 .skip(num_imports)
123 {
124 let ti = TableIndex::new(index);
125 let ty = &module.tables[ti];
126 let style = &table_styles[ti];
127 tables.push(InternalStoreHandle::new(
128 context,
129 self.create_vm_table(ty, style, *tdl)
130 .map_err(LinkError::Resource)?,
131 ));
132 }
133 Ok(tables)
134 }
135 }
136
137 #[allow(clippy::result_large_err)]
140 fn create_globals(
141 &self,
142 context: &mut StoreObjects,
143 module: &ModuleInfo,
144 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
145 let num_imports = module.num_imported_globals;
146 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
147
148 for &global_type in module.globals.values().skip(num_imports) {
149 vmctx_globals.push(InternalStoreHandle::new(
150 context,
151 self.create_global(global_type)
152 .map_err(LinkError::Resource)?,
153 ));
154 }
155
156 Ok(vmctx_globals)
157 }
158
159 fn vmconfig(&self) -> &VMConfig {
166 &VMConfig {
167 wasm_stack_size: None,
168 }
169 }
170}
171
172#[derive(Clone)]
181pub struct BaseTunables {
182 pub static_memory_bound: Pages,
184
185 pub static_memory_offset_guard_size: u64,
187
188 pub dynamic_memory_offset_guard_size: u64,
190}
191
192impl BaseTunables {
193 pub fn for_target(target: &Target) -> Self {
195 let triple = target.triple();
196 let pointer_width: PointerWidth = triple.pointer_width().unwrap();
197 let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
198 match pointer_width {
199 PointerWidth::U16 => (0x400.into(), 0x1000),
200 PointerWidth::U32 => (0x4000.into(), 0x1_0000),
201 PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
208 };
209
210 #[cfg(target_os = "windows")]
216 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
217 #[cfg(not(target_os = "windows"))]
218 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
219
220 Self {
221 static_memory_bound,
222 static_memory_offset_guard_size,
223 dynamic_memory_offset_guard_size,
224 }
225 }
226}
227
228impl Tunables for BaseTunables {
229 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
231 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
236 if maximum <= self.static_memory_bound {
237 MemoryStyle::Static {
238 bound: self.static_memory_bound,
240 offset_guard_size: self.static_memory_offset_guard_size,
241 }
242 } else {
243 MemoryStyle::Dynamic {
244 offset_guard_size: self.dynamic_memory_offset_guard_size,
245 }
246 }
247 }
248
249 fn table_style(&self, _table: &TableType) -> TableStyle {
251 TableStyle::CallerChecksSignature
252 }
253
254 fn create_host_memory(
256 &self,
257 ty: &MemoryType,
258 style: &MemoryStyle,
259 ) -> Result<VMMemory, MemoryError> {
260 VMMemory::new(ty, style)
261 }
262
263 unsafe fn create_vm_memory(
269 &self,
270 ty: &MemoryType,
271 style: &MemoryStyle,
272 vm_definition_location: NonNull<VMMemoryDefinition>,
273 ) -> Result<VMMemory, MemoryError> {
274 unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
275 }
276
277 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
279 VMTable::new(ty, style)
280 }
281
282 unsafe fn create_vm_table(
288 &self,
289 ty: &TableType,
290 style: &TableStyle,
291 vm_definition_location: NonNull<VMTableDefinition>,
292 ) -> Result<VMTable, String> {
293 unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
294 }
295}
296
297impl Tunables for Box<dyn Tunables + Send + Sync> {
298 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
299 self.as_ref().memory_style(memory)
300 }
301
302 fn table_style(&self, table: &TableType) -> TableStyle {
303 self.as_ref().table_style(table)
304 }
305
306 fn create_host_memory(
307 &self,
308 ty: &MemoryType,
309 style: &MemoryStyle,
310 ) -> Result<VMMemory, MemoryError> {
311 self.as_ref().create_host_memory(ty, style)
312 }
313
314 unsafe fn create_vm_memory(
315 &self,
316 ty: &MemoryType,
317 style: &MemoryStyle,
318 vm_definition_location: NonNull<VMMemoryDefinition>,
319 ) -> Result<VMMemory, MemoryError> {
320 unsafe {
321 self.as_ref()
322 .create_vm_memory(ty, style, vm_definition_location)
323 }
324 }
325
326 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
327 self.as_ref().create_host_table(ty, style)
328 }
329
330 unsafe fn create_vm_table(
331 &self,
332 ty: &TableType,
333 style: &TableStyle,
334 vm_definition_location: NonNull<VMTableDefinition>,
335 ) -> Result<VMTable, String> {
336 unsafe {
337 self.as_ref()
338 .create_vm_table(ty, style, vm_definition_location)
339 }
340 }
341}
342
343impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
344 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
345 self.as_ref().memory_style(memory)
346 }
347
348 fn table_style(&self, table: &TableType) -> TableStyle {
349 self.as_ref().table_style(table)
350 }
351
352 fn create_host_memory(
353 &self,
354 ty: &MemoryType,
355 style: &MemoryStyle,
356 ) -> Result<VMMemory, MemoryError> {
357 self.as_ref().create_host_memory(ty, style)
358 }
359
360 unsafe fn create_vm_memory(
361 &self,
362 ty: &MemoryType,
363 style: &MemoryStyle,
364 vm_definition_location: NonNull<VMMemoryDefinition>,
365 ) -> Result<VMMemory, MemoryError> {
366 unsafe {
367 self.as_ref()
368 .create_vm_memory(ty, style, vm_definition_location)
369 }
370 }
371
372 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
373 self.as_ref().create_host_table(ty, style)
374 }
375
376 unsafe fn create_vm_table(
377 &self,
378 ty: &TableType,
379 style: &TableStyle,
380 vm_definition_location: NonNull<VMTableDefinition>,
381 ) -> Result<VMTable, String> {
382 unsafe {
383 self.as_ref()
384 .create_vm_table(ty, style, vm_definition_location)
385 }
386 }
387}