1use crate::engine::error::LinkError;
2use std::ptr::NonNull;
3use wasmer_types::entity::{EntityRef, PrimaryMap};
4use wasmer_types::{
5 target::{PointerWidth, Target},
6 FunctionType, GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, LocalTagIndex,
7 MemoryIndex, MemoryType, ModuleInfo, Pages, TableIndex, TableType, TagKind,
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 let num_imports = module.num_imported_memories;
78 let mut memories: PrimaryMap<LocalMemoryIndex, _> =
79 PrimaryMap::with_capacity(module.memories.len() - num_imports);
80 for (index, mdl) in memory_definition_locations
81 .iter()
82 .enumerate()
83 .take(module.memories.len())
84 .skip(num_imports)
85 {
86 let mi = MemoryIndex::new(index);
87 let ty = &module.memories[mi];
88 let style = &memory_styles[mi];
89 memories.push(InternalStoreHandle::new(
90 context,
91 self.create_vm_memory(ty, style, *mdl)
92 .map_err(|e| LinkError::Resource(format!("Failed to create memory: {e}")))?,
93 ));
94 }
95 Ok(memories)
96 }
97
98 #[allow(clippy::result_large_err)]
104 unsafe fn create_tables(
105 &self,
106 context: &mut StoreObjects,
107 module: &ModuleInfo,
108 table_styles: &PrimaryMap<TableIndex, TableStyle>,
109 table_definition_locations: &[NonNull<VMTableDefinition>],
110 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
111 let num_imports = module.num_imported_tables;
112 let mut tables: PrimaryMap<LocalTableIndex, _> =
113 PrimaryMap::with_capacity(module.tables.len() - num_imports);
114 for (index, tdl) in table_definition_locations
115 .iter()
116 .enumerate()
117 .take(module.tables.len())
118 .skip(num_imports)
119 {
120 let ti = TableIndex::new(index);
121 let ty = &module.tables[ti];
122 let style = &table_styles[ti];
123 tables.push(InternalStoreHandle::new(
124 context,
125 self.create_vm_table(ty, style, *tdl)
126 .map_err(LinkError::Resource)?,
127 ));
128 }
129 Ok(tables)
130 }
131
132 #[allow(clippy::result_large_err)]
135 fn create_tags(
136 &self,
137 context: &mut StoreObjects,
138 module: &ModuleInfo,
139 ) -> Result<PrimaryMap<LocalTagIndex, InternalStoreHandle<VMTag>>, LinkError> {
140 let num_imports = module.num_imported_tags;
141 let mut vmctx_tags = PrimaryMap::with_capacity(module.tags.len() - num_imports);
142
143 for &tag_type in module.tags.values().skip(num_imports) {
144 let sig_ty = if let Some(sig_ty) = module.signatures.get(tag_type) {
145 sig_ty
146 } else {
147 return Err(LinkError::Resource(format!(
148 "Could not find matching signature for tag index {tag_type:?}"
149 )));
150 };
151 vmctx_tags.push(InternalStoreHandle::new(
152 context,
153 self.create_tag(wasmer_types::TagKind::Exception, sig_ty.clone())
154 .map_err(LinkError::Resource)?,
155 ));
156 }
157
158 Ok(vmctx_tags)
159 }
160
161 #[allow(clippy::result_large_err)]
164 fn create_globals(
165 &self,
166 context: &mut StoreObjects,
167 module: &ModuleInfo,
168 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
169 let num_imports = module.num_imported_globals;
170 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
171
172 for &global_type in module.globals.values().skip(num_imports) {
173 vmctx_globals.push(InternalStoreHandle::new(
174 context,
175 self.create_global(global_type)
176 .map_err(LinkError::Resource)?,
177 ));
178 }
179
180 Ok(vmctx_globals)
181 }
182
183 fn vmconfig(&self) -> &VMConfig {
190 &VMConfig {
191 wasm_stack_size: None,
192 }
193 }
194}
195
196#[derive(Clone)]
205pub struct BaseTunables {
206 pub static_memory_bound: Pages,
208
209 pub static_memory_offset_guard_size: u64,
211
212 pub dynamic_memory_offset_guard_size: u64,
214}
215
216impl BaseTunables {
217 pub fn for_target(target: &Target) -> Self {
219 let triple = target.triple();
220 let pointer_width: PointerWidth = triple.pointer_width().unwrap();
221 let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
222 match pointer_width {
223 PointerWidth::U16 => (0x400.into(), 0x1000),
224 PointerWidth::U32 => (0x4000.into(), 0x1_0000),
225 PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
232 };
233
234 #[cfg(target_os = "windows")]
240 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
241 #[cfg(not(target_os = "windows"))]
242 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
243
244 Self {
245 static_memory_bound,
246 static_memory_offset_guard_size,
247 dynamic_memory_offset_guard_size,
248 }
249 }
250}
251
252impl Tunables for BaseTunables {
253 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
255 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
260 if maximum <= self.static_memory_bound {
261 MemoryStyle::Static {
262 bound: self.static_memory_bound,
264 offset_guard_size: self.static_memory_offset_guard_size,
265 }
266 } else {
267 MemoryStyle::Dynamic {
268 offset_guard_size: self.dynamic_memory_offset_guard_size,
269 }
270 }
271 }
272
273 fn table_style(&self, _table: &TableType) -> TableStyle {
275 TableStyle::CallerChecksSignature
276 }
277
278 fn create_host_memory(
280 &self,
281 ty: &MemoryType,
282 style: &MemoryStyle,
283 ) -> Result<VMMemory, MemoryError> {
284 VMMemory::new(ty, style)
285 }
286
287 unsafe fn create_vm_memory(
293 &self,
294 ty: &MemoryType,
295 style: &MemoryStyle,
296 vm_definition_location: NonNull<VMMemoryDefinition>,
297 ) -> Result<VMMemory, MemoryError> {
298 VMMemory::from_definition(ty, style, vm_definition_location)
299 }
300
301 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
303 VMTable::new(ty, style)
304 }
305
306 unsafe fn create_vm_table(
312 &self,
313 ty: &TableType,
314 style: &TableStyle,
315 vm_definition_location: NonNull<VMTableDefinition>,
316 ) -> Result<VMTable, String> {
317 VMTable::from_definition(ty, style, vm_definition_location)
318 }
319}
320
321impl Tunables for Box<dyn Tunables + Send + Sync> {
322 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
323 self.as_ref().memory_style(memory)
324 }
325
326 fn table_style(&self, table: &TableType) -> TableStyle {
327 self.as_ref().table_style(table)
328 }
329
330 fn create_host_memory(
331 &self,
332 ty: &MemoryType,
333 style: &MemoryStyle,
334 ) -> Result<VMMemory, MemoryError> {
335 self.as_ref().create_host_memory(ty, style)
336 }
337
338 unsafe fn create_vm_memory(
339 &self,
340 ty: &MemoryType,
341 style: &MemoryStyle,
342 vm_definition_location: NonNull<VMMemoryDefinition>,
343 ) -> Result<VMMemory, MemoryError> {
344 self.as_ref()
345 .create_vm_memory(ty, style, vm_definition_location)
346 }
347
348 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
349 self.as_ref().create_host_table(ty, style)
350 }
351
352 unsafe fn create_vm_table(
353 &self,
354 ty: &TableType,
355 style: &TableStyle,
356 vm_definition_location: NonNull<VMTableDefinition>,
357 ) -> Result<VMTable, String> {
358 self.as_ref()
359 .create_vm_table(ty, style, vm_definition_location)
360 }
361}
362
363impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
364 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
365 self.as_ref().memory_style(memory)
366 }
367
368 fn table_style(&self, table: &TableType) -> TableStyle {
369 self.as_ref().table_style(table)
370 }
371
372 fn create_host_memory(
373 &self,
374 ty: &MemoryType,
375 style: &MemoryStyle,
376 ) -> Result<VMMemory, MemoryError> {
377 self.as_ref().create_host_memory(ty, style)
378 }
379
380 unsafe fn create_vm_memory(
381 &self,
382 ty: &MemoryType,
383 style: &MemoryStyle,
384 vm_definition_location: NonNull<VMMemoryDefinition>,
385 ) -> Result<VMMemory, MemoryError> {
386 self.as_ref()
387 .create_vm_memory(ty, style, vm_definition_location)
388 }
389
390 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
391 self.as_ref().create_host_table(ty, style)
392 }
393
394 unsafe fn create_vm_table(
395 &self,
396 ty: &TableType,
397 style: &TableStyle,
398 vm_definition_location: NonNull<VMTableDefinition>,
399 ) -> Result<VMTable, String> {
400 self.as_ref()
401 .create_vm_table(ty, style, vm_definition_location)
402 }
403}