From 2ae72c1dabe12d5bcc460052fecf5c904382396c Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Wed, 13 Dec 2017 13:25:24 +0100 Subject: [PATCH] Replace all func_ids to Rcs. --- src/interpreter/host.rs | 10 ++--- src/interpreter/program.rs | 6 +-- src/interpreter/runner.rs | 33 +++++++-------- src/interpreter/store.rs | 82 ++++++++++++++++---------------------- src/interpreter/table.rs | 11 ++--- 5 files changed, 63 insertions(+), 79 deletions(-) diff --git a/src/interpreter/host.rs b/src/interpreter/host.rs index a97730f..29ceba2 100644 --- a/src/interpreter/host.rs +++ b/src/interpreter/host.rs @@ -1,5 +1,5 @@ use std::any::Any; -use std::sync::Arc; +use std::rc::Rc; use std::marker::PhantomData; use std::collections::HashMap; use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType}; @@ -11,7 +11,7 @@ enum HostItem { Func { name: String, func_type: FunctionType, - host_func: Arc, + host_func: Rc, }, Global { name: String, @@ -56,7 +56,7 @@ impl HostModuleBuilder { f: F, ) { let func_type = Func0::::derive_func_type(); - let host_func = Arc::new(f.into()) as Arc; + let host_func = Rc::new(f.into()) as Rc; self.items.push(HostItem::Func { name: name.into(), @@ -77,7 +77,7 @@ impl HostModuleBuilder { f: F, ) { let func_type = Func1::::derive_func_type(); - let host_func = Arc::new(f.into()) as Arc; + let host_func = Rc::new(f.into()) as Rc; self.items.push(HostItem::Func { name: name.into(), @@ -99,7 +99,7 @@ impl HostModuleBuilder { f: F, ) { let func_type = Func2::::derive_func_type(); - let host_func = Arc::new(f.into()) as Arc; + let host_func = Rc::new(f.into()) as Rc; self.items.push(HostItem::Func { name: name.into(), diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index 6f90d8d..eb6f4d4 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -1,8 +1,8 @@ - +use std::rc::Rc; use std::collections::HashMap; use elements::Module; use interpreter::Error; -use interpreter::store::{ModuleId, FuncId, Store, ExternVal}; +use interpreter::store::{ModuleId, Store, ExternVal, FuncInstance}; use interpreter::host::HostModule; use interpreter::value::RuntimeValue; @@ -115,7 +115,7 @@ impl ProgramInstance { pub fn invoke_func( &mut self, - func: FuncId, + func: Rc, args: Vec, state: &mut St, ) -> Result, Error> { diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index 29c0e24..3b9ee3c 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -1,12 +1,13 @@ use std::mem; use std::ops; +use std::rc::Rc; use std::{u32, usize}; use std::fmt::{self, Display}; use std::iter::repeat; use std::collections::{HashMap, VecDeque}; use elements::{Opcode, BlockType, Local, FunctionType}; use interpreter::Error; -use interpreter::store::{Store, FuncId, ModuleId, FuncInstance}; +use interpreter::store::{Store, ModuleId, FuncInstance}; use interpreter::value::{ RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, @@ -25,7 +26,7 @@ pub struct FunctionContext { /// Is context initialized. pub is_initialized: bool, /// Internal function reference. - pub function: FuncId, + pub function: Rc, pub module: ModuleId, /// Function return type. pub return_type: BlockType, @@ -47,7 +48,7 @@ pub enum InstructionOutcome { /// Branch to given frame. Branch(usize), /// Execute function call. - ExecuteCall(FuncId), + ExecuteCall(Rc), /// End current frame. End, /// Return from current function block. @@ -59,7 +60,7 @@ enum RunResult { /// Function has returned (optional) value. Return(Option), /// Function is calling other function. - NestedCall(FuncId), + NestedCall(Rc), } impl<'a, St: 'static> Interpreter<'a, St> { @@ -76,11 +77,9 @@ impl<'a, St: 'static> Interpreter<'a, St> { loop { let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed"); - let function_ref = function_context.function; + let function_ref = Rc::clone(&function_context.function); let function_return = { - let func_body = function_ref.resolve(self.store).body(); - - match func_body { + match function_ref.body() { Some(function_body) => { if !function_context.is_initialized() { let return_type = function_context.return_type; @@ -108,8 +107,8 @@ impl<'a, St: 'static> Interpreter<'a, St> { } }, RunResult::NestedCall(nested_func) => { - let func = nested_func.resolve(self.store).clone(); - match func { + // TODO: check this + match *nested_func { FuncInstance::Internal { .. } => { let nested_context = function_context.nested(self.store, nested_func)?; function_stack.push_back(function_context); @@ -452,7 +451,7 @@ impl<'a, St: 'static> Interpreter<'a, St> { .resolve(self.store); let func_ref = table.get(table_func_idx)?; - let actual_function_type = func_ref.resolve(self.store).func_type().resolve(self.store); + let actual_function_type = func_ref.func_type().resolve(self.store); let required_function_type = context .module() .type_by_index(self.store, type_idx) @@ -1019,9 +1018,8 @@ impl<'a, St: 'static> Interpreter<'a, St> { } impl FunctionContext { - pub fn new<'store>(store: &'store Store, function: FuncId, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec) -> Self { - let func_instance = function.resolve(store); - let module = match *func_instance { + pub fn new<'store>(store: &'store Store, function: Rc, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec) -> Self { + let module = match *function { FuncInstance::Internal { module, .. } => 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"), }; @@ -1037,14 +1035,13 @@ impl FunctionContext { } } - pub fn nested(&mut self, store: &Store, function: FuncId) -> Result { + pub fn nested(&mut self, store: &Store, function: Rc) -> Result { let (function_locals, module, function_return_type) = { - let func_instance = function.resolve(store); - let module = match *func_instance { + let module = match *function { FuncInstance::Internal { module, .. } => 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"), }; - let function_type = func_instance.func_type().resolve(store); + let function_type = function.func_type().resolve(store); let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult); let function_locals = prepare_function_args(function_type, &mut self.value_stack)?; (function_locals, module, function_return_type) diff --git a/src/interpreter/store.rs b/src/interpreter/store.rs index d38774e..c74541d 100644 --- a/src/interpreter/store.rs +++ b/src/interpreter/store.rs @@ -1,7 +1,7 @@ // TODO: remove this #![allow(unused)] -use std::sync::Arc; +use std::rc::Rc; use std::any::Any; use std::fmt; use std::collections::HashMap; @@ -52,7 +52,7 @@ impl ModuleId { .cloned() } - pub fn func_by_index(&self, store: &Store, idx: u32) -> Option { + pub fn func_by_index(&self, store: &Store, idx: u32) -> Option> { store.resolve_module(*self) .funcs .get(idx as usize) @@ -77,17 +77,6 @@ impl ModuleId { #[derive(Copy, Clone, Debug)] pub struct HostFuncId(u32); -#[derive(Copy, Clone, Debug)] -pub struct FuncId(u32); - -impl FuncId { - pub fn resolve<'s>(&self, store: &'s Store) -> &'s FuncInstance { - store - .funcs - .get(self.0 as usize) - .expect("ID should be always valid") - } -} #[derive(Copy, Clone, Debug)] pub struct TableId(u32); @@ -116,18 +105,18 @@ impl MemoryId { #[derive(Copy, Clone, Debug)] pub struct GlobalId(u32); -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub enum ExternVal { - Func(FuncId), + Func(Rc), Table(TableId), Memory(MemoryId), Global(GlobalId), } impl ExternVal { - pub fn as_func(&self) -> Option { + pub fn as_func(&self) -> Option> { match *self { - ExternVal::Func(func) => Some(func), + ExternVal::Func(ref func) => Some(Rc::clone(func)), _ => None, } } @@ -159,11 +148,11 @@ pub enum FuncInstance { Internal { func_type: TypeId, module: ModuleId, - body: Arc, + body: Rc, }, Host { func_type: TypeId, - host_func: Arc, + host_func: Rc, }, } @@ -189,9 +178,9 @@ impl FuncInstance { } } - pub fn body(&self) -> Option> { + pub fn body(&self) -> Option> { match *self { - FuncInstance::Internal { ref body, .. } => Some(Arc::clone(body)), + FuncInstance::Internal { ref body, .. } => Some(Rc::clone(body)), FuncInstance::Host { .. } => None, } } @@ -224,8 +213,8 @@ pub struct ExportInstance { #[derive(Default, Debug)] pub struct ModuleInstance { types: Vec, - funcs: Vec, tables: Vec, + funcs: Vec>, memories: Vec, globals: Vec, exports: HashMap, @@ -274,25 +263,21 @@ impl Store { TypeId(type_id as u32) } - pub fn alloc_func(&mut self, module: ModuleId, func_type: TypeId, body: FuncBody) -> FuncId { + pub fn alloc_func(&mut self, module: ModuleId, func_type: TypeId, body: FuncBody) -> Rc { let func = FuncInstance::Internal { func_type, module, - body: Arc::new(body), + body: Rc::new(body), }; - self.funcs.push(func); - let func_id = self.funcs.len() - 1; - FuncId(func_id as u32) + Rc::new(func) } - pub fn alloc_host_func(&mut self, func_type: TypeId, host_func: Arc) -> FuncId { + pub fn alloc_host_func(&mut self, func_type: TypeId, host_func: Rc) -> Rc { let func = FuncInstance::Host { func_type, host_func, }; - self.funcs.push(func); - let func_id = self.funcs.len() - 1; - FuncId(func_id as u32) + Rc::new(func) } pub fn alloc_table(&mut self, table_type: &TableType) -> Result { @@ -342,10 +327,10 @@ impl Store { for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter()) { - match (import.external(), *extern_val) { - (&External::Function(fn_type_idx), ExternVal::Func(func)) => { + match (import.external(), extern_val) { + (&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => { let expected_fn_type = instance.types.get(fn_type_idx as usize).expect("Due to validation function type should exists").resolve(self); - let actual_fn_type = func.resolve(self).func_type().resolve(self); + let actual_fn_type = func.func_type().resolve(self); if expected_fn_type != actual_fn_type { return Err(Error::Initialization(format!( "Expected function with type {:?}, but actual type is {:?} for entry {}", @@ -354,17 +339,17 @@ impl Store { import.field(), ))); } - instance.funcs.push(func) + instance.funcs.push(Rc::clone(func)) } - (&External::Table(ref tt), ExternVal::Table(table)) => { + (&External::Table(ref tt), &ExternVal::Table(table)) => { match_limits(table.resolve(self).limits(), tt.limits())?; instance.tables.push(table); } - (&External::Memory(ref mt), ExternVal::Memory(memory)) => { + (&External::Memory(ref mt), &ExternVal::Memory(memory)) => { match_limits(memory.resolve(self).limits(), mt.limits())?; instance.memories.push(memory); } - (&External::Global(ref gl), ExternVal::Global(global)) => { + (&External::Global(ref gl), &ExternVal::Global(global)) => { // TODO: check globals instance.globals.push(global) } @@ -439,11 +424,11 @@ impl Store { let field = export.field(); let extern_val: ExternVal = match *export.internal() { Internal::Function(idx) => { - let func_id = instance + let func = instance .funcs .get(idx as usize) .expect("Due to validation func should exists"); - ExternVal::Func(*func_id) + ExternVal::Func(Rc::clone(func)) } Internal::Global(idx) => { let global_id = instance @@ -504,12 +489,12 @@ impl Store { .expect("ID should be always valid"); for (j, func_idx) in element_segment.members().into_iter().enumerate() { - let func_id = instance + let func = instance .funcs .get(*func_idx as usize) .expect("Due to validation funcs from element segments should exists"); - table_inst.set(offset_val + j as u32, *func_id); + table_inst.set(offset_val + j as u32, Rc::clone(func)); } } @@ -537,9 +522,10 @@ impl Store { if let Some(start_fn_idx) = module.start_section() { let start_func = { let instance = self.resolve_module(module_id); - *instance + instance .funcs .get(start_fn_idx as usize) + .cloned() .expect("Due to validation start function should exists") }; self.invoke(start_func, vec![], state)?; @@ -556,23 +542,23 @@ impl Store { pub fn invoke( &mut self, - func: FuncId, + func: Rc, args: Vec, state: &mut St, ) -> Result, Error> { enum InvokeKind { Internal(FunctionContext), - Host(Arc, Vec), + Host(Rc, Vec), } - let result = match *func.resolve(self) { + let result = match *func { FuncInstance::Internal { func_type, .. } => { let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT); let func_signature = func_type.resolve(self); let args = prepare_function_args(&func_signature, &mut args)?; let context = FunctionContext::new( self, - func, + Rc::clone(&func), DEFAULT_VALUE_STACK_LIMIT, DEFAULT_FRAME_STACK_LIMIT, &func_signature, @@ -580,7 +566,7 @@ impl Store { ); InvokeKind::Internal(context) } - FuncInstance::Host { ref host_func, .. } => InvokeKind::Host(Arc::clone(host_func), args), + FuncInstance::Host { ref host_func, .. } => InvokeKind::Host(Rc::clone(host_func), args), }; match result { diff --git a/src/interpreter/table.rs b/src/interpreter/table.rs index aa910e6..bd16edf 100644 --- a/src/interpreter/table.rs +++ b/src/interpreter/table.rs @@ -1,18 +1,19 @@ use std::u32; use std::fmt; +use std::rc::Rc; use parking_lot::RwLock; use elements::{TableType, ResizableLimits}; use interpreter::Error; use interpreter::module::check_limits; use interpreter::variable::VariableType; -use interpreter::store::FuncId; +use interpreter::store::FuncInstance; /// Table instance. pub struct TableInstance { /// Table limits. limits: ResizableLimits, /// Table memory buffer. - buffer: RwLock>>, + buffer: RwLock>>>, } @@ -48,10 +49,10 @@ impl TableInstance { } /// Get the specific value in the table - pub fn get(&self, offset: u32) -> Result { + 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).ok_or(Error::Table(format!( + let table_elem = buffer.get(offset as usize).cloned().ok_or(Error::Table(format!( "trying to read table item with index {} when there are only {} items", offset, buffer_len @@ -63,7 +64,7 @@ impl TableInstance { } /// Set the table element to the specified function. - pub fn set(&self, offset: u32, value: FuncId) -> 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!(