diff --git a/src/interpreter/func.rs b/src/interpreter/func.rs index 1948548..cc9af0c 100644 --- a/src/interpreter/func.rs +++ b/src/interpreter/func.rs @@ -5,25 +5,25 @@ use std::any::Any; use elements::{FunctionType, Opcodes, Local}; use interpreter::{Error, ModuleInstance}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; -use interpreter::host::AnyFunc; +use interpreter::host::HostFunc; use interpreter::value::RuntimeValue; use common::stack::StackWithLimit; use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT}; #[derive(Clone)] -pub enum FuncInstance { +pub enum FuncInstance { Internal { func_type: Rc, - module: Rc, + module: Rc>, body: Rc, }, Host { func_type: Rc, - host_func: Rc, + host_func: Rc>, }, } -impl fmt::Debug for FuncInstance { +impl fmt::Debug for FuncInstance { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &FuncInstance::Internal { @@ -43,9 +43,9 @@ impl fmt::Debug for FuncInstance { } } -impl FuncInstance { +impl FuncInstance { pub fn alloc_internal( - module: Rc, + module: Rc>, func_type: Rc, body: FuncBody, ) -> Rc { @@ -59,7 +59,7 @@ impl FuncInstance { pub fn alloc_host( func_type: Rc, - host_func: Rc, + host_func: Rc>, ) -> Rc { let func = FuncInstance::Host { func_type, @@ -82,14 +82,14 @@ impl FuncInstance { } } - pub fn invoke( - func: Rc, + pub fn invoke( + func: Rc>, args: Vec, state: &mut St, ) -> Result, Error> { - enum InvokeKind { - Internal(FunctionContext), - Host(Rc, Vec), + enum InvokeKind { + Internal(FunctionContext), + Host(Rc>, Vec), } let result = match *func { @@ -115,7 +115,7 @@ impl FuncInstance { let mut interpreter = Interpreter::new(state); interpreter.run_function(ctx) } - InvokeKind::Host(host_func, args) => host_func.call_as_any(state as &mut Any, &args), + InvokeKind::Host(host_func, args) => host_func(state, &args), } } } diff --git a/src/interpreter/host.rs b/src/interpreter/host.rs index 4eb0dd6..51d8f14 100644 --- a/src/interpreter/host.rs +++ b/src/interpreter/host.rs @@ -1,6 +1,4 @@ -use std::any::Any; use std::rc::Rc; -use std::marker::PhantomData; use std::collections::HashMap; use std::collections::hash_map::Entry; use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType}; @@ -13,71 +11,59 @@ use interpreter::value::RuntimeValue; use interpreter::Error; use interpreter::ImportResolver; +pub type HostFunc = Fn(&mut St, &[RuntimeValue]) -> Result, Error>; + pub struct HostModuleBuilder { - exports: HashMap, - _marker: PhantomData, + exports: HashMap>, } -impl HostModuleBuilder { +impl HostModuleBuilder { pub fn new() -> Self { HostModuleBuilder { exports: HashMap::new(), - _marker: PhantomData, } } - pub fn insert_func0< - Cl: Fn(&mut St) -> Result, Error> + 'static, - Ret: AsReturnVal + 'static, - F: Into>, - N: Into, - >( - &mut self, - name: N, - f: F, - ) { - let func_type = Func0::::derive_func_type(); - let host_func = Rc::new(f.into()) as Rc; - let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); - self.insert_func(name, func); - } - - pub fn with_func1< - Cl: Fn(&mut St, P1) -> Result, Error> + 'static, - Ret: AsReturnVal + 'static, - P1: FromArg + 'static, - F: Into>, - N: Into, - >( - &mut self, - name: N, - f: F, - ) { - let func_type = Func1::::derive_func_type(); - let host_func = Rc::new(f.into()) as Rc; - let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); - self.insert_func(name, func); - } + // pub fn insert_func0< + // Cl: Fn(&mut St) -> Result, Error> + AnyFunc + 'static, + // Ret: AsReturnVal + 'static, + // F: Into, + // N: Into, + // >( + // &mut self, + // name: N, + // f: Box, + // ) { + // let func_type = FunctionType::new(vec![], Ret::value_type()); + // let host_func = Rc::new(f) as Rc>; + // let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); + // self.insert_func(name, func); + // } pub fn with_func2< Cl: Fn(&mut St, P1, P2) -> Result, Error> + 'static, Ret: AsReturnVal + 'static, P1: FromArg + 'static, P2: FromArg + 'static, - F: Into>, N: Into, >( &mut self, name: N, - f: F, + f: Cl, ) { - let func_type = Func2::::derive_func_type(); - let host_func = Rc::new(f.into()) as Rc; + let func_type = FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type()); + let host_func = Rc::new(move |state: &mut St, args: &[RuntimeValue]| -> Result, Error> { + let p1 = P1::from_arg(&args[0]); + let p2 = P2::from_arg(&args[1]); + let result = f(state, p1, p2); + result.map(|r| r.and_then(|r| r.as_return_val())) + }); + let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); self.insert_func(name, func); } - pub fn insert_func>(&mut self, name: N, func: Rc) { + pub fn insert_func>(&mut self, name: N, func: Rc>) { self.insert(name, ExternVal::Func(func)); } @@ -89,7 +75,7 @@ impl HostModuleBuilder { self.insert(name, ExternVal::Memory(memory)); } - pub fn insert_table>(&mut self, name: N, table: Rc) { + pub fn insert_table>(&mut self, name: N, table: Rc>) { self.insert(name, ExternVal::Table(table)); } @@ -103,19 +89,19 @@ impl HostModuleBuilder { self } - pub fn with_table>(mut self, name: N, table: Rc) -> Self { + pub fn with_table>(mut self, name: N, table: Rc>) -> Self { self.insert_table(name, table); self } - fn insert>(&mut self, name: N, extern_val: ExternVal) { + fn insert>(&mut self, name: N, extern_val: ExternVal) { match self.exports.entry(name.into()) { Entry::Vacant(v) => v.insert(extern_val), Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()), }; } - pub fn build(self) -> HostModule { + pub fn build(self) -> HostModule { let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports)); HostModule { internal_instance @@ -123,22 +109,22 @@ impl HostModuleBuilder { } } -pub struct HostModule { - internal_instance: Rc, +pub struct HostModule { + internal_instance: Rc>, } -impl HostModule { - pub fn export_by_name(&self, name: &str) -> Option { +impl HostModule { + pub fn export_by_name(&self, name: &str) -> Option> { self.internal_instance.export_by_name(name) } } -impl ImportResolver for HostModule { +impl ImportResolver for HostModule { fn resolve_func( &self, field_name: &str, func_type: &FunctionType, - ) -> Result, Error> { + ) -> Result>, Error> { self.internal_instance.resolve_func(field_name, func_type) } @@ -162,15 +148,15 @@ impl ImportResolver for HostModule { &self, field_name: &str, table_type: &TableType, - ) -> Result, Error> { + ) -> Result>, Error> { self.internal_instance.resolve_table(field_name, table_type) } } -pub trait AnyFunc { +pub trait AnyFunc { fn call_as_any( &self, - state: &mut Any, + state: &mut St, args: &[RuntimeValue], ) -> Result, Error>; } @@ -218,134 +204,26 @@ impl AsReturnVal for () { } } -pub struct Func0 Result, Error>, St, Ret: AsReturnVal> { - closure: Cl, - _marker: PhantomData<(St, Ret)>, -} - -impl< - St: 'static, - Ret: AsReturnVal, - Cl: Fn(&mut St) -> Result, Error>, -> AnyFunc for Func0 { +impl AnyFunc for Fn(&mut St) -> Result, Error> { fn call_as_any( &self, - state: &mut Any, + state: &mut St, _args: &[RuntimeValue], ) -> Result, Error> { - let state = state.downcast_mut::().unwrap(); - let result = (self.closure)(state); + let result = self(state); result.map(|r| r.and_then(|r| r.as_return_val())) } } -impl Result, Error>> From - for Func0 { - fn from(cl: Cl) -> Self { - Func0 { - closure: cl, - _marker: PhantomData, - } - } -} - -impl< - St: 'static, - Ret: AsReturnVal, - Cl: Fn(&mut St) -> Result, Error>, -> Func0 { - fn derive_func_type() -> FunctionType { - FunctionType::new(vec![], Ret::value_type()) - } -} - -pub struct Func1 Result, Error>, St, Ret: AsReturnVal, P1: FromArg> { - closure: Cl, - _marker: PhantomData<(St, Ret, P1)>, -} - -impl< - St: 'static, - Ret: AsReturnVal, - P1: FromArg, - Cl: Fn(&mut St, P1) -> Result, Error>, -> AnyFunc for Func1 { +impl AnyFunc for Fn(&mut St, P1, P2) -> Result, Error> { fn call_as_any( &self, - state: &mut Any, + state: &mut St, args: &[RuntimeValue], ) -> Result, Error> { - let state = state.downcast_mut::().unwrap(); - let p1 = P1::from_arg(&args[0]); - let result = (self.closure)(state, p1); - result.map(|r| r.and_then(|r| r.as_return_val())) - } -} - -impl Result, Error>> From - for Func1 { - fn from(cl: Cl) -> Self { - Func1 { - closure: cl, - _marker: PhantomData, - } - } -} - -impl< - St: 'static, - Ret: AsReturnVal, - P1: FromArg, - Cl: Fn(&mut St, P1) -> Result, Error>, -> Func1 { - fn derive_func_type() -> FunctionType { - FunctionType::new(vec![P1::value_type()], Ret::value_type()) - } -} - -pub struct Func2 Result, Error>, St, Ret: AsReturnVal, P1: FromArg, P2: FromArg> { - closure: Cl, - _marker: PhantomData<(St, Ret, P1, P2)>, -} - -impl< - St: 'static, - Ret: AsReturnVal, - P1: FromArg, - P2: FromArg, - Cl: Fn(&mut St, P1, P2) -> Result, Error>, -> AnyFunc for Func2 { - fn call_as_any( - &self, - state: &mut Any, - args: &[RuntimeValue], - ) -> Result, Error> { - let state = state.downcast_mut::().unwrap(); let p1 = P1::from_arg(&args[0]); let p2 = P2::from_arg(&args[1]); - let result = (self.closure)(state, p1, p2); + let result = self(state, p1, p2); result.map(|r| r.and_then(|r| r.as_return_val())) } } - -impl Result, Error>> From - for Func2 { - fn from(cl: Cl) -> Self { - Func2 { - closure: cl, - _marker: PhantomData, - } - } -} - -impl< - St: 'static, - Ret: AsReturnVal, - P1: FromArg, - P2: FromArg, - Cl: Fn(&mut St, P1, P2) -> Result, Error>, -> Func2 { - fn derive_func_type() -> FunctionType { - FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type()) - } -} diff --git a/src/interpreter/imports.rs b/src/interpreter/imports.rs index 9450184..da9ee09 100644 --- a/src/interpreter/imports.rs +++ b/src/interpreter/imports.rs @@ -7,38 +7,43 @@ use interpreter::memory::MemoryInstance; use interpreter::table::TableInstance; use interpreter::Error; -#[derive(Default)] -pub struct Imports<'a> { - modules: HashMap, +pub struct Imports<'a, St: 'a> { + modules: HashMap>, } -impl<'a> Imports<'a> { - pub fn new() -> Imports<'a> { +impl<'a, St: 'a> Default for Imports<'a, St> { + fn default() -> Self { + Self::new() + } +} + +impl<'a, St: 'a> Imports<'a, St> { + pub fn new() -> Imports<'a, St> { Imports { modules: HashMap::new(), } } - pub fn with_resolver>(mut self, name: N, resolver: &'a ImportResolver) -> Imports<'a> { + pub fn with_resolver>(mut self, name: N, resolver: &'a ImportResolver) -> Self { self.modules.insert(name.into(), resolver); self } - pub fn push_resolver>(&mut self, name: N, resolver: &'a ImportResolver) { + pub fn push_resolver>(&mut self, name: N, resolver: &'a ImportResolver) { self.modules.insert(name.into(), resolver); } - pub fn resolver(&self, name: &str) -> Option<&ImportResolver> { + pub fn resolver(&self, name: &str) -> Option<&ImportResolver> { self.modules.get(name).cloned() } } -pub trait ImportResolver { +pub trait ImportResolver { fn resolve_func( &self, field_name: &str, func_type: &FunctionType, - ) -> Result, Error>; + ) -> Result>, Error>; fn resolve_global( &self, @@ -56,5 +61,5 @@ pub trait ImportResolver { &self, field_name: &str, table_type: &TableType, - ) -> Result, Error>; + ) -> Result>, Error>; } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 1ff6ba3..8980add 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -149,7 +149,7 @@ pub use self::memory::MemoryInstance; pub use self::table::TableInstance; pub use self::program::ProgramInstance; pub use self::value::RuntimeValue; -pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg}; +pub use self::host::{HostModule, HostModuleBuilder, AnyFunc, AsReturnVal, FromArg}; pub use self::imports::{ImportResolver, Imports}; pub use self::module::ModuleInstance; pub use self::global::GlobalInstance; diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index 1038318..f0ef839 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -1,5 +1,6 @@ use std::rc::Rc; use std::cell::RefCell; +use std::fmt; use std::collections::HashMap; use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module, Opcode, ResizableLimits, TableType, Type}; @@ -10,23 +11,44 @@ use interpreter::func::{FuncInstance, FuncBody}; use validation::validate_module; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; -#[derive(Clone, Debug)] -pub enum ExternVal { - Func(Rc), - Table(Rc), +pub enum ExternVal { + Func(Rc>), + Table(Rc>), Memory(Rc), Global(Rc), } -impl ExternVal { - pub fn as_func(&self) -> Option> { +impl Clone for ExternVal { + fn clone(&self) -> Self { + match *self { + ExternVal::Func(ref func) => ExternVal::Func(Rc::clone(func)), + ExternVal::Table(ref table) => ExternVal::Table(Rc::clone(table)), + ExternVal::Memory(ref memory) => ExternVal::Memory(Rc::clone(memory)), + ExternVal::Global(ref global) => ExternVal::Global(Rc::clone(global)), + } + } +} + +impl fmt::Debug for ExternVal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ExternVal {{ {} }}", match *self { + ExternVal::Func(_) => "Func", + ExternVal::Table(_) => "Table", + ExternVal::Memory(_) => "Memory", + ExternVal::Global(_) => "Global", + }) + } +} + +impl ExternVal { + pub fn as_func(&self) -> Option>> { match *self { ExternVal::Func(ref func) => Some(Rc::clone(func)), _ => None, } } - pub fn as_table(&self) -> Option> { + pub fn as_table(&self) -> Option>> { match *self { ExternVal::Table(ref table) => Some(Rc::clone(table)), _ => None, @@ -49,32 +71,38 @@ impl ExternVal { } #[derive(Default, Debug)] -pub struct ModuleInstance { +pub struct ModuleInstance { types: RefCell>>, - tables: RefCell>>, - funcs: RefCell>>, + tables: RefCell>>>, + funcs: RefCell>>>, memories: RefCell>>, globals: RefCell>>, - exports: RefCell>, + exports: RefCell>>, } -impl ModuleInstance { - fn new() -> ModuleInstance { - ModuleInstance::default() +impl ModuleInstance { + fn new() -> ModuleInstance { + ModuleInstance { + types: RefCell::new(Vec::new()), + tables: RefCell::new(Vec::new()), + funcs: RefCell::new(Vec::new()), + memories: RefCell::new(Vec::new()), + globals: RefCell::new(Vec::new()), + exports: RefCell::new(HashMap::new()), + } } - pub fn with_exports(exports: HashMap) -> ModuleInstance { - ModuleInstance { - exports: RefCell::new(exports), - ..Default::default() - } + pub fn with_exports(exports: HashMap>) -> ModuleInstance { + let mut instance = Self::new(); + instance.exports = RefCell::new(exports); + instance } pub fn memory_by_index(&self, idx: u32) -> Option> { self.memories.borrow().get(idx as usize).cloned() } - pub fn table_by_index(&self, idx: u32) -> Option> { + pub fn table_by_index(&self, idx: u32) -> Option>> { self.tables.borrow().get(idx as usize).cloned() } @@ -82,7 +110,7 @@ impl ModuleInstance { self.globals.borrow().get(idx as usize).cloned() } - pub fn func_by_index(&self, idx: u32) -> Option> { + pub fn func_by_index(&self, idx: u32) -> Option>> { self.funcs.borrow().get(idx as usize).cloned() } @@ -90,11 +118,11 @@ impl ModuleInstance { self.types.borrow().get(idx as usize).cloned() } - pub fn export_by_name(&self, name: &str) -> Option { + pub fn export_by_name(&self, name: &str) -> Option> { self.exports.borrow().get(name).cloned() } - fn push_func(&self, func: Rc) { + fn push_func(&self, func: Rc>) { self.funcs.borrow_mut().push(func); } @@ -106,7 +134,7 @@ impl ModuleInstance { self.memories.borrow_mut().push(memory) } - fn push_table(&self, table: Rc) { + fn push_table(&self, table: Rc>) { self.tables.borrow_mut().push(table) } @@ -114,14 +142,14 @@ impl ModuleInstance { self.globals.borrow_mut().push(global) } - fn insert_export>(&self, name: N, extern_val: ExternVal) { + fn insert_export>(&self, name: N, extern_val: ExternVal) { self.exports.borrow_mut().insert(name.into(), extern_val); } fn alloc_module( module: &Module, - extern_vals: &[ExternVal], - instance: &Rc, + extern_vals: &[ExternVal], + instance: &Rc>, ) -> Result<(), Error> { let mut aux_data = validate_module(module)?; @@ -246,7 +274,7 @@ impl ModuleInstance { .unwrap_or(&[]) { let field = export.field(); - let extern_val: ExternVal = match *export.internal() { + let extern_val: ExternVal = match *export.internal() { Internal::Function(idx) => { let func = instance .func_by_index(idx) @@ -280,8 +308,8 @@ impl ModuleInstance { fn instantiate_with_externvals( module: &Module, - extern_vals: &[ExternVal], - ) -> Result, Error> { + extern_vals: &[ExternVal], + ) -> Result>, Error> { let instance = Rc::new(ModuleInstance::new()); ModuleInstance::alloc_module(module, extern_vals, &instance)?; @@ -325,8 +353,8 @@ impl ModuleInstance { fn instantiate_with_imports( module: &Module, - imports: &Imports, - ) -> Result, Error> { + imports: &Imports, + ) -> Result>, Error> { let mut extern_vals = Vec::new(); for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) { let module_name = import_entry.module(); @@ -365,11 +393,11 @@ impl ModuleInstance { Self::instantiate_with_externvals(module, &extern_vals) } - pub fn instantiate<'a>(module: &'a Module) -> InstantiationWizard<'a> { + pub fn instantiate<'a>(module: &'a Module) -> InstantiationWizard<'a, St> { InstantiationWizard::new(module) } - pub fn invoke_index( + pub fn invoke_index( &self, func_idx: u32, args: Vec, @@ -384,7 +412,7 @@ impl ModuleInstance { FuncInstance::invoke(func_instance, args, state) } - pub fn invoke_export( + pub fn invoke_export( &self, func_name: &str, args: Vec, @@ -409,12 +437,12 @@ impl ModuleInstance { } } -pub struct InstantiationWizard<'a> { +pub struct InstantiationWizard<'a, St: 'a> { module: &'a Module, - imports: Option>, + imports: Option>, } -impl<'a> InstantiationWizard<'a> { +impl<'a, St: 'a> InstantiationWizard<'a, St> { fn new(module: &'a Module) -> Self { InstantiationWizard { module, @@ -422,7 +450,7 @@ impl<'a> InstantiationWizard<'a> { } } - pub fn with_imports(mut self, imports: Imports<'a>) -> Self { + pub fn with_imports(mut self, imports: Imports<'a, St>) -> Self { self.imports = Some(imports); self } @@ -430,7 +458,7 @@ impl<'a> InstantiationWizard<'a> { pub fn with_import>( mut self, name: N, - import_resolver: &'a ImportResolver, + import_resolver: &'a ImportResolver, ) -> Self { self.imports .get_or_insert_with(|| Imports::default()) @@ -438,7 +466,7 @@ impl<'a> InstantiationWizard<'a> { self } - pub fn run_start(mut self, state: &mut St) -> Result, Error> { + pub fn run_start(mut self, state: &mut St) -> Result>, Error> { let imports = self.imports.get_or_insert_with(|| Imports::default()); let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?; @@ -451,7 +479,7 @@ impl<'a> InstantiationWizard<'a> { Ok(instance) } - pub fn assert_no_start(mut self) -> Result, Error> { + pub fn assert_no_start(mut self) -> Result>, Error> { assert!(self.module.start_section().is_none()); let imports = self.imports.get_or_insert_with(|| Imports::default()); let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?; @@ -459,12 +487,12 @@ impl<'a> InstantiationWizard<'a> { } } -impl ImportResolver for ModuleInstance { +impl ImportResolver for ModuleInstance { fn resolve_func( &self, field_name: &str, _func_type: &FunctionType, - ) -> Result, Error> { + ) -> Result>, Error> { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -509,7 +537,7 @@ impl ImportResolver for ModuleInstance { &self, field_name: &str, _table_type: &TableType, - ) -> Result, Error> { + ) -> Result>, Error> { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -525,7 +553,7 @@ fn alloc_func_type(func_type: FunctionType) -> Rc { Rc::new(func_type) } -fn alloc_table(table_type: &TableType) -> Result, Error> { +fn alloc_table(table_type: &TableType) -> Result>, Error> { let table = TableInstance::new(table_type)?; Ok(Rc::new(table)) } @@ -540,7 +568,7 @@ fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> Rc RuntimeValue { +fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue { let code = init_expr.code(); debug_assert!( code.len() == 2, diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index dcc61fc..9829a37 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -9,14 +9,14 @@ use interpreter::value::RuntimeValue; use interpreter::imports::{Imports, ImportResolver}; /// Program instance. Program is a set of instantiated modules. -pub struct ProgramInstance { - modules: HashMap>, - resolvers: HashMap>, +pub struct ProgramInstance { + modules: HashMap>>, + resolvers: HashMap>>, } -impl ProgramInstance { +impl ProgramInstance { /// Create new program instance. - pub fn new() -> Self { + pub fn new() -> ProgramInstance { ProgramInstance { modules: HashMap::new(), resolvers: HashMap::new(), @@ -24,12 +24,12 @@ impl ProgramInstance { } /// Instantiate module with validation. - pub fn add_module<'a, St: 'static>( + pub fn add_module( &mut self, name: &str, module: Module, state: &mut St, - ) -> Result, Error> { + ) -> Result>, Error> { let module_instance = { let mut imports = Imports::new(); for (module_name, module_instance) in self.modules.iter() { @@ -50,7 +50,7 @@ impl ProgramInstance { pub fn add_import_resolver( &mut self, name: &str, - import_resolver: Box, + import_resolver: Box>, ) { self.resolvers.insert(name.to_owned(), import_resolver); } @@ -58,16 +58,16 @@ impl ProgramInstance { pub fn add_host_module( &mut self, name: &str, - host_module: HostModule, - ) { - self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box); + host_module: HostModule, + ) where St: 'static { + self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box>); } - pub fn insert_loaded_module(&mut self, name: &str, module: Rc) { + pub fn insert_loaded_module(&mut self, name: &str, module: Rc>) { self.modules.insert(name.to_owned(), module); } - pub fn invoke_export( + pub fn invoke_export( &mut self, module_name: &str, func_name: &str, @@ -80,7 +80,7 @@ impl ProgramInstance { module_instance.invoke_export(func_name, args, state) } - pub fn invoke_index( + pub fn invoke_index( &mut self, module_name: &str, func_idx: u32, @@ -93,16 +93,19 @@ impl ProgramInstance { module_instance.invoke_index(func_idx, args, state) } - pub fn invoke_func( + pub fn invoke_func( &mut self, - func_instance: Rc, + func_instance: Rc>, args: Vec, state: &mut St, ) -> Result, Error> { FuncInstance::invoke(Rc::clone(&func_instance), args, state) } - pub fn module(&self, name: &str) -> Option> { - self.modules.get(name).cloned() + pub fn module(&self, name: &str) -> Option<&ImportResolver> { + self.modules + .get(name) + .map(|x| &**x as &ImportResolver) + .or_else(|| self.resolvers.get(name).map(|x| &**x)) } } diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index a7572c4..9ee7fa9 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -17,17 +17,17 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameTy use common::stack::StackWithLimit; /// Function interpreter. -pub struct Interpreter<'a, St: 'static> { +pub struct Interpreter<'a, St: 'a> { state: &'a mut St, } /// Function execution context. -pub struct FunctionContext { +pub struct FunctionContext { /// Is context initialized. pub is_initialized: bool, /// Internal function reference. - pub function: Rc, - pub module: Rc, + pub function: Rc>, + pub module: Rc>, /// Function return type. pub return_type: BlockType, /// Local variables. @@ -42,13 +42,13 @@ pub struct FunctionContext { /// Interpreter action to execute after executing instruction. #[derive(Debug)] -pub enum InstructionOutcome { +pub enum InstructionOutcome { /// Continue with next instruction. RunNextInstruction, /// Branch to given frame. Branch(usize), /// Execute function call. - ExecuteCall(Rc), + ExecuteCall(Rc>), /// End current frame. End, /// Return from current function block. @@ -56,21 +56,21 @@ pub enum InstructionOutcome { } /// Function run result. -enum RunResult { +enum RunResult { /// Function has returned (optional) value. Return(Option), /// Function is calling other function. - NestedCall(Rc), + NestedCall(Rc>), } -impl<'a, St: 'static> Interpreter<'a, St> { +impl<'a, St: 'a> Interpreter<'a, St> { pub fn new(state: &'a mut St) -> Interpreter<'a, St> { Interpreter { state } } - pub fn run_function(&mut self, function_context: FunctionContext) -> Result, Error> { + pub fn run_function(&mut self, function_context: FunctionContext) -> Result, Error> { let mut function_stack = VecDeque::new(); function_stack.push_back(function_context); @@ -117,7 +117,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { } } - fn do_run_function(&mut self, function_context: &mut FunctionContext, function_body: &[Opcode], function_labels: &HashMap) -> Result { + fn do_run_function(&mut self, function_context: &mut FunctionContext, function_body: &[Opcode], function_labels: &HashMap) -> Result, Error> { loop { let instruction = &function_body[function_context.position]; @@ -155,7 +155,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { })) } - fn run_instruction(&mut self, context: &mut FunctionContext, labels: &HashMap, opcode: &Opcode) -> Result { + fn run_instruction(&mut self, context: &mut FunctionContext, labels: &HashMap, opcode: &Opcode) -> Result, Error> { match opcode { &Opcode::Unreachable => self.run_unreachable(context), &Opcode::Nop => self.run_nop(context), @@ -349,25 +349,25 @@ impl<'a, St: 'static> Interpreter<'a, St> { } } - fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result { + fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result, Error> { Err(Error::Trap("programmatic".into())) } - fn run_nop(&mut self, _context: &mut FunctionContext) -> Result { + fn run_nop(&mut self, _context: &mut FunctionContext) -> Result, Error> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_block(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result { + fn run_block(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result, Error> { context.push_frame(labels, BlockFrameType::Block, block_type)?; Ok(InstructionOutcome::RunNextInstruction) } - fn run_loop(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result { + fn run_loop(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result, Error> { context.push_frame(labels, BlockFrameType::Loop, block_type)?; Ok(InstructionOutcome::RunNextInstruction) } - fn run_if(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result { + fn run_if(&mut self, context: &mut FunctionContext, labels: &HashMap, block_type: BlockType) -> Result, Error> { let branch = context.value_stack_mut().pop_as()?; let block_frame_type = if branch { BlockFrameType::IfTrue } else { let else_pos = labels[&context.position]; @@ -382,23 +382,23 @@ impl<'a, St: 'static> Interpreter<'a, St> { context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction) } - fn run_else(&mut self, context: &mut FunctionContext, labels: &HashMap) -> Result { + fn run_else(&mut self, context: &mut FunctionContext, labels: &HashMap) -> Result, Error> { let end_pos = labels[&context.position]; context.pop_frame(false)?; context.position = end_pos; Ok(InstructionOutcome::RunNextInstruction) } - fn run_end(&mut self, context: &mut FunctionContext) -> Result { + fn run_end(&mut self, context: &mut FunctionContext) -> Result, Error> { context.pop_frame(false)?; Ok(InstructionOutcome::End) } - fn run_br(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result { + fn run_br(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result, Error> { Ok(InstructionOutcome::Branch(label_idx as usize)) } - fn run_br_if(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result { + fn run_br_if(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result, Error> { if context.value_stack_mut().pop_as()? { Ok(InstructionOutcome::Branch(label_idx as usize)) } else { @@ -406,20 +406,20 @@ impl<'a, St: 'static> Interpreter<'a, St> { } } - fn run_br_table(&mut self, context: &mut FunctionContext, table: &Vec, default: u32) -> Result { + fn run_br_table(&mut self, context: &mut FunctionContext, table: &Vec, default: u32) -> Result, Error> { let index: u32 = context.value_stack_mut().pop_as()?; Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize)) } - fn run_return(&mut self, _context: &mut FunctionContext) -> Result { + fn run_return(&mut self, _context: &mut FunctionContext) -> Result, Error> { Ok(InstructionOutcome::Return) } fn run_call( &mut self, - context: &mut FunctionContext, + context: &mut FunctionContext, func_idx: u32, - ) -> Result { + ) -> Result, Error> { let func = context .module() .func_by_index(func_idx) @@ -429,9 +429,9 @@ impl<'a, St: 'static> Interpreter<'a, St> { fn run_call_indirect( &mut self, - context: &mut FunctionContext, + context: &mut FunctionContext, type_idx: u32, - ) -> Result { + ) -> Result, Error> { let table_func_idx: u32 = context.value_stack_mut().pop_as()?; let table = context .module() @@ -458,7 +458,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::ExecuteCall(func_ref)) } - fn run_drop(&mut self, context: &mut FunctionContext) -> Result { + fn run_drop(&mut self, context: &mut FunctionContext) -> Result, Error> { context .value_stack_mut() .pop() @@ -466,7 +466,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_select(&mut self, context: &mut FunctionContext) -> Result { + fn run_select(&mut self, context: &mut FunctionContext) -> Result, Error> { context .value_stack_mut() .pop_triple() @@ -482,19 +482,19 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_get_local(&mut self, context: &mut FunctionContext, index: u32) -> Result { + fn run_get_local(&mut self, context: &mut FunctionContext, index: u32) -> Result, Error> { context.get_local(index as usize) .map(|value| context.value_stack_mut().push(value)) .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_set_local(&mut self, context: &mut FunctionContext, index: u32) -> Result { + fn run_set_local(&mut self, context: &mut FunctionContext, index: u32) -> Result, Error> { let arg = context.value_stack_mut().pop()?; context.set_local(index as usize, arg) .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_tee_local(&mut self, context: &mut FunctionContext, index: u32) -> Result { + fn run_tee_local(&mut self, context: &mut FunctionContext, index: u32) -> Result, Error> { let arg = context.value_stack().top()?.clone(); context.set_local(index as usize, arg) .map(|_| InstructionOutcome::RunNextInstruction) @@ -502,9 +502,9 @@ impl<'a, St: 'static> Interpreter<'a, St> { fn run_get_global( &mut self, - context: &mut FunctionContext, + context: &mut FunctionContext, index: u32, - ) -> Result { + ) -> Result, Error> { let global = context .module() .global_by_index(index) @@ -516,9 +516,9 @@ impl<'a, St: 'static> Interpreter<'a, St> { fn run_set_global( &mut self, - context: &mut FunctionContext, + context: &mut FunctionContext, index: u32, - ) -> Result { + ) -> Result, Error> { let val = context.value_stack_mut().pop()?; let global = context @@ -529,7 +529,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_load(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result + fn run_load(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result, Error> where RuntimeValue: From, T: LittleEndianConvert { let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let m = context.module() @@ -541,7 +541,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_load_extend(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result + fn run_load_extend(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result, Error> where T: ExtendInto, RuntimeValue: From, T: LittleEndianConvert { let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let m = context.module() @@ -557,7 +557,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_store(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result + fn run_store(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result, Error> where RuntimeValue: TryInto, T: LittleEndianConvert { let stack_value = context .value_stack_mut() @@ -574,10 +574,10 @@ impl<'a, St: 'static> Interpreter<'a, St> { fn run_store_wrap( &mut self, - context: &mut FunctionContext, + context: &mut FunctionContext, _align: u32, offset: u32, - ) -> Result + ) -> Result, Error> where RuntimeValue: TryInto, T: WrapInto, @@ -597,7 +597,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result { + fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result, Error> { let m = context.module() .memory_by_index(DEFAULT_MEMORY_INDEX) .expect("Due to validation memory should exists"); @@ -608,7 +608,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result { + fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result, Error> { let pages: u32 = context.value_stack_mut().pop_as()?; let m = context.module() .memory_by_index(DEFAULT_MEMORY_INDEX) @@ -620,7 +620,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { Ok(InstructionOutcome::RunNextInstruction) } - fn run_const(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result { + fn run_const(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result, Error> { context .value_stack_mut() .push(val) @@ -628,7 +628,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_eqz(&mut self, context: &mut FunctionContext) -> Result + fn run_eqz(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialEq + Default { context .value_stack_mut() @@ -638,7 +638,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_eq(&mut self, context: &mut FunctionContext) -> Result + fn run_eq(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialEq { context .value_stack_mut() @@ -648,7 +648,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_ne(&mut self, context: &mut FunctionContext) -> Result + fn run_ne(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialEq { context .value_stack_mut() @@ -658,7 +658,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_lt(&mut self, context: &mut FunctionContext) -> Result + fn run_lt(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialOrd + Display { context .value_stack_mut() @@ -668,7 +668,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_gt(&mut self, context: &mut FunctionContext) -> Result + fn run_gt(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialOrd { context .value_stack_mut() @@ -678,7 +678,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_lte(&mut self, context: &mut FunctionContext) -> Result + fn run_lte(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialOrd { context .value_stack_mut() @@ -688,7 +688,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_gte(&mut self, context: &mut FunctionContext) -> Result + fn run_gte(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: TryInto, T: PartialOrd { context .value_stack_mut() @@ -698,7 +698,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_clz(&mut self, context: &mut FunctionContext) -> Result + fn run_clz(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Integer { context .value_stack_mut() @@ -708,7 +708,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_ctz(&mut self, context: &mut FunctionContext) -> Result + fn run_ctz(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Integer { context .value_stack_mut() @@ -718,7 +718,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_popcnt(&mut self, context: &mut FunctionContext) -> Result + fn run_popcnt(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Integer { context .value_stack_mut() @@ -728,7 +728,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_add(&mut self, context: &mut FunctionContext) -> Result + fn run_add(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: ArithmeticOps { context .value_stack_mut() @@ -738,7 +738,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_sub(&mut self, context: &mut FunctionContext) -> Result + fn run_sub(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: ArithmeticOps { context .value_stack_mut() @@ -748,7 +748,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_mul(&mut self, context: &mut FunctionContext) -> Result + fn run_mul(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: ArithmeticOps { context .value_stack_mut() @@ -758,7 +758,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_div(&mut self, context: &mut FunctionContext) -> Result + fn run_div(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: TransmuteInto + Display, U: ArithmeticOps + TransmuteInto { context .value_stack_mut() @@ -770,7 +770,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_rem(&mut self, context: &mut FunctionContext) -> Result + fn run_rem(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: TransmuteInto, U: Integer + TransmuteInto { context .value_stack_mut() @@ -782,7 +782,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_and(&mut self, context: &mut FunctionContext) -> Result + fn run_and(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From<::Output> + TryInto, T: ops::BitAnd { context .value_stack_mut() @@ -792,7 +792,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_or(&mut self, context: &mut FunctionContext) -> Result + fn run_or(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From<::Output> + TryInto, T: ops::BitOr { context .value_stack_mut() @@ -802,7 +802,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_xor(&mut self, context: &mut FunctionContext) -> Result + fn run_xor(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From<::Output> + TryInto, T: ops::BitXor { context .value_stack_mut() @@ -812,7 +812,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_shl(&mut self, context: &mut FunctionContext, mask: T) -> Result + fn run_shl(&mut self, context: &mut FunctionContext, mask: T) -> Result, Error> where RuntimeValue: From<>::Output> + TryInto, T: ops::Shl + ops::BitAnd { context .value_stack_mut() @@ -822,7 +822,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_shr(&mut self, context: &mut FunctionContext, mask: U) -> Result + fn run_shr(&mut self, context: &mut FunctionContext, mask: U) -> Result, Error> where RuntimeValue: From + TryInto, T: TransmuteInto, U: ops::Shr + ops::BitAnd, >::Output: TransmuteInto { context .value_stack_mut() @@ -834,7 +834,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_rotl(&mut self, context: &mut FunctionContext) -> Result + fn run_rotl(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Integer { context .value_stack_mut() @@ -844,7 +844,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_rotr(&mut self, context: &mut FunctionContext) -> Result + fn run_rotr(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Integer { context .value_stack_mut() @@ -854,7 +854,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_abs(&mut self, context: &mut FunctionContext) -> Result + fn run_abs(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -864,7 +864,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_neg(&mut self, context: &mut FunctionContext) -> Result + fn run_neg(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From<::Output> + TryInto, T: ops::Neg { context .value_stack_mut() @@ -874,7 +874,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_ceil(&mut self, context: &mut FunctionContext) -> Result + fn run_ceil(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -884,7 +884,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_floor(&mut self, context: &mut FunctionContext) -> Result + fn run_floor(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -894,7 +894,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_trunc(&mut self, context: &mut FunctionContext) -> Result + fn run_trunc(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -904,7 +904,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_nearest(&mut self, context: &mut FunctionContext) -> Result + fn run_nearest(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -914,7 +914,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_sqrt(&mut self, context: &mut FunctionContext) -> Result + fn run_sqrt(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -924,7 +924,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_min(&mut self, context: &mut FunctionContext) -> Result + fn run_min(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -934,7 +934,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_max(&mut self, context: &mut FunctionContext) -> Result + fn run_max(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -944,7 +944,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_copysign(&mut self, context: &mut FunctionContext) -> Result + fn run_copysign(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: Float { context .value_stack_mut() @@ -954,7 +954,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_wrap(&mut self, context: &mut FunctionContext) -> Result + fn run_wrap(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: WrapInto { context .value_stack_mut() @@ -964,7 +964,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_trunc_to_int(&mut self, context: &mut FunctionContext) -> Result + fn run_trunc_to_int(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: TryTruncateInto, U: TransmuteInto, { context .value_stack_mut() @@ -975,7 +975,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_extend(&mut self, context: &mut FunctionContext) -> Result + fn run_extend(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From + TryInto, T: ExtendInto, U: TransmuteInto { context .value_stack_mut() @@ -987,7 +987,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_reinterpret(&mut self, context: &mut FunctionContext) -> Result + fn run_reinterpret(&mut self, context: &mut FunctionContext) -> Result, Error> where RuntimeValue: From, RuntimeValue: TryInto, T: TransmuteInto { context .value_stack_mut() @@ -998,8 +998,8 @@ impl<'a, St: 'static> Interpreter<'a, St> { } } -impl FunctionContext { - pub fn new<'store>(function: Rc, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec) -> Self { +impl FunctionContext { + pub fn new<'store>(function: Rc>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec) -> Self { let module = match *function { FuncInstance::Internal { ref module, .. } => Rc::clone(module), FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"), @@ -1016,7 +1016,7 @@ impl FunctionContext { } } - pub fn nested(&mut self, function: Rc) -> Result { + pub fn nested(&mut self, function: Rc>) -> Result { let (function_locals, module, function_return_type) = { let module = match *function { FuncInstance::Internal { ref module, .. } => Rc::clone(module), @@ -1055,11 +1055,11 @@ impl FunctionContext { self.locals.extend(locals); } - pub fn module(&self) -> Rc { + pub fn module(&self) -> Rc> { Rc::clone(&self.module) } - pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result { + pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result, Error> { let l = self.locals.get_mut(index) .ok_or(Error::Local(format!("expected to have local with index {}", index)))?; @@ -1137,7 +1137,7 @@ impl FunctionContext { } } -impl fmt::Debug for FunctionContext { +impl fmt::Debug for FunctionContext { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "FunctionContext") } diff --git a/src/interpreter/table.rs b/src/interpreter/table.rs index 2ac3180..8cd49d7 100644 --- a/src/interpreter/table.rs +++ b/src/interpreter/table.rs @@ -8,15 +8,15 @@ use interpreter::module::check_limits; use interpreter::func::FuncInstance; /// Table instance. -pub struct TableInstance { +pub struct TableInstance { /// Table limits. limits: ResizableLimits, /// Table memory buffer. - buffer: RwLock>>>, + buffer: RwLock>>>>, } -impl fmt::Debug for TableInstance { +impl fmt::Debug for TableInstance { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("TableInstance") .field("limits", &self.limits) @@ -25,7 +25,7 @@ impl fmt::Debug for TableInstance { } } -impl TableInstance { +impl TableInstance { /// New instance of the table pub fn new(table_type: &TableType) -> Result { check_limits(table_type.limits())?; @@ -43,7 +43,7 @@ impl TableInstance { } /// Get the specific value in the table - pub fn get(&self, offset: u32) -> Result, Error> { + pub fn get(&self, offset: u32) -> Result>, Error> { let buffer = self.buffer.read(); let buffer_len = buffer.len(); let table_elem = buffer.get(offset as usize).cloned().ok_or(Error::Table(format!( @@ -58,7 +58,7 @@ impl TableInstance { } /// Set the table element to the specified function. - pub fn set(&self, offset: u32, value: Rc) -> Result<(), Error> { + pub fn set(&self, offset: u32, value: Rc>) -> Result<(), Error> { let mut buffer = self.buffer.write(); let buffer_len = buffer.len(); let table_elem = buffer.get_mut(offset as usize).ok_or(Error::Table(format!( diff --git a/src/interpreter/tests/basics.rs b/src/interpreter/tests/basics.rs index 33b6832..5c713db 100644 --- a/src/interpreter/tests/basics.rs +++ b/src/interpreter/tests/basics.rs @@ -121,7 +121,7 @@ struct TestState { pub values: Vec, } -fn build_env_module() -> HostModule { +fn build_env_module() -> HostModule { let mut builder = HostModuleBuilder::::new(); builder.with_func2("add", |state: &mut TestState, arg: i32, unused: i32| { let memory_value = state.memory.get(0, 1).unwrap()[0]; @@ -219,7 +219,7 @@ fn native_env_function() { fn native_env_global() { struct State; - let module_constructor = |host_module: HostModule| { + let module_constructor = |host_module: HostModule| { let mut program = ProgramInstance::new(); program.add_host_module("env", host_module); diff --git a/src/interpreter/tests/mod.rs b/src/interpreter/tests/mod.rs index 593fb84..8610a08 100644 --- a/src/interpreter/tests/mod.rs +++ b/src/interpreter/tests/mod.rs @@ -3,27 +3,22 @@ mod wabt; mod wasm; mod utils { - use elements::{Internal, ExportEntry, InitExpr, Opcode, ValueType, GlobalType, GlobalEntry}; - use interpreter::ProgramInstance; - use builder::module; + use elements::{ExportEntry, InitExpr, Opcode, ValueType, GlobalType, GlobalEntry, MemoryType, TableType}; + use interpreter::{ProgramInstance, HostModuleBuilder, MemoryInstance, TableInstance, GlobalInstance, RuntimeValue}; + use std::rc::Rc; - pub fn program_with_default_env() -> ProgramInstance { - let mut program = ProgramInstance::new(); - let env_module = module() - .memory() - .with_min(256) // 256 pages. 256 * 64K = 16MB - .build() - .with_export(ExportEntry::new("memory".into(), Internal::Memory(0))) - .table() - .with_min(64) - .build() - .with_export(ExportEntry::new("table".into(), Internal::Table(0))) - .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0), Opcode::End]))) - .with_export(ExportEntry::new("tableBase".into(), Internal::Global(0))) - .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0), Opcode::End]))) - .with_export(ExportEntry::new("memoryBase".into(), Internal::Global(1))) - .build(); - program.add_module("env", env_module, &mut ()).unwrap(); + pub fn program_with_default_env() -> ProgramInstance { + let mut program = ProgramInstance::::new(); + + let mut builder = HostModuleBuilder::::new(); + // TODO: Alloc + builder.insert_memory("memory", Rc::new(MemoryInstance::new(&MemoryType::new(256, None)).unwrap())); + builder.insert_table("table", Rc::new(TableInstance::new(&TableType::new(64, None)).unwrap())); + builder.insert_global("tableBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false))); + builder.insert_global("memoryBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false))); + let env_host_module = builder.build(); + + program.add_host_module("env", env_host_module); program } } diff --git a/src/interpreter/tests/wasm.rs b/src/interpreter/tests/wasm.rs index 4271543..2f4875a 100644 --- a/src/interpreter/tests/wasm.rs +++ b/src/interpreter/tests/wasm.rs @@ -1,6 +1,6 @@ use elements::deserialize_file; -use elements::Module; -use interpreter::value::RuntimeValue; +use elements::{Module, MemoryType}; +use interpreter::RuntimeValue; use super::utils::program_with_default_env; #[test] @@ -46,8 +46,10 @@ fn interpreter_accumulate_u8() { .add_module("main", module, &mut ()) .expect("Failed to initialize module"); - let env_module = program.module("env").unwrap(); - let env_memory = env_module.memory_by_index(0).unwrap(); + let env_memory = { + let env_module = program.module("env").unwrap(); + env_module.resolve_memory("memory", &MemoryType::new(1, None)).unwrap() + }; // Place the octet-sequence at index 0 in linear memory let offset: u32 = 0;