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, WASM_MAX_PAGES,
6 entity::PrimaryMap,
7 target::{PointerWidth, Target},
8};
9use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects, VMTag};
10use wasmer_vm::{MemoryStyle, TableStyle};
11use wasmer_vm::{VMConfig, VMGlobal, VMGlobalDefinition, 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 unsafe fn create_vm_global(
65 &self,
66 ty: GlobalType,
67 vm_definition_location: NonNull<VMGlobalDefinition>,
68 ) -> Result<VMGlobal, String> {
69 unsafe { Ok(VMGlobal::new_instance(ty, vm_definition_location)) }
70 }
71
72 fn create_tag(&self, kind: TagKind, ty: FunctionType) -> Result<VMTag, String> {
74 Ok(VMTag::new(kind, ty))
75 }
76
77 #[allow(clippy::result_large_err)]
82 unsafe fn create_memories(
83 &self,
84 context: &mut StoreObjects,
85 module: &ModuleInfo,
86 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
87 memory_definition_locations: &[NonNull<VMMemoryDefinition>],
88 ) -> Result<PrimaryMap<LocalMemoryIndex, InternalStoreHandle<VMMemory>>, LinkError> {
89 unsafe {
90 let num_imports = module.num_imported_memories;
91 let mut memories: PrimaryMap<LocalMemoryIndex, _> =
92 PrimaryMap::with_capacity(module.memories.len() - num_imports);
93 for ((mi, ty), mdl) in module
94 .memories
95 .iter()
96 .skip(num_imports)
97 .zip(memory_definition_locations)
98 {
99 let style = &memory_styles[mi];
100 memories.push(InternalStoreHandle::new(
101 context,
102 self.create_vm_memory(ty, style, *mdl).map_err(|e| {
103 LinkError::Resource(format!("Failed to create memory: {e}"))
104 })?,
105 ));
106 }
107 Ok(memories)
108 }
109 }
110
111 #[allow(clippy::result_large_err)]
117 unsafe fn create_tables(
118 &self,
119 context: &mut StoreObjects,
120 module: &ModuleInfo,
121 table_styles: &PrimaryMap<TableIndex, TableStyle>,
122 table_definition_locations: &[NonNull<VMTableDefinition>],
123 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
124 unsafe {
125 let num_imports = module.num_imported_tables;
126 let mut tables: PrimaryMap<LocalTableIndex, _> =
127 PrimaryMap::with_capacity(module.tables.len() - num_imports);
128 for ((ti, ty), tdl) in module
129 .tables
130 .iter()
131 .skip(num_imports)
132 .zip(table_definition_locations)
133 {
134 let style = &table_styles[ti];
135 tables.push(InternalStoreHandle::new(
136 context,
137 self.create_vm_table(ty, style, *tdl)
138 .map_err(LinkError::Resource)?,
139 ));
140 }
141 Ok(tables)
142 }
143 }
144
145 #[allow(clippy::result_large_err)]
148 fn create_globals(
149 &self,
150 context: &mut StoreObjects,
151 module: &ModuleInfo,
152 vm_definition_locations: &[NonNull<VMGlobalDefinition>],
153 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
154 let num_imports = module.num_imported_globals;
155 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
156
157 for (i, &global_type) in module.globals.values().skip(num_imports).enumerate() {
158 let location = vm_definition_locations
159 .get(i)
160 .ok_or_else(|| LinkError::Resource("global definition location missing".into()))?;
161 vmctx_globals.push(InternalStoreHandle::new(context, unsafe {
162 self.create_vm_global(global_type, *location)
163 .map_err(LinkError::Resource)?
164 }));
165 }
166
167 Ok(vmctx_globals)
168 }
169
170 fn vmconfig(&self) -> &VMConfig {
177 &VMConfig {
178 wasm_stack_size: None,
179 }
180 }
181}
182
183#[derive(Clone)]
192pub struct BaseTunables {
193 pub static_memory_bound: Pages,
195
196 pub static_memory_offset_guard_size: u64,
198
199 pub dynamic_memory_offset_guard_size: u64,
201}
202
203impl BaseTunables {
204 pub fn for_target(target: &Target) -> Self {
206 let triple = target.triple();
207 let pointer_width: PointerWidth = triple.pointer_width().unwrap();
208 let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
209 match pointer_width {
210 PointerWidth::U16 => (0x400.into(), 0x1000),
211 PointerWidth::U32 => (0x4000.into(), 0x1_0000),
212 PointerWidth::U64 => (WASM_MAX_PAGES.into(), 0x1_0000_0000),
222 };
223
224 #[cfg(target_os = "windows")]
230 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
231 #[cfg(not(target_os = "windows"))]
232 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
233
234 Self {
235 static_memory_bound,
236 static_memory_offset_guard_size,
237 dynamic_memory_offset_guard_size,
238 }
239 }
240}
241
242impl Tunables for BaseTunables {
243 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
245 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
250 if maximum <= self.static_memory_bound {
251 MemoryStyle::Static {
252 bound: self.static_memory_bound,
254 offset_guard_size: self.static_memory_offset_guard_size,
255 }
256 } else {
257 MemoryStyle::Dynamic {
258 offset_guard_size: self.dynamic_memory_offset_guard_size,
259 }
260 }
261 }
262
263 fn table_style(&self, _table: &TableType) -> TableStyle {
265 TableStyle::CallerChecksSignature
266 }
267
268 fn create_host_memory(
270 &self,
271 ty: &MemoryType,
272 style: &MemoryStyle,
273 ) -> Result<VMMemory, MemoryError> {
274 VMMemory::new(ty, style)
275 }
276
277 unsafe fn create_vm_memory(
283 &self,
284 ty: &MemoryType,
285 style: &MemoryStyle,
286 vm_definition_location: NonNull<VMMemoryDefinition>,
287 ) -> Result<VMMemory, MemoryError> {
288 unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
289 }
290
291 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
293 VMTable::new(ty, style)
294 }
295
296 unsafe fn create_vm_table(
302 &self,
303 ty: &TableType,
304 style: &TableStyle,
305 vm_definition_location: NonNull<VMTableDefinition>,
306 ) -> Result<VMTable, String> {
307 unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
308 }
309}
310
311impl Tunables for Box<dyn Tunables + Send + Sync> {
312 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
313 self.as_ref().memory_style(memory)
314 }
315
316 fn table_style(&self, table: &TableType) -> TableStyle {
317 self.as_ref().table_style(table)
318 }
319
320 fn create_host_memory(
321 &self,
322 ty: &MemoryType,
323 style: &MemoryStyle,
324 ) -> Result<VMMemory, MemoryError> {
325 self.as_ref().create_host_memory(ty, style)
326 }
327
328 unsafe fn create_vm_memory(
329 &self,
330 ty: &MemoryType,
331 style: &MemoryStyle,
332 vm_definition_location: NonNull<VMMemoryDefinition>,
333 ) -> Result<VMMemory, MemoryError> {
334 unsafe {
335 self.as_ref()
336 .create_vm_memory(ty, style, vm_definition_location)
337 }
338 }
339
340 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
341 self.as_ref().create_host_table(ty, style)
342 }
343
344 unsafe fn create_vm_table(
345 &self,
346 ty: &TableType,
347 style: &TableStyle,
348 vm_definition_location: NonNull<VMTableDefinition>,
349 ) -> Result<VMTable, String> {
350 unsafe {
351 self.as_ref()
352 .create_vm_table(ty, style, vm_definition_location)
353 }
354 }
355}
356
357impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
358 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
359 self.as_ref().memory_style(memory)
360 }
361
362 fn table_style(&self, table: &TableType) -> TableStyle {
363 self.as_ref().table_style(table)
364 }
365
366 fn create_host_memory(
367 &self,
368 ty: &MemoryType,
369 style: &MemoryStyle,
370 ) -> Result<VMMemory, MemoryError> {
371 self.as_ref().create_host_memory(ty, style)
372 }
373
374 unsafe fn create_vm_memory(
375 &self,
376 ty: &MemoryType,
377 style: &MemoryStyle,
378 vm_definition_location: NonNull<VMMemoryDefinition>,
379 ) -> Result<VMMemory, MemoryError> {
380 unsafe {
381 self.as_ref()
382 .create_vm_memory(ty, style, vm_definition_location)
383 }
384 }
385
386 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
387 self.as_ref().create_host_table(ty, style)
388 }
389
390 unsafe fn create_vm_table(
391 &self,
392 ty: &TableType,
393 style: &TableStyle,
394 vm_definition_location: NonNull<VMTableDefinition>,
395 ) -> Result<VMTable, String> {
396 unsafe {
397 self.as_ref()
398 .create_vm_table(ty, style, vm_definition_location)
399 }
400 }
401}