1use crate::{DEFAULT_MAX_TABLE_ELEMENTS, engine::error::LinkError};
2use std::ptr::NonNull;
3use wasmer_types::{
4 FunctionType, GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
5 MemoryType, ModuleInfo, TableIndex, TableType, TagKind, entity::PrimaryMap,
6};
7use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects, VMTag};
8use wasmer_vm::{MemoryStyle, TableStyle};
9use wasmer_vm::{VMConfig, VMGlobal, VMGlobalDefinition, VMMemory, VMTable};
10use wasmer_vm::{VMMemoryDefinition, VMTableDefinition};
11
12pub trait Tunables {
15 fn max_table_elements(&self) -> u32 {
18 DEFAULT_MAX_TABLE_ELEMENTS
19 }
20
21 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle;
23
24 fn table_style(&self, table: &TableType) -> TableStyle;
26
27 fn create_host_memory(
29 &self,
30 ty: &MemoryType,
31 style: &MemoryStyle,
32 ) -> Result<VMMemory, MemoryError>;
33
34 unsafe fn create_vm_memory(
39 &self,
40 ty: &MemoryType,
41 style: &MemoryStyle,
42 vm_definition_location: NonNull<VMMemoryDefinition>,
43 ) -> Result<VMMemory, MemoryError>;
44
45 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String>;
47
48 unsafe fn create_vm_table(
53 &self,
54 ty: &TableType,
55 style: &TableStyle,
56 vm_definition_location: NonNull<VMTableDefinition>,
57 ) -> Result<VMTable, String>;
58
59 fn create_global(&self, ty: GlobalType) -> Result<VMGlobal, String> {
61 Ok(VMGlobal::new(ty))
62 }
63
64 unsafe fn create_vm_global(
69 &self,
70 ty: GlobalType,
71 vm_definition_location: NonNull<VMGlobalDefinition>,
72 ) -> Result<VMGlobal, String> {
73 unsafe { Ok(VMGlobal::new_instance(ty, vm_definition_location)) }
74 }
75
76 fn create_tag(&self, kind: TagKind, ty: FunctionType) -> Result<VMTag, String> {
78 Ok(VMTag::new(kind, ty))
79 }
80
81 #[allow(clippy::result_large_err)]
86 unsafe fn create_memories(
87 &self,
88 context: &mut StoreObjects,
89 module: &ModuleInfo,
90 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
91 memory_definition_locations: &[NonNull<VMMemoryDefinition>],
92 ) -> Result<PrimaryMap<LocalMemoryIndex, InternalStoreHandle<VMMemory>>, LinkError> {
93 unsafe {
94 let num_imports = module.num_imported_memories;
95 let mut memories: PrimaryMap<LocalMemoryIndex, _> =
96 PrimaryMap::with_capacity(module.memories.len() - num_imports);
97 for ((mi, ty), mdl) in module
98 .memories
99 .iter()
100 .skip(num_imports)
101 .zip(memory_definition_locations)
102 {
103 let style = &memory_styles[mi];
104 memories.push(InternalStoreHandle::new(
105 context,
106 self.create_vm_memory(ty, style, *mdl).map_err(|e| {
107 LinkError::Resource(format!("Failed to create memory: {e}"))
108 })?,
109 ));
110 }
111 Ok(memories)
112 }
113 }
114
115 #[allow(clippy::result_large_err)]
121 unsafe fn create_tables(
122 &self,
123 context: &mut StoreObjects,
124 module: &ModuleInfo,
125 table_styles: &PrimaryMap<TableIndex, TableStyle>,
126 table_definition_locations: &[NonNull<VMTableDefinition>],
127 ) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
128 let max_table_elements = self.max_table_elements();
129 let total_table_elements = module
130 .tables
131 .values()
132 .skip(module.num_imported_tables)
133 .fold(0u32, |total, ty| total.saturating_add(ty.minimum));
134 if total_table_elements > max_table_elements {
135 return Err(LinkError::Resource(format!(
136 "Total table ({total_table_elements}) is larger than maximum allowed size ({max_table_elements})!",
137 )));
138 }
139
140 let num_imports = module.num_imported_tables;
141 let mut tables: PrimaryMap<LocalTableIndex, _> =
142 PrimaryMap::with_capacity(module.tables.len() - num_imports);
143 for ((ti, ty), tdl) in module
144 .tables
145 .iter()
146 .skip(num_imports)
147 .zip(table_definition_locations)
148 {
149 let style = &table_styles[ti];
150 tables.push(InternalStoreHandle::new(context, unsafe {
151 self.create_vm_table(ty, style, *tdl)
152 .map_err(LinkError::Resource)?
153 }));
154 }
155 Ok(tables)
156 }
157
158 #[allow(clippy::result_large_err)]
161 fn create_globals(
162 &self,
163 context: &mut StoreObjects,
164 module: &ModuleInfo,
165 vm_definition_locations: &[NonNull<VMGlobalDefinition>],
166 ) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
167 let num_imports = module.num_imported_globals;
168 let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
169
170 for (i, &global_type) in module.globals.values().skip(num_imports).enumerate() {
171 let location = vm_definition_locations
172 .get(i)
173 .ok_or_else(|| LinkError::Resource("global definition location missing".into()))?;
174 vmctx_globals.push(InternalStoreHandle::new(context, unsafe {
175 self.create_vm_global(global_type, *location)
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, Default)]
205pub struct BaseTunables {}
206
207impl BaseTunables {
208 pub fn new() -> Self {
210 Self {}
211 }
212}
213
214impl Tunables for BaseTunables {
215 fn memory_style(&self, _memory: &MemoryType) -> MemoryStyle {
217 MemoryStyle::Static
218 }
219
220 fn table_style(&self, _table: &TableType) -> TableStyle {
222 TableStyle::CallerChecksSignature
223 }
224
225 fn create_host_memory(
227 &self,
228 ty: &MemoryType,
229 style: &MemoryStyle,
230 ) -> Result<VMMemory, MemoryError> {
231 VMMemory::new(ty, style)
232 }
233
234 unsafe fn create_vm_memory(
240 &self,
241 ty: &MemoryType,
242 style: &MemoryStyle,
243 vm_definition_location: NonNull<VMMemoryDefinition>,
244 ) -> Result<VMMemory, MemoryError> {
245 unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
246 }
247
248 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
250 VMTable::new(ty, style)
251 }
252
253 unsafe fn create_vm_table(
259 &self,
260 ty: &TableType,
261 style: &TableStyle,
262 vm_definition_location: NonNull<VMTableDefinition>,
263 ) -> Result<VMTable, String> {
264 unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
265 }
266}
267
268impl Tunables for Box<dyn Tunables + Send + Sync> {
269 fn max_table_elements(&self) -> u32 {
270 self.as_ref().max_table_elements()
271 }
272
273 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
274 self.as_ref().memory_style(memory)
275 }
276
277 fn table_style(&self, table: &TableType) -> TableStyle {
278 self.as_ref().table_style(table)
279 }
280
281 fn create_host_memory(
282 &self,
283 ty: &MemoryType,
284 style: &MemoryStyle,
285 ) -> Result<VMMemory, MemoryError> {
286 self.as_ref().create_host_memory(ty, style)
287 }
288
289 unsafe fn create_vm_memory(
290 &self,
291 ty: &MemoryType,
292 style: &MemoryStyle,
293 vm_definition_location: NonNull<VMMemoryDefinition>,
294 ) -> Result<VMMemory, MemoryError> {
295 unsafe {
296 self.as_ref()
297 .create_vm_memory(ty, style, vm_definition_location)
298 }
299 }
300
301 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
302 self.as_ref().create_host_table(ty, style)
303 }
304
305 unsafe fn create_vm_table(
306 &self,
307 ty: &TableType,
308 style: &TableStyle,
309 vm_definition_location: NonNull<VMTableDefinition>,
310 ) -> Result<VMTable, String> {
311 unsafe {
312 self.as_ref()
313 .create_vm_table(ty, style, vm_definition_location)
314 }
315 }
316}
317
318impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
319 fn max_table_elements(&self) -> u32 {
320 self.as_ref().max_table_elements()
321 }
322
323 fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
324 self.as_ref().memory_style(memory)
325 }
326
327 fn table_style(&self, table: &TableType) -> TableStyle {
328 self.as_ref().table_style(table)
329 }
330
331 fn create_host_memory(
332 &self,
333 ty: &MemoryType,
334 style: &MemoryStyle,
335 ) -> Result<VMMemory, MemoryError> {
336 self.as_ref().create_host_memory(ty, style)
337 }
338
339 unsafe fn create_vm_memory(
340 &self,
341 ty: &MemoryType,
342 style: &MemoryStyle,
343 vm_definition_location: NonNull<VMMemoryDefinition>,
344 ) -> Result<VMMemory, MemoryError> {
345 unsafe {
346 self.as_ref()
347 .create_vm_memory(ty, style, vm_definition_location)
348 }
349 }
350
351 fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
352 self.as_ref().create_host_table(ty, style)
353 }
354
355 unsafe fn create_vm_table(
356 &self,
357 ty: &TableType,
358 style: &TableStyle,
359 vm_definition_location: NonNull<VMTableDefinition>,
360 ) -> Result<VMTable, String> {
361 unsafe {
362 self.as_ref()
363 .create_vm_table(ty, style, vm_definition_location)
364 }
365 }
366}