diff --git a/spec/src/run.rs b/spec/src/run.rs index 55dfa09..c58be84 100644 --- a/spec/src/run.rs +++ b/spec/src/run.rs @@ -21,16 +21,17 @@ use parity_wasm::interpreter::{ TableInstance, ModuleInstance, HostFunc, + MemoryRef, }; struct SpecModule { default_host_callback: Rc>, table: Rc>, - memory: Rc, - global_i32: Rc, - global_i64: Rc, - global_f32: Rc, - global_f64: Rc, + memory: MemoryRef, + global_i32: GlobalRef, + global_i64: GlobalRef, + global_f32: GlobalRef, + global_f64: GlobalRef, } impl SpecModule { @@ -73,7 +74,7 @@ impl ImportResolver<()> for SpecModule { &self, field_name: &str, global_type: &GlobalType, - ) -> Result, InterpreterError> { + ) -> Result { if field_name == "global" { return match global_type.content_type() { ValueType::I32 => { @@ -98,7 +99,7 @@ impl ImportResolver<()> for SpecModule { &self, field_name: &str, _memory_type: &MemoryType, - ) -> Result, InterpreterError> { + ) -> Result { if field_name == "memory" { return Ok(Rc::clone(&self.memory)); } diff --git a/src/interpreter/func.rs b/src/interpreter/func.rs index 4442e4b..b4754e8 100644 --- a/src/interpreter/func.rs +++ b/src/interpreter/func.rs @@ -3,6 +3,7 @@ use std::fmt; use std::collections::HashMap; use std::borrow::Cow; use elements::{FunctionType, Local, Opcodes}; +use interpreter::module::FuncRef; use interpreter::{Error, ModuleInstance}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; use interpreter::host::HostFunc; @@ -83,7 +84,7 @@ impl FuncInstance { } pub fn invoke<'a, 'b: 'a>( - func: Rc, + func: FuncRef, args: Cow<[RuntimeValue]>, state: &'a mut HostState<'b>, ) -> Result, Error> { diff --git a/src/interpreter/host.rs b/src/interpreter/host.rs index 780a9bf..47819dc 100644 --- a/src/interpreter/host.rs +++ b/src/interpreter/host.rs @@ -1,8 +1,11 @@ +use interpreter::module::GlobalRef; use std::rc::Rc; use std::collections::HashMap; use std::collections::hash_map::Entry; use elements::{FunctionType, GlobalType, MemoryType, TableType, ValueType}; -use interpreter::module::{ExternVal, ModuleInstance}; +use interpreter::module::{ExternVal, ModuleInstance, FuncRef}; +use interpreter::module::MemoryRef; +use interpreter::module::TableRef; use interpreter::func::FuncInstance; use interpreter::global::GlobalInstance; use interpreter::memory::MemoryInstance; @@ -222,33 +225,33 @@ impl HostModuleBuilder { self } - pub fn insert_func>(&mut self, name: N, func: Rc) { + pub fn insert_func>(&mut self, name: N, func: FuncRef) { self.insert(name, ExternVal::Func(func)); } - pub fn insert_global>(&mut self, name: N, global: Rc) { + pub fn insert_global>(&mut self, name: N, global: GlobalRef) { self.insert(name, ExternVal::Global(global)); } - pub fn insert_memory>(&mut self, name: N, memory: Rc) { + pub fn insert_memory>(&mut self, name: N, memory: MemoryRef) { 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: TableRef) { self.insert(name, ExternVal::Table(table)); } - pub fn with_global>(mut self, name: N, global: Rc) -> Self { + pub fn with_global>(mut self, name: N, global: GlobalRef) -> Self { self.insert_global(name, global); self } - pub fn with_memory>(mut self, name: N, memory: Rc) -> Self { + pub fn with_memory>(mut self, name: N, memory: MemoryRef) -> Self { self.insert_memory(name, memory); self } - pub fn with_table>(mut self, name: N, table: Rc) -> Self { + pub fn with_table>(mut self, name: N, table: TableRef) -> Self { self.insert_table(name, table); self } @@ -281,7 +284,7 @@ impl ImportResolver for HostModule { &self, field_name: &str, func_type: &FunctionType, - ) -> Result, Error> { + ) -> Result { self.internal_instance.resolve_func(field_name, func_type) } @@ -289,7 +292,7 @@ impl ImportResolver for HostModule { &self, field_name: &str, global_type: &GlobalType, - ) -> Result, Error> { + ) -> Result { self.internal_instance .resolve_global(field_name, global_type) } @@ -298,7 +301,7 @@ impl ImportResolver for HostModule { &self, field_name: &str, memory_type: &MemoryType, - ) -> Result, Error> { + ) -> Result { self.internal_instance .resolve_memory(field_name, memory_type) } @@ -307,7 +310,7 @@ impl ImportResolver for HostModule { &self, field_name: &str, table_type: &TableType, - ) -> Result, Error> { + ) -> Result { self.internal_instance.resolve_table(field_name, table_type) } } @@ -382,3 +385,20 @@ impl IntoReturnVal for () { None } } + +trait Externals { + fn invoke_index( + &mut self, + index: u32, + args: &[RuntimeValue], + ) -> Result, Error>; + + // TODO: or check signature? + fn signature(&self, index: usize) -> &FunctionType; + + fn memory_by_index(&self, index: usize) -> &MemoryInstance; + fn table_by_index(&self, index: usize) -> &TableInstance; + fn global_by_index(&self, index: usize) -> &GlobalInstance; +} + + diff --git a/src/interpreter/imports.rs b/src/interpreter/imports.rs index 1717069..f22a4d8 100644 --- a/src/interpreter/imports.rs +++ b/src/interpreter/imports.rs @@ -1,10 +1,9 @@ -use std::rc::Rc; +use interpreter::module::GlobalRef; use std::collections::HashMap; use elements::{FunctionType, GlobalType, MemoryType, TableType}; -use interpreter::func::FuncInstance; -use interpreter::global::GlobalInstance; -use interpreter::memory::MemoryInstance; -use interpreter::table::TableInstance; +use interpreter::module::MemoryRef; +use interpreter::module::FuncRef; +use interpreter::module::TableRef; use interpreter::Error; pub struct Imports<'a> { @@ -45,23 +44,23 @@ pub trait ImportResolver { &self, field_name: &str, func_type: &FunctionType, - ) -> Result, Error>; + ) -> Result; fn resolve_global( &self, field_name: &str, global_type: &GlobalType, - ) -> Result, Error>; + ) -> Result; fn resolve_memory( &self, field_name: &str, memory_type: &MemoryType, - ) -> Result, Error>; + ) -> Result; fn resolve_table( &self, field_name: &str, table_type: &TableType, - ) -> Result, Error>; + ) -> Result; } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 062b309..b3a8575 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -157,7 +157,7 @@ pub use self::program::ProgramInstance; pub use self::value::RuntimeValue; pub use self::host::{HostModule, HostModuleBuilder, HostFunc, IntoReturnVal, FromArg}; pub use self::imports::{ImportResolver, Imports}; -pub use self::module::ModuleInstance; +pub use self::module::{ModuleInstance, FuncRef, MemoryRef, GlobalRef, TableRef}; pub use self::global::GlobalInstance; pub use self::func::FuncInstance; pub use self::state::{HostState, StateKey}; diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index ef09303..f64feb0 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -13,11 +13,16 @@ use interpreter::state::HostState; use validation::validate_module; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; +pub type FuncRef = Rc; +pub type TableRef = Rc; +pub type MemoryRef = Rc; +pub type GlobalRef = Rc; + pub enum ExternVal { - Func(Rc), - Table(Rc), - Memory(Rc), - Global(Rc), + Func(FuncRef), + Table(TableRef), + Memory(MemoryRef), + Global(GlobalRef), } impl Clone for ExternVal { @@ -47,28 +52,28 @@ impl fmt::Debug for ExternVal { } impl ExternVal { - pub fn as_func(&self) -> Option> { + 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, } } - pub fn as_memory(&self) -> Option> { + pub fn as_memory(&self) -> Option { match *self { ExternVal::Memory(ref memory) => Some(Rc::clone(memory)), _ => None, } } - pub fn as_global(&self) -> Option> { + pub fn as_global(&self) -> Option { match *self { ExternVal::Global(ref global) => Some(Rc::clone(global)), _ => None, @@ -79,10 +84,10 @@ impl ExternVal { #[derive(Debug)] pub struct ModuleInstance { types: RefCell>>, - tables: RefCell>>, - funcs: RefCell>>, - memories: RefCell>>, - globals: RefCell>>, + tables: RefCell>, + funcs: RefCell>, + memories: RefCell>, + globals: RefCell>, exports: RefCell>, } @@ -106,19 +111,19 @@ impl ModuleInstance { instance } - pub fn memory_by_index(&self, idx: u32) -> Option> { + 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() } - pub fn global_by_index(&self, idx: u32) -> Option> { + pub fn global_by_index(&self, idx: u32) -> Option { 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() } @@ -130,7 +135,7 @@ impl ModuleInstance { self.exports.borrow().get(name).cloned() } - fn push_func(&self, func: Rc) { + fn push_func(&self, func: FuncRef) { self.funcs.borrow_mut().push(func); } @@ -138,15 +143,15 @@ impl ModuleInstance { self.types.borrow_mut().push(func_type) } - fn push_memory(&self, memory: Rc) { + fn push_memory(&self, memory: MemoryRef) { self.memories.borrow_mut().push(memory) } - fn push_table(&self, table: Rc) { + fn push_table(&self, table: TableRef) { self.tables.borrow_mut().push(table) } - fn push_global(&self, global: Rc) { + fn push_global(&self, global: GlobalRef) { self.globals.borrow_mut().push(global) } @@ -498,7 +503,7 @@ impl ImportResolver for ModuleInstance { &self, field_name: &str, _func_type: &FunctionType, - ) -> Result, Error> { + ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -513,7 +518,7 @@ impl ImportResolver for ModuleInstance { &self, field_name: &str, _global_type: &GlobalType, - ) -> Result, Error> { + ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -528,7 +533,7 @@ impl ImportResolver for ModuleInstance { &self, field_name: &str, _memory_type: &MemoryType, - ) -> Result, Error> { + ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -543,7 +548,7 @@ impl ImportResolver for ModuleInstance { &self, field_name: &str, _table_type: &TableType, - ) -> Result, Error> { + ) -> Result { Ok(self.export_by_name(field_name) .ok_or_else(|| { Error::Validation(format!("Export {} not found", field_name)) @@ -559,17 +564,17 @@ 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 { let table = TableInstance::new(table_type)?; Ok(Rc::new(table)) } -fn alloc_memory(mem_type: &MemoryType) -> Result, Error> { +fn alloc_memory(mem_type: &MemoryType) -> Result { let memory = MemoryInstance::new(&mem_type)?; Ok(Rc::new(memory)) } -fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> Rc { +fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> GlobalRef { let global = GlobalInstance::new(val, global_type.is_mutable()); Rc::new(global) } diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index 66fb8f4..ac0e125 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::borrow::Cow; use elements::Module; use interpreter::Error; -use interpreter::module::ModuleInstance; +use interpreter::module::{ModuleInstance, FuncRef}; use interpreter::func::FuncInstance; use interpreter::host::HostModule; use interpreter::value::RuntimeValue; @@ -98,7 +98,7 @@ impl ProgramInstance { pub fn invoke_func<'a>( &mut self, - func_instance: Rc, + func_instance: FuncRef, args: &[RuntimeValue], state: &'a mut HostState<'a>, ) -> Result, Error> { diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index 752ad48..44e8fba 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -8,6 +8,7 @@ use std::collections::{HashMap, VecDeque}; use elements::{Opcode, BlockType, Local, FunctionType}; use interpreter::Error; use interpreter::module::ModuleInstance; +use interpreter::module::FuncRef; use interpreter::func::FuncInstance; use interpreter::value::{ RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, @@ -27,7 +28,7 @@ pub struct FunctionContext { /// Is context initialized. pub is_initialized: bool, /// Internal function reference. - pub function: Rc, + pub function: FuncRef, pub module: Rc, /// Function return type. pub return_type: BlockType, @@ -48,7 +49,7 @@ pub enum InstructionOutcome { /// Branch to given frame. Branch(usize), /// Execute function call. - ExecuteCall(Rc), + ExecuteCall(FuncRef), /// End current frame. End, /// Return from current function block. @@ -60,7 +61,7 @@ enum RunResult { /// Function has returned (optional) value. Return(Option), /// Function is calling other function. - NestedCall(Rc), + NestedCall(FuncRef), } impl<'a, 'b: 'a> Interpreter<'a, 'b> { @@ -998,7 +999,7 @@ impl<'a, 'b: 'a> Interpreter<'a, 'b> { } impl FunctionContext { - pub fn new<'store>(function: Rc, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec) -> Self { + pub fn new<'store>(function: FuncRef, 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"), @@ -1015,7 +1016,7 @@ impl FunctionContext { } } - pub fn nested(&mut self, function: Rc) -> Result { + pub fn nested(&mut self, function: FuncRef) -> Result { let (function_locals, module, function_return_type) = { let module = match *function { FuncInstance::Internal { ref module, .. } => Rc::clone(module), diff --git a/src/interpreter/table.rs b/src/interpreter/table.rs index 4308d61..8ebab55 100644 --- a/src/interpreter/table.rs +++ b/src/interpreter/table.rs @@ -1,18 +1,17 @@ use std::u32; use std::fmt; -use std::rc::Rc; use std::cell::RefCell; use elements::{ResizableLimits, TableType}; use interpreter::Error; +use interpreter::module::FuncRef; use interpreter::module::check_limits; -use interpreter::func::FuncInstance; /// Table instance. pub struct TableInstance { /// Table limits. limits: ResizableLimits, /// Table memory buffer. - buffer: RefCell>>>, + buffer: RefCell>>, } impl fmt::Debug for TableInstance { @@ -40,7 +39,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 { let buffer = self.buffer.borrow(); let buffer_len = buffer.len(); let table_elem = buffer.get(offset as usize).cloned().ok_or( @@ -57,7 +56,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: FuncRef) -> Result<(), Error> { let mut buffer = self.buffer.borrow_mut(); 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 d7e9b45..7c0e3fd 100644 --- a/src/interpreter/tests/basics.rs +++ b/src/interpreter/tests/basics.rs @@ -118,7 +118,7 @@ impl ::std::fmt::Display for UserErrorWithCode { impl UserError for UserErrorWithCode {} struct TestState { - pub memory: Rc, + pub memory: MemoryRef, pub values: RefCell>, }