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::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 => (0x1_0000.into(), 0x8000_0000),
219 };
220
221 #[cfg(target_os = "windows")]
227 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
228 #[cfg(not(target_os = "windows"))]
229 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
230
231 Self {
232 static_memory_bound,
233 static_memory_offset_guard_size,
234 dynamic_memory_offset_guard_size,
235 }
236 }
237}
238
239impl Tunables for BaseTunables {
240 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
242 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
247 if maximum <= self.static_memory_bound {
248 MemoryStyle::Static {
249 bound: self.static_memory_bound,
251 offset_guard_size: self.static_memory_offset_guard_size,
252 }
253 } else {
254 MemoryStyle::Dynamic {
255 offset_guard_size: self.dynamic_memory_offset_guard_size,
256 }
257 }
258 }
259
260 fn table_style(&self, _table: &TableType) -> TableStyle {
262 TableStyle::CallerChecksSignature
263 }
264
265 fn create_host_memory(
267 &self,
268 ty: &MemoryType,
269 style: &MemoryStyle,
270 ) -> Result<VMMemory, MemoryError> {
271 VMMemory::new(ty, style)
272 }
273
274 unsafe fn create_vm_memory(
280 &self,
281 ty: &MemoryType,
282 style: &MemoryStyle,
283 vm_definition_location: NonNull<VMMemoryDefinition>,
284 ) -> Result<VMMemory, MemoryError> {
285 unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
286 }
287
288 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
290 VMTable::new(ty, style)
291 }
292
293 unsafe fn create_vm_table(
299 &self,
300 ty: &TableType,
301 style: &TableStyle,
302 vm_definition_location: NonNull<VMTableDefinition>,
303 ) -> Result<VMTable, String> {
304 unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
305 }
306}
307
308impl Tunables for Box<dyn Tunables + Send + Sync> {
309 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
310 self.as_ref().memory_style(memory)
311 }
312
313 fn table_style(&self, table: &TableType) -> TableStyle {
314 self.as_ref().table_style(table)
315 }
316
317 fn create_host_memory(
318 &self,
319 ty: &MemoryType,
320 style: &MemoryStyle,
321 ) -> Result<VMMemory, MemoryError> {
322 self.as_ref().create_host_memory(ty, style)
323 }
324
325 unsafe fn create_vm_memory(
326 &self,
327 ty: &MemoryType,
328 style: &MemoryStyle,
329 vm_definition_location: NonNull<VMMemoryDefinition>,
330 ) -> Result<VMMemory, MemoryError> {
331 unsafe {
332 self.as_ref()
333 .create_vm_memory(ty, style, vm_definition_location)
334 }
335 }
336
337 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
338 self.as_ref().create_host_table(ty, style)
339 }
340
341 unsafe fn create_vm_table(
342 &self,
343 ty: &TableType,
344 style: &TableStyle,
345 vm_definition_location: NonNull<VMTableDefinition>,
346 ) -> Result<VMTable, String> {
347 unsafe {
348 self.as_ref()
349 .create_vm_table(ty, style, vm_definition_location)
350 }
351 }
352}
353
354impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
355 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
356 self.as_ref().memory_style(memory)
357 }
358
359 fn table_style(&self, table: &TableType) -> TableStyle {
360 self.as_ref().table_style(table)
361 }
362
363 fn create_host_memory(
364 &self,
365 ty: &MemoryType,
366 style: &MemoryStyle,
367 ) -> Result<VMMemory, MemoryError> {
368 self.as_ref().create_host_memory(ty, style)
369 }
370
371 unsafe fn create_vm_memory(
372 &self,
373 ty: &MemoryType,
374 style: &MemoryStyle,
375 vm_definition_location: NonNull<VMMemoryDefinition>,
376 ) -> Result<VMMemory, MemoryError> {
377 unsafe {
378 self.as_ref()
379 .create_vm_memory(ty, style, vm_definition_location)
380 }
381 }
382
383 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
384 self.as_ref().create_host_table(ty, style)
385 }
386
387 unsafe fn create_vm_table(
388 &self,
389 ty: &TableType,
390 style: &TableStyle,
391 vm_definition_location: NonNull<VMTableDefinition>,
392 ) -> Result<VMTable, String> {
393 unsafe {
394 self.as_ref()
395 .create_vm_table(ty, style, vm_definition_location)
396 }
397 }
398}