use crate::engine::error::LinkError;
use std::ptr::NonNull;
use wasmer_types::{
FunctionType, GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
MemoryType, ModuleInfo, TableIndex, TableType, TagKind, entity::PrimaryMap,
};
use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects, VMTag};
use wasmer_vm::{MemoryStyle, TableStyle};
use wasmer_vm::{VMConfig, VMGlobal, VMGlobalDefinition, VMMemory, VMTable};
use wasmer_vm::{VMMemoryDefinition, VMTableDefinition};
pub trait Tunables {
fn memory_style(&self, memory: &MemoryType) -> MemoryStyle;
fn table_style(&self, table: &TableType) -> TableStyle;
fn create_host_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
) -> Result<VMMemory, MemoryError>;
unsafe fn create_vm_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: NonNull<VMMemoryDefinition>,
) -> Result<VMMemory, MemoryError>;
fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String>;
unsafe fn create_vm_table(
&self,
ty: &TableType,
style: &TableStyle,
vm_definition_location: NonNull<VMTableDefinition>,
) -> Result<VMTable, String>;
fn create_global(&self, ty: GlobalType) -> Result<VMGlobal, String> {
Ok(VMGlobal::new(ty))
}
unsafe fn create_vm_global(
&self,
ty: GlobalType,
vm_definition_location: NonNull<VMGlobalDefinition>,
) -> Result<VMGlobal, String> {
unsafe { Ok(VMGlobal::new_instance(ty, vm_definition_location)) }
}
fn create_tag(&self, kind: TagKind, ty: FunctionType) -> Result<VMTag, String> {
Ok(VMTag::new(kind, ty))
}
#[allow(clippy::result_large_err)]
unsafe fn create_memories(
&self,
context: &mut StoreObjects,
module: &ModuleInfo,
memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
memory_definition_locations: &[NonNull<VMMemoryDefinition>],
) -> Result<PrimaryMap<LocalMemoryIndex, InternalStoreHandle<VMMemory>>, LinkError> {
unsafe {
let num_imports = module.num_imported_memories;
let mut memories: PrimaryMap<LocalMemoryIndex, _> =
PrimaryMap::with_capacity(module.memories.len() - num_imports);
for ((mi, ty), mdl) in module
.memories
.iter()
.skip(num_imports)
.zip(memory_definition_locations)
{
let style = &memory_styles[mi];
memories.push(InternalStoreHandle::new(
context,
self.create_vm_memory(ty, style, *mdl).map_err(|e| {
LinkError::Resource(format!("Failed to create memory: {e}"))
})?,
));
}
Ok(memories)
}
}
#[allow(clippy::result_large_err)]
unsafe fn create_tables(
&self,
context: &mut StoreObjects,
module: &ModuleInfo,
table_styles: &PrimaryMap<TableIndex, TableStyle>,
table_definition_locations: &[NonNull<VMTableDefinition>],
) -> Result<PrimaryMap<LocalTableIndex, InternalStoreHandle<VMTable>>, LinkError> {
unsafe {
let num_imports = module.num_imported_tables;
let mut tables: PrimaryMap<LocalTableIndex, _> =
PrimaryMap::with_capacity(module.tables.len() - num_imports);
for ((ti, ty), tdl) in module
.tables
.iter()
.skip(num_imports)
.zip(table_definition_locations)
{
let style = &table_styles[ti];
tables.push(InternalStoreHandle::new(
context,
self.create_vm_table(ty, style, *tdl)
.map_err(LinkError::Resource)?,
));
}
Ok(tables)
}
}
#[allow(clippy::result_large_err)]
fn create_globals(
&self,
context: &mut StoreObjects,
module: &ModuleInfo,
vm_definition_locations: &[NonNull<VMGlobalDefinition>],
) -> Result<PrimaryMap<LocalGlobalIndex, InternalStoreHandle<VMGlobal>>, LinkError> {
let num_imports = module.num_imported_globals;
let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports);
for (i, &global_type) in module.globals.values().skip(num_imports).enumerate() {
let location = vm_definition_locations
.get(i)
.ok_or_else(|| LinkError::Resource("global definition location missing".into()))?;
vmctx_globals.push(InternalStoreHandle::new(context, unsafe {
self.create_vm_global(global_type, *location)
.map_err(LinkError::Resource)?
}));
}
Ok(vmctx_globals)
}
fn vmconfig(&self) -> &VMConfig {
&VMConfig {
wasm_stack_size: None,
}
}
}
#[derive(Clone, Default)]
pub struct BaseTunables {}
impl BaseTunables {
pub fn new() -> Self {
Self {}
}
}
impl Tunables for BaseTunables {
fn memory_style(&self, _memory: &MemoryType) -> MemoryStyle {
MemoryStyle::Static
}
fn table_style(&self, _table: &TableType) -> TableStyle {
TableStyle::CallerChecksSignature
}
fn create_host_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
) -> Result<VMMemory, MemoryError> {
VMMemory::new(ty, style)
}
unsafe fn create_vm_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: NonNull<VMMemoryDefinition>,
) -> Result<VMMemory, MemoryError> {
unsafe { VMMemory::from_definition(ty, style, vm_definition_location) }
}
fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
VMTable::new(ty, style)
}
unsafe fn create_vm_table(
&self,
ty: &TableType,
style: &TableStyle,
vm_definition_location: NonNull<VMTableDefinition>,
) -> Result<VMTable, String> {
unsafe { VMTable::from_definition(ty, style, vm_definition_location) }
}
}
impl Tunables for Box<dyn Tunables + Send + Sync> {
fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
self.as_ref().memory_style(memory)
}
fn table_style(&self, table: &TableType) -> TableStyle {
self.as_ref().table_style(table)
}
fn create_host_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
) -> Result<VMMemory, MemoryError> {
self.as_ref().create_host_memory(ty, style)
}
unsafe fn create_vm_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: NonNull<VMMemoryDefinition>,
) -> Result<VMMemory, MemoryError> {
unsafe {
self.as_ref()
.create_vm_memory(ty, style, vm_definition_location)
}
}
fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
self.as_ref().create_host_table(ty, style)
}
unsafe fn create_vm_table(
&self,
ty: &TableType,
style: &TableStyle,
vm_definition_location: NonNull<VMTableDefinition>,
) -> Result<VMTable, String> {
unsafe {
self.as_ref()
.create_vm_table(ty, style, vm_definition_location)
}
}
}
impl Tunables for std::sync::Arc<dyn Tunables + Send + Sync> {
fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
self.as_ref().memory_style(memory)
}
fn table_style(&self, table: &TableType) -> TableStyle {
self.as_ref().table_style(table)
}
fn create_host_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
) -> Result<VMMemory, MemoryError> {
self.as_ref().create_host_memory(ty, style)
}
unsafe fn create_vm_memory(
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: NonNull<VMMemoryDefinition>,
) -> Result<VMMemory, MemoryError> {
unsafe {
self.as_ref()
.create_vm_memory(ty, style, vm_definition_location)
}
}
fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
self.as_ref().create_host_table(ty, style)
}
unsafe fn create_vm_table(
&self,
ty: &TableType,
style: &TableStyle,
vm_definition_location: NonNull<VMTableDefinition>,
) -> Result<VMTable, String> {
unsafe {
self.as_ref()
.create_vm_table(ty, style, vm_definition_location)
}
}
}