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-05-18 15:08:55 +03:00
|
|
|
use elements::{FunctionType, Internal, ValueType};
|
|
|
|
use interpreter::Error;
|
|
|
|
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
|
2017-06-13 12:01:59 +03:00
|
|
|
CallerContext, ExportEntryType};
|
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-05-19 09:36:50 +03:00
|
|
|
/// User function closure type.
|
|
|
|
// pub type UserFunctionClosure<'a> = &'a mut FnMut(context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
|
2017-05-18 15:08:55 +03:00
|
|
|
|
2017-05-19 09:36:50 +03:00
|
|
|
/// User functions executor.
|
|
|
|
pub trait UserFunctionExecutor {
|
|
|
|
/// Execute function with given name.
|
|
|
|
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
2017-06-14 17:07:22 +03:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub enum UserFunctionDescriptor {
|
|
|
|
Static(&'static str, &'static [ValueType]),
|
|
|
|
Heap(String, Vec<ValueType>),
|
|
|
|
}
|
|
|
|
|
2017-05-19 09:36:50 +03:00
|
|
|
/// User function type.
|
2017-06-14 17:07:22 +03:00
|
|
|
#[derive(Clone)]
|
2017-05-18 15:08:55 +03:00
|
|
|
pub struct UserFunction {
|
2017-06-14 17:07:22 +03:00
|
|
|
pub desc: UserFunctionDescriptor,
|
2017-05-18 15:08:55 +03:00
|
|
|
pub result: Option<ValueType>,
|
|
|
|
}
|
|
|
|
|
2017-06-14 17:07:22 +03:00
|
|
|
impl UserFunction {
|
|
|
|
/// New function with statically known params
|
|
|
|
pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
|
|
|
|
UserFunction {
|
|
|
|
desc: UserFunctionDescriptor::Static(name, params),
|
|
|
|
result: result,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// New function with statically unknown params
|
|
|
|
pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
|
|
|
|
UserFunction {
|
|
|
|
desc: UserFunctionDescriptor::Heap(name, params),
|
|
|
|
result: result,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Name of the function
|
|
|
|
pub fn name(&self) -> &str {
|
|
|
|
match self.desc {
|
|
|
|
UserFunctionDescriptor::Static(name, _) => name,
|
|
|
|
UserFunctionDescriptor::Heap(ref name, _) => name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Arguments of the function
|
|
|
|
pub fn params(&self) -> &[ValueType] {
|
|
|
|
match self.desc {
|
|
|
|
UserFunctionDescriptor::Static(_, params) => params,
|
|
|
|
UserFunctionDescriptor::Heap(_, ref params) => params,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return type of the function
|
|
|
|
pub fn result(&self) -> Option<ValueType> {
|
|
|
|
self.result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-19 09:36:50 +03:00
|
|
|
/// Set of user-defined functions
|
|
|
|
pub struct UserFunctions<'a> {
|
|
|
|
/// Functions list.
|
2017-06-14 17:07:22 +03:00
|
|
|
pub functions: Cow<'static, [UserFunction]>,
|
2017-05-19 09:36:50 +03:00
|
|
|
/// Functions executor.
|
|
|
|
pub executor: &'a mut UserFunctionExecutor,
|
|
|
|
}
|
2017-05-18 15:08:55 +03:00
|
|
|
|
|
|
|
/// Native module instance.
|
2017-05-19 09:36:50 +03:00
|
|
|
pub struct NativeModuleInstance<'a> {
|
|
|
|
/// Underllying module reference.
|
2017-05-18 15:08:55 +03:00
|
|
|
env: Arc<ModuleInstanceInterface>,
|
2017-05-19 09:36:50 +03:00
|
|
|
/// User function executor.
|
|
|
|
executor: RwLock<&'a mut UserFunctionExecutor>,
|
|
|
|
/// By-name functions index.
|
|
|
|
by_name: HashMap<String, u32>,
|
|
|
|
/// User functions list.
|
2017-06-14 17:07:22 +03:00
|
|
|
functions: Cow<'static, [UserFunction]>,
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
2017-05-19 09:36:50 +03:00
|
|
|
impl<'a> NativeModuleInstance<'a> {
|
|
|
|
/// Create new native module
|
|
|
|
pub fn new(env: Arc<ModuleInstanceInterface>, functions: UserFunctions<'a>) -> Result<Self, Error> {
|
2017-05-18 15:08:55 +03:00
|
|
|
Ok(NativeModuleInstance {
|
|
|
|
env: env,
|
2017-05-19 09:36:50 +03:00
|
|
|
executor: RwLock::new(functions.executor),
|
2017-06-14 17:07:22 +03:00
|
|
|
by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
|
2017-05-19 09:36:50 +03:00
|
|
|
functions: functions.functions,
|
2017-05-18 15:08:55 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-19 09:36:50 +03:00
|
|
|
impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
|
2017-06-13 12:01:59 +03:00
|
|
|
fn instantiate<'b>(&self, is_user_module: bool, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<(), Error> {
|
|
|
|
self.env.instantiate(is_user_module, externals)
|
|
|
|
}
|
|
|
|
|
2017-05-18 15:08:55 +03:00
|
|
|
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
self.env.execute_index(index, params)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
self.env.execute_export(name, params)
|
|
|
|
}
|
|
|
|
|
2017-06-13 12:01:59 +03:00
|
|
|
fn export_entry<'b>(&self, name: &str, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>, required_type: &ExportEntryType) -> Result<Internal, Error> {
|
2017-05-19 09:36:50 +03:00
|
|
|
if let Some(index) = self.by_name.get(name) {
|
|
|
|
return Ok(Internal::Function(NATIVE_INDEX_FUNC_MIN + *index));
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
2017-06-13 12:01:59 +03:00
|
|
|
self.env.export_entry(name, externals, required_type)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn function_type<'b>(&self, function_index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<FunctionType, Error> {
|
|
|
|
let index = match function_index {
|
|
|
|
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
|
|
|
|
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
|
|
|
|
};
|
|
|
|
|
|
|
|
if index < NATIVE_INDEX_FUNC_MIN {
|
|
|
|
return self.env.function_type(function_index, externals);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.functions
|
|
|
|
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
|
|
|
|
.ok_or(Error::Native(format!("missing native env function with index {}", index)))
|
2017-06-14 17:07:22 +03:00
|
|
|
.map(|f| FunctionType::new(f.params().to_vec(), f.result().clone()))
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
|
|
|
|
self.env.table(index)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
|
|
|
|
self.env.memory(index)
|
|
|
|
}
|
|
|
|
|
2017-06-13 12:01:59 +03:00
|
|
|
fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error> {
|
|
|
|
self.env.global(index, variable_type)
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
2017-06-13 12:01:59 +03:00
|
|
|
fn call_function(&self, outer: CallerContext, index: ItemIndex, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
self.env.call_function(outer, index, function_type)
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn call_function_indirect(&self, outer: CallerContext, table_index: ItemIndex, type_index: u32, func_index: u32) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
self.env.call_function_indirect(outer, table_index, type_index, func_index)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn call_internal_function(&self, outer: CallerContext, index: u32, function_type: Option<&FunctionType>) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
if index < NATIVE_INDEX_FUNC_MIN {
|
|
|
|
return self.env.call_internal_function(outer, index, function_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: check type
|
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)))
|
2017-06-14 17:07:22 +03:00
|
|
|
.and_then(|f| self.executor.write().execute(&f.name(), outer))
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create wrapper for env module with given native user functions.
|
|
|
|
pub fn env_native_module(env: Arc<ModuleInstanceInterface>, user_functions: UserFunctions) -> Result<NativeModuleInstance, Error> {
|
2017-05-19 09:36:50 +03:00
|
|
|
NativeModuleInstance::new(env, user_functions)
|
2017-05-18 15:08:55 +03:00
|
|
|
}
|