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, 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 (index, mdl) in memory_definition_locations
94 .iter()
95 .enumerate()
96 .take(module.memories.len())
97 .skip(num_imports)
98 {
99 let mi = MemoryIndex::new(index);
100 let ty = &module.memories[mi];
101 let style = &memory_styles[mi];
102 memories.push(InternalStoreHandle::new(
103 context,
104 self.create_vm_memory(ty, style, *mdl).map_err(|e| {
105 LinkError::Resource(format!("Failed to create memory: {e}"))
106 })?,
107 ));
108 }
109 Ok(memories)
110 }
111 }
112
113 #[allow(clippy::result_large_err)]
119 unsafe fn create_tables(
120 &self,
121 context: &mut StoreObjects,
122 module: &ModuleInfo,
123 table_styles: &PrimaryMap<TableIndex, TableStyle>,
124 table_definition_locations: &[NonNull<VMTableDefinition>],
125 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
126 unsafe {
127 let num_imports = module.num_imported_tables;
128 let mut tables: PrimaryMap<LocalTableIndex, _> =
129 PrimaryMap::with_capacity(module.tables.len() - num_imports);
130 for (index, tdl) in table_definition_locations
131 .iter()
132 .enumerate()
133 .take(module.tables.len())
134 .skip(num_imports)
135 {
136 let ti = TableIndex::new(index);
137 let ty = &module.tables[ti];
138 let style = &table_styles[ti];
139 tables.push(InternalStoreHandle::new(
140 context,
141 self.create_vm_table(ty, style, *tdl)
142 .map_err(LinkError::Resource)?,
143 ));
144 }
145 Ok(tables)
146 }
147 }
148
149 #[allow(clippy::result_large_err)]
152 fn create_globals(
153 &self,
154 context: &mut StoreObjects,
155 module: &ModuleInfo,
156 vm_definition_locations: &[NonNull<VMGlobalDefinition>],
157 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
158 let num_imports = module.num_imported_globals;
159 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
160
161 for (i, &global_type) in module.globals.values().skip(num_imports).enumerate() {
162 let location = vm_definition_locations
163 .get(i)
164 .ok_or_else(|| LinkError::Resource("global definition location missing".into()))?;
165 vmctx_globals.push(InternalStoreHandle::new(context, unsafe {
166 self.create_vm_global(global_type, *location)
167 .map_err(LinkError::Resource)?
168 }));
169 }
170
171 Ok(vmctx_globals)
172 }
173
174 fn vmconfig(&self) -> &VMConfig {
181 &VMConfig {
182 wasm_stack_size: None,
183 }
184 }
185}
186
187#[derive(Clone)]
196pub struct BaseTunables {
197 pub static_memory_bound: Pages,
199
200 pub static_memory_offset_guard_size: u64,
202
203 pub dynamic_memory_offset_guard_size: u64,
205}
206
207impl BaseTunables {
208 pub fn for_target(target: &Target) -> Self {
210 let triple = target.triple();
211 let pointer_width: PointerWidth = triple.pointer_width().unwrap();
212 let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
213 match pointer_width {
214 PointerWidth::U16 => (0x400.into(), 0x1000),
215 PointerWidth::U32 => (0x4000.into(), 0x1_0000),
216 PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
223 };
224
225 #[cfg(target_os = "windows")]
231 let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
232 #[cfg(not(target_os = "windows"))]
233 let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
234
235 Self {
236 static_memory_bound,
237 static_memory_offset_guard_size,
238 dynamic_memory_offset_guard_size,
239 }
240 }
241}
242
243impl Tunables for BaseTunables {
244 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
246 let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
251 if maximum <= self.static_memory_bound {
252 MemoryStyle::Static {
253 bound: self.static_memory_bound,
255 offset_guard_size: self.static_memory_offset_guard_size,
256 }
257 } else {
258 MemoryStyle::Dynamic {
259 offset_guard_size: self.dynamic_memory_offset_guard_size,
260 }
261 }
262 }
263
264 fn table_style(&self, _table: &TableType) -> TableStyle {
266 TableStyle::CallerChecksSignature
267 }
268
269 fn create_host_memory(
271 &self,
272 ty: &MemoryType,
273 style: &MemoryStyle,
274 ) -> Result<VMMemory, MemoryError> {
275 VMMemory::new(ty, style)
276 }
277
278 unsafe fn create_vm_memory(
284 &self,
285 ty: &MemoryType,
286 style: &MemoryStyle,
287 vm_definition_location: NonNull<VMMemoryDefinition>,
288 ) -> Result<VMMemory, MemoryError> {
289 unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
290 }
291
292 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
294 VMTable::new(ty, style)
295 }
296
297 unsafe fn create_vm_table(
303 &self,
304 ty: &TableType,
305 style: &TableStyle,
306 vm_definition_location: NonNull<VMTableDefinition>,
307 ) -> Result<VMTable, String> {
308 unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
309 }
310}
311
312impl Tunables for Box<dyn Tunables + Send + Sync> {
313 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
314 self.as_ref().memory_style(memory)
315 }
316
317 fn table_style(&self, table: &TableType) -> TableStyle {
318 self.as_ref().table_style(table)
319 }
320
321 fn create_host_memory(
322 &self,
323 ty: &MemoryType,
324 style: &MemoryStyle,
325 ) -> Result<VMMemory, MemoryError> {
326 self.as_ref().create_host_memory(ty, style)
327 }
328
329 unsafe fn create_vm_memory(
330 &self,
331 ty: &MemoryType,
332 style: &MemoryStyle,
333 vm_definition_location: NonNull<VMMemoryDefinition>,
334 ) -> Result<VMMemory, MemoryError> {
335 unsafe {
336 self.as_ref()
337 .create_vm_memory(ty, style, vm_definition_location)
338 }
339 }
340
341 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
342 self.as_ref().create_host_table(ty, style)
343 }
344
345 unsafe fn create_vm_table(
346 &self,
347 ty: &TableType,
348 style: &TableStyle,
349 vm_definition_location: NonNull<VMTableDefinition>,
350 ) -> Result<VMTable, String> {
351 unsafe {
352 self.as_ref()
353 .create_vm_table(ty, style, vm_definition_location)
354 }
355 }
356}
357
358impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
359 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
360 self.as_ref().memory_style(memory)
361 }
362
363 fn table_style(&self, table: &TableType) -> TableStyle {
364 self.as_ref().table_style(table)
365 }
366
367 fn create_host_memory(
368 &self,
369 ty: &MemoryType,
370 style: &MemoryStyle,
371 ) -> Result<VMMemory, MemoryError> {
372 self.as_ref().create_host_memory(ty, style)
373 }
374
375 unsafe fn create_vm_memory(
376 &self,
377 ty: &MemoryType,
378 style: &MemoryStyle,
379 vm_definition_location: NonNull<VMMemoryDefinition>,
380 ) -> Result<VMMemory, MemoryError> {
381 unsafe {
382 self.as_ref()
383 .create_vm_memory(ty, style, vm_definition_location)
384 }
385 }
386
387 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
388 self.as_ref().create_host_table(ty, style)
389 }
390
391 unsafe fn create_vm_table(
392 &self,
393 ty: &TableType,
394 style: &TableStyle,
395 vm_definition_location: NonNull<VMTableDefinition>,
396 ) -> Result<VMTable, String> {
397 unsafe {
398 self.as_ref()
399 .create_vm_table(ty, style, vm_definition_location)
400 }
401 }
402}