Replace all func_ids to Rcs.

This commit is contained in:
Sergey Pepyakin
2017-12-13 13:25:24 +01:00
parent ad06080c1b
commit 2ae72c1dab
5 changed files with 63 additions and 79 deletions

View File

@ -1,5 +1,5 @@
use std::any::Any; use std::any::Any;
use std::sync::Arc; use std::rc::Rc;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::collections::HashMap; use std::collections::HashMap;
use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType}; use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType};
@ -11,7 +11,7 @@ enum HostItem {
Func { Func {
name: String, name: String,
func_type: FunctionType, func_type: FunctionType,
host_func: Arc<AnyFunc>, host_func: Rc<AnyFunc>,
}, },
Global { Global {
name: String, name: String,
@ -56,7 +56,7 @@ impl<St: 'static> HostModuleBuilder<St> {
f: F, f: F,
) { ) {
let func_type = Func0::<Cl, St, Ret>::derive_func_type(); let func_type = Func0::<Cl, St, Ret>::derive_func_type();
let host_func = Arc::new(f.into()) as Arc<AnyFunc>; let host_func = Rc::new(f.into()) as Rc<AnyFunc>;
self.items.push(HostItem::Func { self.items.push(HostItem::Func {
name: name.into(), name: name.into(),
@ -77,7 +77,7 @@ impl<St: 'static> HostModuleBuilder<St> {
f: F, f: F,
) { ) {
let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type(); let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type();
let host_func = Arc::new(f.into()) as Arc<AnyFunc>; let host_func = Rc::new(f.into()) as Rc<AnyFunc>;
self.items.push(HostItem::Func { self.items.push(HostItem::Func {
name: name.into(), name: name.into(),
@ -99,7 +99,7 @@ impl<St: 'static> HostModuleBuilder<St> {
f: F, f: F,
) { ) {
let func_type = Func2::<Cl, St, Ret, P1, P2>::derive_func_type(); let func_type = Func2::<Cl, St, Ret, P1, P2>::derive_func_type();
let host_func = Arc::new(f.into()) as Arc<AnyFunc>; let host_func = Rc::new(f.into()) as Rc<AnyFunc>;
self.items.push(HostItem::Func { self.items.push(HostItem::Func {
name: name.into(), name: name.into(),

View File

@ -1,8 +1,8 @@
use std::rc::Rc;
use std::collections::HashMap; use std::collections::HashMap;
use elements::Module; use elements::Module;
use interpreter::Error; use interpreter::Error;
use interpreter::store::{ModuleId, FuncId, Store, ExternVal}; use interpreter::store::{ModuleId, Store, ExternVal, FuncInstance};
use interpreter::host::HostModule; use interpreter::host::HostModule;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
@ -115,7 +115,7 @@ impl ProgramInstance {
pub fn invoke_func<St: 'static>( pub fn invoke_func<St: 'static>(
&mut self, &mut self,
func: FuncId, func: Rc<FuncInstance>,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
state: &mut St, state: &mut St,
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {

View File

@ -1,12 +1,13 @@
use std::mem; use std::mem;
use std::ops; use std::ops;
use std::rc::Rc;
use std::{u32, usize}; use std::{u32, usize};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::iter::repeat; use std::iter::repeat;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, Local, FunctionType}; use elements::{Opcode, BlockType, Local, FunctionType};
use interpreter::Error; use interpreter::Error;
use interpreter::store::{Store, FuncId, ModuleId, FuncInstance}; use interpreter::store::{Store, ModuleId, FuncInstance};
use interpreter::value::{ use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto,
@ -25,7 +26,7 @@ pub struct FunctionContext {
/// Is context initialized. /// Is context initialized.
pub is_initialized: bool, pub is_initialized: bool,
/// Internal function reference. /// Internal function reference.
pub function: FuncId, pub function: Rc<FuncInstance>,
pub module: ModuleId, pub module: ModuleId,
/// Function return type. /// Function return type.
pub return_type: BlockType, pub return_type: BlockType,
@ -47,7 +48,7 @@ pub enum InstructionOutcome {
/// Branch to given frame. /// Branch to given frame.
Branch(usize), Branch(usize),
/// Execute function call. /// Execute function call.
ExecuteCall(FuncId), ExecuteCall(Rc<FuncInstance>),
/// End current frame. /// End current frame.
End, End,
/// Return from current function block. /// Return from current function block.
@ -59,7 +60,7 @@ enum RunResult {
/// Function has returned (optional) value. /// Function has returned (optional) value.
Return(Option<RuntimeValue>), Return(Option<RuntimeValue>),
/// Function is calling other function. /// Function is calling other function.
NestedCall(FuncId), NestedCall(Rc<FuncInstance>),
} }
impl<'a, St: 'static> Interpreter<'a, St> { impl<'a, St: 'static> Interpreter<'a, St> {
@ -76,11 +77,9 @@ impl<'a, St: 'static> Interpreter<'a, St> {
loop { loop {
let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed"); 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 function_return = {
let func_body = function_ref.resolve(self.store).body(); match function_ref.body() {
match func_body {
Some(function_body) => { Some(function_body) => {
if !function_context.is_initialized() { if !function_context.is_initialized() {
let return_type = function_context.return_type; let return_type = function_context.return_type;
@ -108,8 +107,8 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
}, },
RunResult::NestedCall(nested_func) => { RunResult::NestedCall(nested_func) => {
let func = nested_func.resolve(self.store).clone(); // TODO: check this
match func { match *nested_func {
FuncInstance::Internal { .. } => { FuncInstance::Internal { .. } => {
let nested_context = function_context.nested(self.store, nested_func)?; let nested_context = function_context.nested(self.store, nested_func)?;
function_stack.push_back(function_context); function_stack.push_back(function_context);
@ -452,7 +451,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.resolve(self.store); .resolve(self.store);
let func_ref = table.get(table_func_idx)?; 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 let required_function_type = context
.module() .module()
.type_by_index(self.store, type_idx) .type_by_index(self.store, type_idx)
@ -1019,9 +1018,8 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
impl FunctionContext { impl FunctionContext {
pub fn new<'store>(store: &'store Store, function: FuncId, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self { pub fn new<'store>(store: &'store Store, function: Rc<FuncInstance>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
let func_instance = function.resolve(store); let module = match *function {
let module = match *func_instance {
FuncInstance::Internal { module, .. } => module, 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"), 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<Self, Error> { pub fn nested(&mut self, store: &Store, function: Rc<FuncInstance>) -> Result<Self, Error> {
let (function_locals, module, function_return_type) = { let (function_locals, module, function_return_type) = {
let func_instance = function.resolve(store); let module = match *function {
let module = match *func_instance {
FuncInstance::Internal { module, .. } => module, 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"), 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_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)?; let function_locals = prepare_function_args(function_type, &mut self.value_stack)?;
(function_locals, module, function_return_type) (function_locals, module, function_return_type)

View File

@ -1,7 +1,7 @@
// TODO: remove this // TODO: remove this
#![allow(unused)] #![allow(unused)]
use std::sync::Arc; use std::rc::Rc;
use std::any::Any; use std::any::Any;
use std::fmt; use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
@ -52,7 +52,7 @@ impl ModuleId {
.cloned() .cloned()
} }
pub fn func_by_index(&self, store: &Store, idx: u32) -> Option<FuncId> { pub fn func_by_index(&self, store: &Store, idx: u32) -> Option<Rc<FuncInstance>> {
store.resolve_module(*self) store.resolve_module(*self)
.funcs .funcs
.get(idx as usize) .get(idx as usize)
@ -77,17 +77,6 @@ impl ModuleId {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct HostFuncId(u32); 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)] #[derive(Copy, Clone, Debug)]
pub struct TableId(u32); pub struct TableId(u32);
@ -116,18 +105,18 @@ impl MemoryId {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct GlobalId(u32); pub struct GlobalId(u32);
#[derive(Copy, Clone, Debug)] #[derive(Clone, Debug)]
pub enum ExternVal { pub enum ExternVal {
Func(FuncId), Func(Rc<FuncInstance>),
Table(TableId), Table(TableId),
Memory(MemoryId), Memory(MemoryId),
Global(GlobalId), Global(GlobalId),
} }
impl ExternVal { impl ExternVal {
pub fn as_func(&self) -> Option<FuncId> { pub fn as_func(&self) -> Option<Rc<FuncInstance>> {
match *self { match *self {
ExternVal::Func(func) => Some(func), ExternVal::Func(ref func) => Some(Rc::clone(func)),
_ => None, _ => None,
} }
} }
@ -159,11 +148,11 @@ pub enum FuncInstance {
Internal { Internal {
func_type: TypeId, func_type: TypeId,
module: ModuleId, module: ModuleId,
body: Arc<FuncBody>, body: Rc<FuncBody>,
}, },
Host { Host {
func_type: TypeId, func_type: TypeId,
host_func: Arc<AnyFunc>, host_func: Rc<AnyFunc>,
}, },
} }
@ -189,9 +178,9 @@ impl FuncInstance {
} }
} }
pub fn body(&self) -> Option<Arc<FuncBody>> { pub fn body(&self) -> Option<Rc<FuncBody>> {
match *self { match *self {
FuncInstance::Internal { ref body, .. } => Some(Arc::clone(body)), FuncInstance::Internal { ref body, .. } => Some(Rc::clone(body)),
FuncInstance::Host { .. } => None, FuncInstance::Host { .. } => None,
} }
} }
@ -224,8 +213,8 @@ pub struct ExportInstance {
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ModuleInstance { pub struct ModuleInstance {
types: Vec<TypeId>, types: Vec<TypeId>,
funcs: Vec<FuncId>,
tables: Vec<TableId>, tables: Vec<TableId>,
funcs: Vec<Rc<FuncInstance>>,
memories: Vec<MemoryId>, memories: Vec<MemoryId>,
globals: Vec<GlobalId>, globals: Vec<GlobalId>,
exports: HashMap<String, ExternVal>, exports: HashMap<String, ExternVal>,
@ -274,25 +263,21 @@ impl Store {
TypeId(type_id as u32) 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<FuncInstance> {
let func = FuncInstance::Internal { let func = FuncInstance::Internal {
func_type, func_type,
module, module,
body: Arc::new(body), body: Rc::new(body),
}; };
self.funcs.push(func); Rc::new(func)
let func_id = self.funcs.len() - 1;
FuncId(func_id as u32)
} }
pub fn alloc_host_func(&mut self, func_type: TypeId, host_func: Arc<AnyFunc>) -> FuncId { pub fn alloc_host_func(&mut self, func_type: TypeId, host_func: Rc<AnyFunc>) -> Rc<FuncInstance> {
let func = FuncInstance::Host { let func = FuncInstance::Host {
func_type, func_type,
host_func, host_func,
}; };
self.funcs.push(func); Rc::new(func)
let func_id = self.funcs.len() - 1;
FuncId(func_id as u32)
} }
pub fn alloc_table(&mut self, table_type: &TableType) -> Result<TableId, Error> { pub fn alloc_table(&mut self, table_type: &TableType) -> Result<TableId, Error> {
@ -342,10 +327,10 @@ impl Store {
for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter()) for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter())
{ {
match (import.external(), *extern_val) { match (import.external(), extern_val) {
(&External::Function(fn_type_idx), ExternVal::Func(func)) => { (&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 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 { if expected_fn_type != actual_fn_type {
return Err(Error::Initialization(format!( return Err(Error::Initialization(format!(
"Expected function with type {:?}, but actual type is {:?} for entry {}", "Expected function with type {:?}, but actual type is {:?} for entry {}",
@ -354,17 +339,17 @@ impl Store {
import.field(), 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())?; match_limits(table.resolve(self).limits(), tt.limits())?;
instance.tables.push(table); 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())?; match_limits(memory.resolve(self).limits(), mt.limits())?;
instance.memories.push(memory); instance.memories.push(memory);
} }
(&External::Global(ref gl), ExternVal::Global(global)) => { (&External::Global(ref gl), &ExternVal::Global(global)) => {
// TODO: check globals // TODO: check globals
instance.globals.push(global) instance.globals.push(global)
} }
@ -439,11 +424,11 @@ impl Store {
let field = export.field(); let field = export.field();
let extern_val: ExternVal = match *export.internal() { let extern_val: ExternVal = match *export.internal() {
Internal::Function(idx) => { Internal::Function(idx) => {
let func_id = instance let func = instance
.funcs .funcs
.get(idx as usize) .get(idx as usize)
.expect("Due to validation func should exists"); .expect("Due to validation func should exists");
ExternVal::Func(*func_id) ExternVal::Func(Rc::clone(func))
} }
Internal::Global(idx) => { Internal::Global(idx) => {
let global_id = instance let global_id = instance
@ -504,12 +489,12 @@ impl Store {
.expect("ID should be always valid"); .expect("ID should be always valid");
for (j, func_idx) in element_segment.members().into_iter().enumerate() { for (j, func_idx) in element_segment.members().into_iter().enumerate() {
let func_id = instance let func = instance
.funcs .funcs
.get(*func_idx as usize) .get(*func_idx as usize)
.expect("Due to validation funcs from element segments should exists"); .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() { if let Some(start_fn_idx) = module.start_section() {
let start_func = { let start_func = {
let instance = self.resolve_module(module_id); let instance = self.resolve_module(module_id);
*instance instance
.funcs .funcs
.get(start_fn_idx as usize) .get(start_fn_idx as usize)
.cloned()
.expect("Due to validation start function should exists") .expect("Due to validation start function should exists")
}; };
self.invoke(start_func, vec![], state)?; self.invoke(start_func, vec![], state)?;
@ -556,23 +542,23 @@ impl Store {
pub fn invoke<St: 'static>( pub fn invoke<St: 'static>(
&mut self, &mut self,
func: FuncId, func: Rc<FuncInstance>,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
state: &mut St, state: &mut St,
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {
enum InvokeKind { enum InvokeKind {
Internal(FunctionContext), Internal(FunctionContext),
Host(Arc<AnyFunc>, Vec<RuntimeValue>), Host(Rc<AnyFunc>, Vec<RuntimeValue>),
} }
let result = match *func.resolve(self) { let result = match *func {
FuncInstance::Internal { func_type, .. } => { FuncInstance::Internal { func_type, .. } => {
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT); let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let func_signature = func_type.resolve(self); let func_signature = func_type.resolve(self);
let args = prepare_function_args(&func_signature, &mut args)?; let args = prepare_function_args(&func_signature, &mut args)?;
let context = FunctionContext::new( let context = FunctionContext::new(
self, self,
func, Rc::clone(&func),
DEFAULT_VALUE_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT,
DEFAULT_FRAME_STACK_LIMIT, DEFAULT_FRAME_STACK_LIMIT,
&func_signature, &func_signature,
@ -580,7 +566,7 @@ impl Store {
); );
InvokeKind::Internal(context) 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 { match result {

View File

@ -1,18 +1,19 @@
use std::u32; use std::u32;
use std::fmt; use std::fmt;
use std::rc::Rc;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{TableType, ResizableLimits}; use elements::{TableType, ResizableLimits};
use interpreter::Error; use interpreter::Error;
use interpreter::module::check_limits; use interpreter::module::check_limits;
use interpreter::variable::VariableType; use interpreter::variable::VariableType;
use interpreter::store::FuncId; use interpreter::store::FuncInstance;
/// Table instance. /// Table instance.
pub struct TableInstance { pub struct TableInstance {
/// Table limits. /// Table limits.
limits: ResizableLimits, limits: ResizableLimits,
/// Table memory buffer. /// Table memory buffer.
buffer: RwLock<Vec<Option<FuncId>>>, buffer: RwLock<Vec<Option<Rc<FuncInstance>>>>,
} }
@ -48,10 +49,10 @@ impl TableInstance {
} }
/// Get the specific value in the table /// Get the specific value in the table
pub fn get(&self, offset: u32) -> Result<FuncId, Error> { pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
let buffer = self.buffer.read(); let buffer = self.buffer.read();
let buffer_len = buffer.len(); 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", "trying to read table item with index {} when there are only {} items",
offset, offset,
buffer_len buffer_len
@ -63,7 +64,7 @@ impl TableInstance {
} }
/// Set the table element to the specified function. /// 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<FuncInstance>) -> Result<(), Error> {
let mut buffer = self.buffer.write(); let mut buffer = self.buffer.write();
let buffer_len = buffer.len(); let buffer_len = buffer.len();
let table_elem = buffer.get_mut(offset as usize).ok_or(Error::Table(format!( let table_elem = buffer.get_mut(offset as usize).ok_or(Error::Table(format!(