264 lines
9.3 KiB
Rust
Raw Normal View History

2017-11-27 16:22:00 +03:00
//! This module provides a way to create wasm modules that is backed in
//! a native Rust code.
2017-05-18 15:08:55 +03:00
use std::sync::Arc;
use std::collections::HashMap;
2017-06-14 17:07:22 +03:00
use std::borrow::Cow;
2017-05-19 09:36:50 +03:00
use parking_lot::RwLock;
2017-06-26 11:54:17 +03:00
use elements::{Internal, ValueType};
2017-11-25 22:55:45 +03:00
use interpreter::Error;
2017-05-18 15:08:55 +03:00
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
2017-06-26 11:54:17 +03:00
CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
2017-05-18 15:08:55 +03:00
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
2017-06-13 12:01:59 +03:00
use interpreter::variable::{VariableInstance, VariableType};
2017-05-18 15:08:55 +03:00
/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
2017-07-31 11:58:24 +03:00
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;
2017-05-18 15:08:55 +03:00
2017-05-19 09:36:50 +03:00
/// User functions executor.
2017-11-25 22:55:45 +03:00
pub trait UserFunctionExecutor {
2017-05-19 09:36:50 +03:00
/// Execute function with given name.
2017-11-25 22:55:45 +03:00
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
2017-05-18 15:08:55 +03:00
}
2017-06-14 18:02:31 +03:00
/// User function descriptor
2017-06-26 11:54:17 +03:00
#[derive(Debug, Clone)]
2017-06-14 17:07:22 +03:00
pub enum UserFunctionDescriptor {
2017-06-14 18:52:47 +03:00
/// Static function definition
2017-06-26 11:54:17 +03:00
Static(&'static str, &'static [ValueType], Option<ValueType>),
2017-06-14 18:52:47 +03:00
/// Dynamic heap function definition
2017-06-26 11:54:17 +03:00
Heap(String, Vec<ValueType>, Option<ValueType>),
2017-06-14 17:07:22 +03:00
}
2017-06-26 11:54:17 +03:00
impl UserFunctionDescriptor {
2017-06-14 17:07:22 +03:00
/// New function with statically known params
pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
2017-06-26 11:54:17 +03:00
UserFunctionDescriptor::Static(name, params, result)
2017-06-14 17:07:22 +03:00
}
/// New function with statically unknown params
pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
2017-06-26 11:54:17 +03:00
UserFunctionDescriptor::Heap(name, params, result)
2017-06-14 17:07:22 +03:00
}
/// Name of the function
pub fn name(&self) -> &str {
2017-06-26 11:54:17 +03:00
match self {
&UserFunctionDescriptor::Static(name, _, _) => name,
&UserFunctionDescriptor::Heap(ref name, _, _) => name,
2017-06-14 17:07:22 +03:00
}
}
/// Arguments of the function
pub fn params(&self) -> &[ValueType] {
2017-06-26 11:54:17 +03:00
match self {
&UserFunctionDescriptor::Static(_, params, _) => params,
&UserFunctionDescriptor::Heap(_, ref params, _) => params,
}
2017-06-14 17:07:22 +03:00
}
/// Return type of the function
2017-06-26 11:54:17 +03:00
pub fn return_type(&self) -> Option<ValueType> {
match self {
&UserFunctionDescriptor::Static(_, _, result) => result,
&UserFunctionDescriptor::Heap(_, _, result) => result,
}
2017-06-14 17:07:22 +03:00
}
}
2017-07-31 11:58:24 +03:00
/// Set of user-defined module elements.
2017-11-25 22:55:45 +03:00
pub struct UserDefinedElements<'a> {
2017-07-31 11:58:24 +03:00
/// User globals list.
2017-11-25 22:55:45 +03:00
pub globals: HashMap<String, Arc<VariableInstance>>,
2017-07-31 11:58:24 +03:00
/// User functions list.
2017-06-26 11:54:17 +03:00
pub functions: Cow<'static, [UserFunctionDescriptor]>,
2017-05-19 09:36:50 +03:00
/// Functions executor.
2017-11-25 22:55:45 +03:00
pub executor: Option<&'a mut UserFunctionExecutor>,
2017-05-19 09:36:50 +03:00
}
2017-05-18 15:08:55 +03:00
/// Native module instance.
2017-11-25 22:55:45 +03:00
pub struct NativeModuleInstance<'a> {
2017-11-27 16:22:00 +03:00
/// Underlying module reference.
base: Arc<ModuleInstanceInterface>,
2017-05-19 09:36:50 +03:00
/// User function executor.
2017-11-25 22:55:45 +03:00
executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
2017-05-19 09:36:50 +03:00
/// By-name functions index.
2017-07-31 11:58:24 +03:00
functions_by_name: HashMap<String, u32>,
2017-05-19 09:36:50 +03:00
/// User functions list.
2017-06-26 11:54:17 +03:00
functions: Cow<'static, [UserFunctionDescriptor]>,
2017-07-31 11:58:24 +03:00
/// By-name functions index.
globals_by_name: HashMap<String, u32>,
/// User globals list.
2017-11-25 22:55:45 +03:00
globals: Vec<Arc<VariableInstance>>,
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
impl<'a> NativeModuleInstance<'a> {
2017-05-19 09:36:50 +03:00
/// Create new native module
2017-11-27 16:22:00 +03:00
pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
2017-07-31 11:58:24 +03:00
if !elements.functions.is_empty() && elements.executor.is_none() {
return Err(Error::Function("trying to construct native env module with functions, but without executor".into()));
}
2017-05-18 15:08:55 +03:00
Ok(NativeModuleInstance {
2017-11-27 16:22:00 +03:00
base: base,
2017-07-31 11:58:24 +03:00
executor: RwLock::new(elements.executor),
functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
functions: elements.functions,
globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
2017-05-18 15:08:55 +03:00
})
}
}
2017-11-25 22:55:45 +03:00
impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
2017-11-27 16:22:00 +03:00
self.base.execute_index(index, params)
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
2017-11-27 16:22:00 +03:00
self.base.execute_export(name, params)
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
2017-07-31 11:58:24 +03:00
if let Some(index) = self.functions_by_name.get(name) {
2017-06-21 09:23:20 +03:00
let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
match required_type {
2017-07-31 11:58:24 +03:00
&ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
&ExportEntryType::Function(ref required_type) => {
let actual_type = self.function_type(ItemIndex::Internal(composite_index))
.expect(
"by_name contains index; function_type succeeds for all functions from by_name; qed",
);
return if actual_type == *required_type {
Ok(Internal::Function(composite_index))
} else {
Err(Error::Validation(format!(
"Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
index,
required_type.params(),
required_type.return_type(),
actual_type.params(),
actual_type.return_type()
)))
};
}
2017-06-21 09:23:20 +03:00
_ => (),
}
2017-05-18 15:08:55 +03:00
}
2017-07-31 11:58:24 +03:00
if let Some(index) = self.globals_by_name.get(name) {
let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
2017-07-31 11:58:24 +03:00
match required_type {
&ExportEntryType::Any => {
return Ok(Internal::Global(composite_index))
}
&ExportEntryType::Global(ref required_type) => {
let actual_type = self.globals
.get(*index as usize)
.expect(
"globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
)
.variable_type();
return if actual_type == *required_type {
Ok(Internal::Global(composite_index))
} else {
Err(Error::Validation(format!(
"Export global type {} mismatch. Expected type {:?} when got {:?}",
index,
required_type,
actual_type
)))
};
}
2017-07-31 11:58:24 +03:00
_ => (),
}
}
2017-05-18 15:08:55 +03:00
2017-11-27 16:22:00 +03:00
self.base.export_entry(name, required_type)
2017-06-13 12:01:59 +03:00
}
2017-11-25 22:55:45 +03:00
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
2017-11-27 16:22:00 +03:00
self.base.table(index)
2017-06-19 12:04:16 +03:00
}
2017-11-25 22:55:45 +03:00
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
2017-11-27 16:22:00 +03:00
self.base.memory(index)
2017-06-19 12:04:16 +03:00
}
2017-11-25 22:55:45 +03:00
fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
2017-07-31 11:58:24 +03:00
let index = match global_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to get global, exported by native env module"),
};
if index < NATIVE_INDEX_GLOBAL_MIN {
2017-11-27 16:22:00 +03:00
return self.base.global(global_index, variable_type, externals);
2017-07-31 11:58:24 +03:00
}
self.globals
.get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
.cloned()
.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
2017-06-19 12:04:16 +03:00
}
2017-11-25 22:55:45 +03:00
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
2017-06-13 12:01:59 +03:00
let index = match function_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
};
2017-06-19 12:04:16 +03:00
2017-07-31 11:58:24 +03:00
if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
2017-11-27 16:22:00 +03:00
return self.base.function_type(function_index);
2017-06-13 12:01:59 +03:00
}
2017-06-26 11:54:17 +03:00
Ok(FunctionSignature::User(self.functions
2017-06-13 12:01:59 +03:00
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
2017-06-26 11:54:17 +03:00
.ok_or(Error::Native(format!("missing native env function with index {}", index)))?))
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
2017-06-19 12:35:17 +03:00
self.function_type(ItemIndex::Internal(type_index))
2017-06-19 11:01:59 +03:00
}
2017-11-25 22:55:45 +03:00
fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
2017-11-27 16:22:00 +03:00
self.base.function_reference(index, externals)
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
2017-11-27 16:22:00 +03:00
self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
2017-05-18 15:08:55 +03:00
}
2017-11-25 22:55:45 +03:00
fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
2017-06-19 11:01:59 +03:00
Ok(None)
2017-06-16 12:23:49 +03:00
}
2017-11-25 22:55:45 +03:00
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
2017-07-31 11:58:24 +03:00
if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
2017-11-27 16:22:00 +03:00
return self.base.call_internal_function(outer, index);
2017-05-18 15:08:55 +03:00
}
2017-06-19 12:04:16 +03:00
2017-05-19 09:36:50 +03:00
self.functions
2017-05-18 15:08:55 +03:00
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
.ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
2017-07-31 11:58:24 +03:00
.and_then(|f| self.executor.write()
.as_mut()
.expect("function existss; if function exists, executor must also exists [checked in constructor]; qed")
.execute(&f.name(), outer))
2017-05-18 15:08:55 +03:00
}
}
2017-11-27 16:22:00 +03:00
/// Create wrapper for a module with given native user functions.
pub fn native_module<'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
NativeModuleInstance::new(base, user_elements)
2017-05-18 15:08:55 +03:00
}
2017-06-26 11:54:17 +03:00
impl<'a> PartialEq for UserFunctionDescriptor {
fn eq(&self, other: &Self) -> bool {
self.params() == other.params()
&& self.return_type() == other.return_type()
}
}