Replace ModuleIds to Rcs

This commit is contained in:
Sergey Pepyakin
2017-12-13 14:36:06 +01:00
parent 667417177c
commit 9e09508cf5
8 changed files with 180 additions and 182 deletions

View File

@ -3,7 +3,9 @@ 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};
use interpreter::store::{Store, ExternVal, ModuleId, ModuleInstance}; use interpreter::store::{Store, ExternVal, ModuleInstance, GlobalInstance, FuncInstance};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
use interpreter::Error; use interpreter::Error;
@ -149,27 +151,29 @@ pub struct HostModule {
} }
impl HostModule { impl HostModule {
pub(crate) fn allocate(self, store: &mut Store) -> Result<ModuleId, Error> { pub(crate) fn allocate(self) -> Result<Rc<ModuleInstance>, Error> {
let mut exports = HashMap::new(); let mut exports = HashMap::new();
for item in self.items { for item in self.items {
match item { match item {
HostItem::Func { name, func_type, host_func } => { HostItem::Func { name, func_type, host_func } => {
let type_id = store.alloc_func_type(func_type); let func = FuncInstance::Host {
let func_id = store.alloc_host_func(type_id, host_func); func_type: Rc::new(func_type),
exports.insert(name, ExternVal::Func(func_id)); host_func: host_func,
};
exports.insert(name, ExternVal::Func(Rc::new(func)));
}, },
HostItem::Global { name, global_type, init_val } => { HostItem::Global { name, global_type, init_val } => {
let global_id = store.alloc_global(global_type, init_val); let global = GlobalInstance::new(init_val, global_type.is_mutable());
exports.insert(name, ExternVal::Global(global_id)); exports.insert(name, ExternVal::Global(Rc::new(global)));
}, },
HostItem::Memory { name, memory_type } => { HostItem::Memory { name, memory_type } => {
let memory_id = store.alloc_memory(&memory_type)?; let memory = MemoryInstance::new(&memory_type)?;
exports.insert(name, ExternVal::Memory(memory_id)); exports.insert(name, ExternVal::Memory(Rc::new(memory)));
}, },
HostItem::Table { name, table_type } => { HostItem::Table { name, table_type } => {
let table_id = store.alloc_table(&table_type)?; let table = TableInstance::new(&table_type)?;
exports.insert(name, ExternVal::Table(table_id)); exports.insert(name, ExternVal::Table(Rc::new(table)));
} }
HostItem::ExternVal { name, extern_val } => { HostItem::ExternVal { name, extern_val } => {
exports.insert(name, extern_val); exports.insert(name, extern_val);
@ -178,9 +182,7 @@ impl HostModule {
} }
let host_module_instance = ModuleInstance::with_exports(exports); let host_module_instance = ModuleInstance::with_exports(exports);
let module_id = store.add_module_instance(host_module_instance); Ok(Rc::new(host_module_instance))
Ok(module_id)
} }
} }

View File

@ -151,6 +151,3 @@ pub use self::program::ProgramInstance;
pub use self::value::RuntimeValue; pub use self::value::RuntimeValue;
pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue}; pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg}; pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg};
// TODO: All exports
pub use self::store::ModuleId;

View File

@ -2,14 +2,14 @@ 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, Store, ExternVal, FuncInstance}; use interpreter::store::{Store, ExternVal, FuncInstance, ModuleInstance};
use interpreter::host::HostModule; use interpreter::host::HostModule;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
/// Program instance. Program is a set of instantiated modules. /// Program instance. Program is a set of instantiated modules.
pub struct ProgramInstance { pub struct ProgramInstance {
store: Store, store: Store,
modules: HashMap<String, ModuleId>, modules: HashMap<String, Rc<ModuleInstance>>,
} }
impl ProgramInstance { impl ProgramInstance {
@ -27,12 +27,12 @@ impl ProgramInstance {
name: &str, name: &str,
module: Module, module: Module,
state: &mut St, state: &mut St,
) -> Result<ModuleId, Error> { ) -> Result<Rc<ModuleInstance>, Error> {
let mut extern_vals = Vec::new(); let mut extern_vals = Vec::new();
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) { for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
let module = self.modules[import_entry.module()]; let module = self.modules.get(import_entry.module()).ok_or_else(|| Error::Program(format!("Module {} not found", import_entry.module())))?;
let extern_val = module let extern_val = module
.export_by_name(&self.store, import_entry.field()) .export_by_name(import_entry.field())
.ok_or_else(|| { .ok_or_else(|| {
Error::Program(format!( Error::Program(format!(
"Module {} doesn't have export {}", "Module {} doesn't have export {}",
@ -43,23 +43,23 @@ impl ProgramInstance {
extern_vals.push(extern_val); extern_vals.push(extern_val);
} }
let module_id = self.store.instantiate_module(&module, &extern_vals, state)?; let module_instance = self.store.instantiate_module(&module, &extern_vals, state)?;
self.modules.insert(name.to_owned(), module_id); self.modules.insert(name.to_owned(), Rc::clone(&module_instance));
Ok(module_id) Ok(module_instance)
} }
pub fn add_host_module( pub fn add_host_module(
&mut self, &mut self,
name: &str, name: &str,
host_module: HostModule, host_module: HostModule,
) -> Result<ModuleId, Error> { ) -> Result<Rc<ModuleInstance>, Error> {
let module_id = host_module.allocate(&mut self.store)?; let module_instance = host_module.allocate()?;
self.modules.insert(name.to_owned(), module_id); self.modules.insert(name.to_owned(), Rc::clone(&module_instance));
Ok(module_id) Ok(module_instance)
} }
pub fn insert_loaded_module(&mut self, name: &str, module: ModuleId) { pub fn insert_loaded_module(&mut self, name: &str, module: Rc<ModuleInstance>) {
self.modules.insert(name.to_owned(), module); self.modules.insert(name.to_owned(), module);
} }
@ -74,7 +74,7 @@ impl ProgramInstance {
Error::Program(format!("Module {} not found", module_name)) Error::Program(format!("Module {} not found", module_name))
})?; })?;
let extern_val = module_id let extern_val = module_id
.export_by_name(&self.store, func_name) .export_by_name(func_name)
.ok_or_else(|| { .ok_or_else(|| {
Error::Program(format!( Error::Program(format!(
"Module {} doesn't have export {}", "Module {} doesn't have export {}",
@ -107,7 +107,7 @@ impl ProgramInstance {
let module_id = self.modules.get(module_name).cloned().ok_or_else(|| { let module_id = self.modules.get(module_name).cloned().ok_or_else(|| {
Error::Program(format!("Module {} not found", module_name)) Error::Program(format!("Module {} not found", module_name))
})?; })?;
let func_id = module_id.func_by_index(&self.store, func_idx).ok_or_else(|| { let func_id = module_id.func_by_index(func_idx).ok_or_else(|| {
Error::Program(format!("Module doesn't contain function at index {}", func_idx)) Error::Program(format!("Module doesn't contain function at index {}", func_idx))
})?; })?;
self.invoke_func(func_id, args, state) self.invoke_func(func_id, args, state)
@ -126,7 +126,7 @@ impl ProgramInstance {
&self.store &self.store
} }
pub fn module(&self, name: &str) -> Option<ModuleId> { pub fn module(&self, name: &str) -> Option<Rc<ModuleInstance>> {
self.modules.get(name).cloned() self.modules.get(name).cloned()
} }
} }

View File

@ -7,7 +7,7 @@ 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, ModuleId, FuncInstance}; use interpreter::store::{Store, FuncInstance, ModuleInstance};
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,
@ -27,7 +27,7 @@ pub struct FunctionContext {
pub is_initialized: bool, pub is_initialized: bool,
/// Internal function reference. /// Internal function reference.
pub function: Rc<FuncInstance>, pub function: Rc<FuncInstance>,
pub module: ModuleId, pub module: Rc<ModuleInstance>,
/// Function return type. /// Function return type.
pub return_type: BlockType, pub return_type: BlockType,
/// Local variables. /// Local variables.
@ -433,7 +433,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome, Error> {
let func = context let func = context
.module() .module()
.func_by_index(self.store, func_idx) .func_by_index(func_idx)
.expect("Due to validation func should exists"); .expect("Due to validation func should exists");
Ok(InstructionOutcome::ExecuteCall(func)) Ok(InstructionOutcome::ExecuteCall(func))
} }
@ -446,14 +446,14 @@ impl<'a, St: 'static> Interpreter<'a, St> {
let table_func_idx: u32 = context.value_stack_mut().pop_as()?; let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
let table = context let table = context
.module() .module()
.table_by_index(self.store, DEFAULT_TABLE_INDEX) .table_by_index(DEFAULT_TABLE_INDEX)
.expect("Due to validation table should exists"); .expect("Due to validation table should exists");
let func_ref = table.get(table_func_idx)?; let func_ref = table.get(table_func_idx)?;
let actual_function_type = func_ref.func_type(); let actual_function_type = func_ref.func_type();
let required_function_type = context let required_function_type = context
.module() .module()
.type_by_index(self.store, type_idx) .type_by_index(type_idx)
.expect("Due to validation type should exists"); .expect("Due to validation type should exists");
if required_function_type != actual_function_type { if required_function_type != actual_function_type {
@ -518,7 +518,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome, Error> {
let global = context let global = context
.module() .module()
.global_by_index(&self.store, index) .global_by_index(index)
.expect("Due to validation global should exists"); .expect("Due to validation global should exists");
let val = global.get(); let val = global.get();
context.value_stack_mut().push(val)?; context.value_stack_mut().push(val)?;
@ -534,7 +534,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
let global = context let global = context
.module() .module()
.global_by_index(&self.store, index) .global_by_index(index)
.expect("Due to validation global should exists"); .expect("Due to validation global should exists");
global.set(val)?; global.set(val)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
@ -544,7 +544,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
where RuntimeValue: From<T>, T: LittleEndianConvert { where RuntimeValue: From<T>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
let b = m.get(address, mem::size_of::<T>())?; let b = m.get(address, mem::size_of::<T>())?;
let n = T::from_little_endian(b)?; let n = T::from_little_endian(b)?;
@ -556,7 +556,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert { where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
let b = m.get(address, mem::size_of::<T>())?; let b = m.get(address, mem::size_of::<T>())?;
let v = T::from_little_endian(b)?; let v = T::from_little_endian(b)?;
@ -577,7 +577,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
m.set(address, &stack_value)?; m.set(address, &stack_value)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
@ -602,7 +602,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
let stack_value = stack_value.wrap_into().into_little_endian(); let stack_value = stack_value.wrap_into().into_little_endian();
let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?; let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
m.set(address, &stack_value)?; m.set(address, &stack_value)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
@ -610,7 +610,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
let s = m.size(); let s = m.size();
context context
@ -622,7 +622,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
let pages: u32 = context.value_stack_mut().pop_as()?; let pages: u32 = context.value_stack_mut().pop_as()?;
let m = context.module() let m = context.module()
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
let m = m.grow(pages)?; let m = m.grow(pages)?;
context context
@ -1012,7 +1012,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
impl FunctionContext { impl FunctionContext {
pub fn new<'store>(function: Rc<FuncInstance>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self { pub fn new<'store>(function: Rc<FuncInstance>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
let module = match *function { let module = match *function {
FuncInstance::Internal { module, .. } => module, 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"), FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
}; };
FunctionContext { FunctionContext {
@ -1030,7 +1030,7 @@ impl FunctionContext {
pub fn nested(&mut self, function: Rc<FuncInstance>) -> Result<Self, Error> { pub fn nested(&mut self, function: Rc<FuncInstance>) -> Result<Self, Error> {
let (function_locals, module, function_return_type) = { let (function_locals, module, function_return_type) = {
let module = match *function { let module = match *function {
FuncInstance::Internal { module, .. } => module, 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"), 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 = function.func_type(); let function_type = function.func_type();
@ -1066,8 +1066,8 @@ impl FunctionContext {
self.locals.extend(locals); self.locals.extend(locals);
} }
pub fn module(&self) -> ModuleId { pub fn module(&self) -> Rc<ModuleInstance> {
self.module Rc::clone(&self.module)
} }
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome, Error> { pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome, Error> {

View File

@ -2,7 +2,7 @@
#![allow(unused)] #![allow(unused)]
use std::rc::Rc; use std::rc::Rc;
use std::cell::Cell; use std::cell::{Cell, RefCell};
use std::any::Any; use std::any::Any;
use std::fmt; use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
@ -17,53 +17,6 @@ use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDE
DEFAULT_VALUE_STACK_LIMIT}; DEFAULT_VALUE_STACK_LIMIT};
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
#[derive(Copy, Clone, Debug)]
pub struct ModuleId(u32);
impl ModuleId {
pub fn memory_by_index(&self, store: &Store, idx: u32) -> Option<Rc<MemoryInstance>> {
store.resolve_module(*self)
.memories
.get(idx as usize)
.cloned()
}
pub fn table_by_index(&self, store: &Store, idx: u32) -> Option<Rc<TableInstance>> {
store.resolve_module(*self)
.tables
.get(idx as usize)
.cloned()
}
pub fn global_by_index(&self, store: &Store, idx: u32) -> Option<Rc<GlobalInstance>> {
store.resolve_module(*self)
.globals
.get(idx as usize)
.cloned()
}
pub fn func_by_index(&self, store: &Store, idx: u32) -> Option<Rc<FuncInstance>> {
store.resolve_module(*self)
.funcs
.get(idx as usize)
.cloned()
}
pub fn type_by_index(&self, store: &Store, idx: u32) -> Option<Rc<FunctionType>> {
store.resolve_module(*self)
.types
.get(idx as usize)
.cloned()
}
pub fn export_by_name(&self, store: &Store, name: &str) -> Option<ExternVal> {
store.resolve_module(*self)
.exports
.get(name)
.cloned()
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ExternVal { pub enum ExternVal {
Func(Rc<FuncInstance>), Func(Rc<FuncInstance>),
@ -106,7 +59,7 @@ impl ExternVal {
pub enum FuncInstance { pub enum FuncInstance {
Internal { Internal {
func_type: Rc<FunctionType>, func_type: Rc<FunctionType>,
module: ModuleId, module: Rc<ModuleInstance>,
body: Rc<FuncBody>, body: Rc<FuncBody>,
}, },
Host { Host {
@ -118,7 +71,7 @@ pub enum FuncInstance {
impl fmt::Debug for FuncInstance { impl fmt::Debug for FuncInstance {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&FuncInstance::Internal { ref func_type, module, .. } => { &FuncInstance::Internal { ref func_type, ref module, .. } => {
write!(f, "Internal {{ type={:?}, module={:?} }}", func_type, module) write!(f, "Internal {{ type={:?}, module={:?} }}", func_type, module)
}, },
&FuncInstance::Host { ref func_type, .. } => { &FuncInstance::Host { ref func_type, .. } => {
@ -159,7 +112,7 @@ pub struct GlobalInstance {
} }
impl GlobalInstance { impl GlobalInstance {
fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance { pub fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance {
GlobalInstance { GlobalInstance {
val: Cell::new(val), val: Cell::new(val),
mutable mutable
@ -187,12 +140,12 @@ pub struct ExportInstance {
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ModuleInstance { pub struct ModuleInstance {
types: Vec<Rc<FunctionType>>, types: RefCell<Vec<Rc<FunctionType>>>,
tables: Vec<Rc<TableInstance>>, tables: RefCell<Vec<Rc<TableInstance>>>,
funcs: Vec<Rc<FuncInstance>>, funcs: RefCell<Vec<Rc<FuncInstance>>>,
memories: Vec<Rc<MemoryInstance>>, memories: RefCell<Vec<Rc<MemoryInstance>>>,
globals: Vec<Rc<GlobalInstance>>, globals: RefCell<Vec<Rc<GlobalInstance>>>,
exports: HashMap<String, ExternVal>, exports: RefCell<HashMap<String, ExternVal>>,
} }
impl ModuleInstance { impl ModuleInstance {
@ -202,9 +155,84 @@ impl ModuleInstance {
pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance { pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance {
ModuleInstance { ModuleInstance {
exports, ..Default::default() exports: RefCell::new(exports), ..Default::default()
} }
} }
pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> {
self
.memories
.borrow()
.get(idx as usize)
.cloned()
}
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance>> {
self
.tables
.borrow()
.get(idx as usize)
.cloned()
}
pub fn global_by_index(&self, idx: u32) -> Option<Rc<GlobalInstance>> {
self
.globals
.borrow()
.get(idx as usize)
.cloned()
}
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance>> {
self
.funcs
.borrow()
.get(idx as usize)
.cloned()
}
pub fn type_by_index(&self, idx: u32) -> Option<Rc<FunctionType>> {
self
.types
.borrow()
.get(idx as usize)
.cloned()
}
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
self
.exports
.borrow()
.get(name)
.cloned()
}
fn push_func(&self, func: Rc<FuncInstance>) {
self.funcs.borrow_mut().push(func);
}
fn push_type(&self, func_type: Rc<FunctionType>) {
self.types.borrow_mut().push(func_type)
}
fn push_memory(&self, memory: Rc<MemoryInstance>) {
self.memories.borrow_mut().push(memory)
}
fn push_table(&self, table: Rc<TableInstance>) {
self.tables.borrow_mut().push(table)
}
fn push_global(&self, global: Rc<GlobalInstance>) {
self.globals.borrow_mut().push(global)
}
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) {
self
.exports
.borrow_mut()
.insert(name.into(), extern_val);
}
} }
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -220,20 +248,14 @@ impl Store {
Store::default() Store::default()
} }
fn resolve_module(&self, id: ModuleId) -> &ModuleInstance {
self.modules
.get(id.0 as usize)
.expect("ID should always be a valid index")
}
pub fn alloc_func_type(&mut self, func_type: FunctionType) -> Rc<FunctionType> { pub fn alloc_func_type(&mut self, func_type: FunctionType) -> Rc<FunctionType> {
Rc::new(func_type) Rc::new(func_type)
} }
pub fn alloc_func(&mut self, module: ModuleId, func_type: Rc<FunctionType>, body: FuncBody) -> Rc<FuncInstance> { pub fn alloc_func(&mut self, module: &Rc<ModuleInstance>, func_type: Rc<FunctionType>, body: FuncBody) -> Rc<FuncInstance> {
let func = FuncInstance::Internal { let func = FuncInstance::Internal {
func_type, func_type,
module, module: Rc::clone(module),
body: Rc::new(body), body: Rc::new(body),
}; };
Rc::new(func) Rc::new(func)
@ -266,8 +288,7 @@ impl Store {
&mut self, &mut self,
module: &Module, module: &Module,
extern_vals: &[ExternVal], extern_vals: &[ExternVal],
instance: &mut ModuleInstance, instance: &Rc<ModuleInstance>,
module_id: ModuleId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut aux_data = validate_module(module)?; let mut aux_data = validate_module(module)?;
@ -277,7 +298,7 @@ impl Store {
.unwrap_or(&[]) .unwrap_or(&[])
{ {
let type_id = self.alloc_func_type(ty.clone()); let type_id = self.alloc_func_type(ty.clone());
instance.types.push(type_id); instance.push_type(type_id);
} }
{ {
@ -290,9 +311,9 @@ impl Store {
{ {
match (import.external(), extern_val) { match (import.external(), extern_val) {
(&External::Function(fn_type_idx), &ExternVal::Func(ref 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"); let expected_fn_type = instance.type_by_index(fn_type_idx).expect("Due to validation function type should exists");
let actual_fn_type = func.func_type(); let actual_fn_type = func.func_type();
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 {}",
expected_fn_type, expected_fn_type,
@ -300,19 +321,19 @@ impl Store {
import.field(), import.field(),
))); )));
} }
instance.funcs.push(Rc::clone(func)) instance.push_func(Rc::clone(func))
} }
(&External::Table(ref tt), &ExternVal::Table(ref table)) => { (&External::Table(ref tt), &ExternVal::Table(ref table)) => {
match_limits(table.limits(), tt.limits())?; match_limits(table.limits(), tt.limits())?;
instance.tables.push(Rc::clone(table)); instance.push_table(Rc::clone(table));
} }
(&External::Memory(ref mt), &ExternVal::Memory(ref memory)) => { (&External::Memory(ref mt), &ExternVal::Memory(ref memory)) => {
match_limits(memory.limits(), mt.limits())?; match_limits(memory.limits(), mt.limits())?;
instance.memories.push(Rc::clone(memory)); instance.push_memory(Rc::clone(memory));
} }
(&External::Global(ref gl), &ExternVal::Global(ref global)) => { (&External::Global(ref gl), &ExternVal::Global(ref global)) => {
// TODO: check globals // TODO: check globals
instance.globals.push(Rc::clone(global)) instance.push_global(Rc::clone(global))
} }
(expected_import, actual_extern_val) => { (expected_import, actual_extern_val) => {
return Err(Error::Initialization(format!( return Err(Error::Initialization(format!(
@ -339,7 +360,7 @@ impl Store {
for (index, (ty, body)) in for (index, (ty, body)) in
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate() Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
{ {
let func_type = Rc::clone(&instance.types[ty.type_ref() as usize]); let func_type = instance.type_by_index(ty.type_ref()).expect("Due to validation type should exists");
let labels = aux_data.labels.remove(&index).expect( let labels = aux_data.labels.remove(&index).expect(
"At func validation time labels are collected; Collected labels are added by index; qed", "At func validation time labels are collected; Collected labels are added by index; qed",
); );
@ -348,33 +369,33 @@ impl Store {
opcodes: body.code().clone(), opcodes: body.code().clone(),
labels: labels, labels: labels,
}; };
let func_id = self.alloc_func(module_id, func_type, func_body); let func_instance = self.alloc_func(instance, func_type, func_body);
instance.funcs.push(func_id); instance.push_func(func_instance);
} }
} }
for table in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) { for table in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) {
let table_id = self.alloc_table(table)?; let table_id = self.alloc_table(table)?;
instance.tables.push(table_id); instance.push_table(table_id);
} }
for memory in module for memory_type in module
.memory_section() .memory_section()
.map(|ms| ms.entries()) .map(|ms| ms.entries())
.unwrap_or(&[]) .unwrap_or(&[])
{ {
let memory_id = self.alloc_memory(memory)?; let memory = self.alloc_memory(memory_type)?;
instance.memories.push(memory_id); instance.push_memory(memory);
} }
for global in module for global_entry in module
.global_section() .global_section()
.map(|gs| gs.entries()) .map(|gs| gs.entries())
.unwrap_or(&[]) .unwrap_or(&[])
{ {
let init_val = eval_init_expr(global.init_expr(), instance, self); let init_val = eval_init_expr(global_entry.init_expr(), &*instance, self);
let global_id = self.alloc_global(global.global_type().clone(), init_val); let global = self.alloc_global(global_entry.global_type().clone(), init_val);
instance.globals.push(global_id); instance.push_global(global);
} }
for export in module for export in module
@ -386,34 +407,30 @@ impl Store {
let extern_val: ExternVal = match *export.internal() { let extern_val: ExternVal = match *export.internal() {
Internal::Function(idx) => { Internal::Function(idx) => {
let func = instance let func = instance
.funcs .func_by_index(idx)
.get(idx as usize)
.expect("Due to validation func should exists"); .expect("Due to validation func should exists");
ExternVal::Func(Rc::clone(func)) ExternVal::Func(func)
} }
Internal::Global(idx) => { Internal::Global(idx) => {
let global = instance let global = instance
.globals .global_by_index(idx)
.get(idx as usize)
.expect("Due to validation global should exists"); .expect("Due to validation global should exists");
ExternVal::Global(Rc::clone(global)) ExternVal::Global(global)
} }
Internal::Memory(idx) => { Internal::Memory(idx) => {
let memory = instance let memory = instance
.memories .memory_by_index(idx)
.get(idx as usize)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
ExternVal::Memory(Rc::clone(memory)) ExternVal::Memory(memory)
} }
Internal::Table(idx) => { Internal::Table(idx) => {
let table = instance let table = instance
.tables .table_by_index(idx)
.get(idx as usize)
.expect("Due to validation table should exists"); .expect("Due to validation table should exists");
ExternVal::Table(Rc::clone(table)) ExternVal::Table(table)
} }
}; };
instance.exports.insert(field.into(), extern_val); instance.insert_export(field, extern_val);
} }
Ok(()) Ok(())
@ -424,12 +441,10 @@ impl Store {
module: &Module, module: &Module,
extern_vals: &[ExternVal], extern_vals: &[ExternVal],
state: &mut St, state: &mut St,
) -> Result<ModuleId, Error> { ) -> Result<Rc<ModuleInstance>, Error> {
let mut instance = ModuleInstance::new(); let mut instance = Rc::new(ModuleInstance::new());
// Reserve the index of the module, but not yet push the module.
let module_id = ModuleId((self.modules.len()) as u32);
self.alloc_module_internal(module, extern_vals, &mut instance, module_id)?; self.alloc_module_internal(module, extern_vals, &instance)?;
for element_segment in module for element_segment in module
.elements_section() .elements_section()
@ -442,16 +457,14 @@ impl Store {
}; };
let table_inst = instance let table_inst = instance
.tables .table_by_index(DEFAULT_TABLE_INDEX)
.get(DEFAULT_TABLE_INDEX as usize)
.expect("Due to validation default table should exists"); .expect("Due to validation default table should exists");
for (j, func_idx) in element_segment.members().into_iter().enumerate() { for (j, func_idx) in element_segment.members().into_iter().enumerate() {
let func = instance let func = instance
.funcs .func_by_index(*func_idx)
.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, Rc::clone(func)); table_inst.set(offset_val + j as u32, func);
} }
} }
@ -462,35 +475,22 @@ impl Store {
}; };
let memory_inst = instance let memory_inst = instance
.memories .memory_by_index(DEFAULT_MEMORY_INDEX)
.get(DEFAULT_MEMORY_INDEX as usize)
.expect("Due to validation default memory should exists"); .expect("Due to validation default memory should exists");
memory_inst.set(offset_val, data_segment.value())?; memory_inst.set(offset_val, data_segment.value())?;
} }
// Finally push instance to it's place
self.modules.push(instance);
// And run module's start function, if any // And run module's start function, if any
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);
instance instance
.funcs .func_by_index(start_fn_idx)
.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)?;
} }
Ok(module_id) Ok(instance)
}
pub fn add_module_instance(&mut self, instance: ModuleInstance) -> ModuleId {
self.modules.push(instance);
let module_id = self.modules.len() - 1;
ModuleId(module_id as u32)
} }
pub fn invoke<St: 'static>( pub fn invoke<St: 'static>(
@ -545,8 +545,7 @@ fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance, store: &Store)
Opcode::F64Const(v) => RuntimeValue::decode_f64(v), Opcode::F64Const(v) => RuntimeValue::decode_f64(v),
Opcode::GetGlobal(idx) => { Opcode::GetGlobal(idx) => {
let global = module let global = module
.globals .global_by_index(idx)
.get(idx as usize)
.expect("Due to validation global should exists in module"); .expect("Due to validation global should exists in module");
global.get() global.get()
} }

View File

@ -156,7 +156,7 @@ fn native_env_function() {
let mut program = program_with_default_env(); let mut program = program_with_default_env();
let env_host_module = build_env_module(); let env_host_module = build_env_module();
let env_module = program.add_host_module("env", env_host_module).unwrap(); let env_module = program.add_host_module("env", env_host_module).unwrap();
let env_memory = env_module.export_by_name(program.store(), "memory").unwrap().as_memory().unwrap(); let env_memory = env_module.export_by_name("memory").unwrap().as_memory().unwrap();
let mut state = FunctionExecutor { let mut state = FunctionExecutor {
memory: env_memory, memory: env_memory,
@ -255,7 +255,7 @@ fn native_custom_error() {
let mut program = program_with_default_env(); let mut program = program_with_default_env();
let env_host_module = build_env_module(); let env_host_module = build_env_module();
let env_module = program.add_host_module("env", env_host_module).unwrap(); let env_module = program.add_host_module("env", env_host_module).unwrap();
let env_memory = env_module.export_by_name(program.store(), "memory").unwrap().as_memory().unwrap(); let env_memory = env_module.export_by_name("memory").unwrap().as_memory().unwrap();
let mut state = FunctionExecutor { let mut state = FunctionExecutor {
memory: env_memory, memory: env_memory,

View File

@ -464,11 +464,11 @@ fn return_void() {
let module = program.add_module("main", module, &mut ()).unwrap(); let module = program.add_module("main", module, &mut ()).unwrap();
program.invoke_index("main", 0, vec![RuntimeValue::I32(0)], &mut ()).unwrap(); program.invoke_index("main", 0, vec![RuntimeValue::I32(0)], &mut ()).unwrap();
let memory = module.memory_by_index(program.store(), 0).unwrap(); let memory = module.memory_by_index(0).unwrap();
assert_eq!(memory.get(0, 4).unwrap(), vec![0, 0, 0, 0]); assert_eq!(memory.get(0, 4).unwrap(), vec![0, 0, 0, 0]);
program.invoke_index("main", 0, vec![RuntimeValue::I32(1)], &mut ()).unwrap(); program.invoke_index("main", 0, vec![RuntimeValue::I32(1)], &mut ()).unwrap();
let memory = module.memory_by_index(program.store(), 0).unwrap(); let memory = module.memory_by_index(0).unwrap();
assert_eq!(memory.get(0, 4).unwrap(), vec![1, 0, 0, 0]); assert_eq!(memory.get(0, 4).unwrap(), vec![1, 0, 0, 0]);
} }

View File

@ -47,7 +47,7 @@ fn interpreter_accumulate_u8() {
.expect("Failed to initialize module"); .expect("Failed to initialize module");
let env_module = program.module("env").unwrap(); let env_module = program.module("env").unwrap();
let env_memory = env_module.memory_by_index(program.store(), 0).unwrap(); let env_memory = env_module.memory_by_index(0).unwrap();
// Place the octet-sequence at index 0 in linear memory // Place the octet-sequence at index 0 in linear memory
let offset: u32 = 0; let offset: u32 = 0;