wasmer_engine/
artifact.rsuse crate::{resolve_imports, InstantiationError, Resolver, RuntimeError, Tunables};
use loupe::MemoryUsage;
use std::any::Any;
pub use wasmer_artifact::MetadataHeader;
use wasmer_artifact::{ArtifactCreate, Upcastable};
use wasmer_compiler::CpuFeature;
use wasmer_types::entity::BoxedSlice;
use wasmer_types::{DataInitializer, FunctionIndex, LocalFunctionIndex, SignatureIndex};
use wasmer_vm::{
FuncDataRegistry, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler,
VMSharedSignatureIndex, VMTrampoline,
};
pub trait Artifact: Send + Sync + Upcastable + MemoryUsage + ArtifactCreate {
fn register_frame_info(&self);
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>;
fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline>;
fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr>;
fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex>;
fn func_data_registry(&self) -> &FuncDataRegistry;
fn preinstantiate(&self) -> Result<(), InstantiationError> {
Ok(())
}
unsafe fn instantiate(
&self,
tunables: &dyn Tunables,
resolver: &dyn Resolver,
host_state: Box<dyn Any>,
) -> Result<InstanceHandle, InstantiationError> {
let host_cpu_features = CpuFeature::for_host();
if !host_cpu_features.is_superset(self.cpu_features()) {
Err(InstantiationError::CpuFeature(format!(
"{:?}",
self.cpu_features().difference(host_cpu_features)
)))?;
}
self.preinstantiate()?;
let module = self.module();
let (imports, import_function_envs) = {
let mut imports = resolve_imports(
&module,
resolver,
&self.finished_dynamic_function_trampolines(),
self.memory_styles(),
self.table_styles(),
)
.map_err(InstantiationError::Link)?;
let import_function_envs = imports.get_imported_function_envs();
(imports, import_function_envs)
};
let (allocator, memory_definition_locations, table_definition_locations) =
InstanceAllocator::new(&*module);
let finished_memories = tunables
.create_memories(&module, self.memory_styles(), &memory_definition_locations)
.map_err(InstantiationError::Link)?
.into_boxed_slice();
let finished_tables = tunables
.create_tables(&module, self.table_styles(), &table_definition_locations)
.map_err(InstantiationError::Link)?
.into_boxed_slice();
let finished_globals = tunables
.create_globals(&module)
.map_err(InstantiationError::Link)?
.into_boxed_slice();
self.register_frame_info();
let handle = InstanceHandle::new(
allocator,
module,
self.finished_functions().clone(),
self.finished_function_call_trampolines().clone(),
finished_memories,
finished_tables,
finished_globals,
imports,
self.signatures().clone(),
host_state,
import_function_envs,
)
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
Ok(handle)
}
unsafe fn finish_instantiation(
&self,
trap_handler: &(dyn TrapHandler + 'static),
handle: &InstanceHandle,
) -> Result<(), InstantiationError> {
let data_initializers = self
.data_initializers()
.iter()
.map(|init| DataInitializer {
location: init.location.clone(),
data: &*init.data,
})
.collect::<Vec<_>>();
handle
.finish_instantiation(trap_handler, &data_initializers)
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
}
}
impl dyn Artifact + 'static {
#[inline]
pub fn downcast_ref<T: 'static>(&'_ self) -> Option<&'_ T> {
self.upcast_any_ref().downcast_ref::<T>()
}
#[inline]
pub fn downcast_mut<T: 'static>(&'_ mut self) -> Option<&'_ mut T> {
self.upcast_any_mut().downcast_mut::<T>()
}
}