mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-22 19:21:59 +00:00
Replace ModuleIds to Rcs
This commit is contained in:
@ -3,7 +3,9 @@ use std::rc::Rc;
|
||||
use std::marker::PhantomData;
|
||||
use std::collections::HashMap;
|
||||
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::Error;
|
||||
|
||||
@ -149,27 +151,29 @@ pub struct 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();
|
||||
|
||||
for item in self.items {
|
||||
match item {
|
||||
HostItem::Func { name, func_type, host_func } => {
|
||||
let type_id = store.alloc_func_type(func_type);
|
||||
let func_id = store.alloc_host_func(type_id, host_func);
|
||||
exports.insert(name, ExternVal::Func(func_id));
|
||||
let func = FuncInstance::Host {
|
||||
func_type: Rc::new(func_type),
|
||||
host_func: host_func,
|
||||
};
|
||||
exports.insert(name, ExternVal::Func(Rc::new(func)));
|
||||
},
|
||||
HostItem::Global { name, global_type, init_val } => {
|
||||
let global_id = store.alloc_global(global_type, init_val);
|
||||
exports.insert(name, ExternVal::Global(global_id));
|
||||
let global = GlobalInstance::new(init_val, global_type.is_mutable());
|
||||
exports.insert(name, ExternVal::Global(Rc::new(global)));
|
||||
},
|
||||
HostItem::Memory { name, memory_type } => {
|
||||
let memory_id = store.alloc_memory(&memory_type)?;
|
||||
exports.insert(name, ExternVal::Memory(memory_id));
|
||||
let memory = MemoryInstance::new(&memory_type)?;
|
||||
exports.insert(name, ExternVal::Memory(Rc::new(memory)));
|
||||
},
|
||||
HostItem::Table { name, table_type } => {
|
||||
let table_id = store.alloc_table(&table_type)?;
|
||||
exports.insert(name, ExternVal::Table(table_id));
|
||||
let table = TableInstance::new(&table_type)?;
|
||||
exports.insert(name, ExternVal::Table(Rc::new(table)));
|
||||
}
|
||||
HostItem::ExternVal { name, extern_val } => {
|
||||
exports.insert(name, extern_val);
|
||||
@ -178,9 +182,7 @@ impl HostModule {
|
||||
}
|
||||
|
||||
let host_module_instance = ModuleInstance::with_exports(exports);
|
||||
let module_id = store.add_module_instance(host_module_instance);
|
||||
|
||||
Ok(module_id)
|
||||
Ok(Rc::new(host_module_instance))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,3 @@ pub use self::program::ProgramInstance;
|
||||
pub use self::value::RuntimeValue;
|
||||
pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
|
||||
pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg};
|
||||
|
||||
// TODO: All exports
|
||||
pub use self::store::ModuleId;
|
||||
|
@ -2,14 +2,14 @@ use std::rc::Rc;
|
||||
use std::collections::HashMap;
|
||||
use elements::Module;
|
||||
use interpreter::Error;
|
||||
use interpreter::store::{ModuleId, Store, ExternVal, FuncInstance};
|
||||
use interpreter::store::{Store, ExternVal, FuncInstance, ModuleInstance};
|
||||
use interpreter::host::HostModule;
|
||||
use interpreter::value::RuntimeValue;
|
||||
|
||||
/// Program instance. Program is a set of instantiated modules.
|
||||
pub struct ProgramInstance {
|
||||
store: Store,
|
||||
modules: HashMap<String, ModuleId>,
|
||||
modules: HashMap<String, Rc<ModuleInstance>>,
|
||||
}
|
||||
|
||||
impl ProgramInstance {
|
||||
@ -27,12 +27,12 @@ impl ProgramInstance {
|
||||
name: &str,
|
||||
module: Module,
|
||||
state: &mut St,
|
||||
) -> Result<ModuleId, Error> {
|
||||
) -> Result<Rc<ModuleInstance>, Error> {
|
||||
let mut extern_vals = Vec::new();
|
||||
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
|
||||
.export_by_name(&self.store, import_entry.field())
|
||||
.export_by_name(import_entry.field())
|
||||
.ok_or_else(|| {
|
||||
Error::Program(format!(
|
||||
"Module {} doesn't have export {}",
|
||||
@ -43,23 +43,23 @@ impl ProgramInstance {
|
||||
extern_vals.push(extern_val);
|
||||
}
|
||||
|
||||
let module_id = self.store.instantiate_module(&module, &extern_vals, state)?;
|
||||
self.modules.insert(name.to_owned(), module_id);
|
||||
let module_instance = self.store.instantiate_module(&module, &extern_vals, state)?;
|
||||
self.modules.insert(name.to_owned(), Rc::clone(&module_instance));
|
||||
|
||||
Ok(module_id)
|
||||
Ok(module_instance)
|
||||
}
|
||||
|
||||
pub fn add_host_module(
|
||||
&mut self,
|
||||
name: &str,
|
||||
host_module: HostModule,
|
||||
) -> Result<ModuleId, Error> {
|
||||
let module_id = host_module.allocate(&mut self.store)?;
|
||||
self.modules.insert(name.to_owned(), module_id);
|
||||
Ok(module_id)
|
||||
) -> Result<Rc<ModuleInstance>, Error> {
|
||||
let module_instance = host_module.allocate()?;
|
||||
self.modules.insert(name.to_owned(), Rc::clone(&module_instance));
|
||||
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);
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ impl ProgramInstance {
|
||||
Error::Program(format!("Module {} not found", module_name))
|
||||
})?;
|
||||
let extern_val = module_id
|
||||
.export_by_name(&self.store, func_name)
|
||||
.export_by_name(func_name)
|
||||
.ok_or_else(|| {
|
||||
Error::Program(format!(
|
||||
"Module {} doesn't have export {}",
|
||||
@ -107,7 +107,7 @@ impl ProgramInstance {
|
||||
let module_id = self.modules.get(module_name).cloned().ok_or_else(|| {
|
||||
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))
|
||||
})?;
|
||||
self.invoke_func(func_id, args, state)
|
||||
@ -126,7 +126,7 @@ impl ProgramInstance {
|
||||
&self.store
|
||||
}
|
||||
|
||||
pub fn module(&self, name: &str) -> Option<ModuleId> {
|
||||
pub fn module(&self, name: &str) -> Option<Rc<ModuleInstance>> {
|
||||
self.modules.get(name).cloned()
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use std::iter::repeat;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use elements::{Opcode, BlockType, Local, FunctionType};
|
||||
use interpreter::Error;
|
||||
use interpreter::store::{Store, ModuleId, FuncInstance};
|
||||
use interpreter::store::{Store, FuncInstance, ModuleInstance};
|
||||
use interpreter::value::{
|
||||
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
|
||||
ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto,
|
||||
@ -27,7 +27,7 @@ pub struct FunctionContext {
|
||||
pub is_initialized: bool,
|
||||
/// Internal function reference.
|
||||
pub function: Rc<FuncInstance>,
|
||||
pub module: ModuleId,
|
||||
pub module: Rc<ModuleInstance>,
|
||||
/// Function return type.
|
||||
pub return_type: BlockType,
|
||||
/// Local variables.
|
||||
@ -433,7 +433,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
) -> Result<InstructionOutcome, Error> {
|
||||
let func = context
|
||||
.module()
|
||||
.func_by_index(self.store, func_idx)
|
||||
.func_by_index(func_idx)
|
||||
.expect("Due to validation func should exists");
|
||||
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 = context
|
||||
.module()
|
||||
.table_by_index(self.store, DEFAULT_TABLE_INDEX)
|
||||
.table_by_index(DEFAULT_TABLE_INDEX)
|
||||
.expect("Due to validation table should exists");
|
||||
let func_ref = table.get(table_func_idx)?;
|
||||
|
||||
let actual_function_type = func_ref.func_type();
|
||||
let required_function_type = context
|
||||
.module()
|
||||
.type_by_index(self.store, type_idx)
|
||||
.type_by_index(type_idx)
|
||||
.expect("Due to validation type should exists");
|
||||
|
||||
if required_function_type != actual_function_type {
|
||||
@ -518,7 +518,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
) -> Result<InstructionOutcome, Error> {
|
||||
let global = context
|
||||
.module()
|
||||
.global_by_index(&self.store, index)
|
||||
.global_by_index(index)
|
||||
.expect("Due to validation global should exists");
|
||||
let val = global.get();
|
||||
context.value_stack_mut().push(val)?;
|
||||
@ -534,7 +534,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
|
||||
let global = context
|
||||
.module()
|
||||
.global_by_index(&self.store, index)
|
||||
.global_by_index(index)
|
||||
.expect("Due to validation global should exists");
|
||||
global.set(val)?;
|
||||
Ok(InstructionOutcome::RunNextInstruction)
|
||||
@ -544,7 +544,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
where RuntimeValue: From<T>, T: LittleEndianConvert {
|
||||
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
||||
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");
|
||||
let b = m.get(address, mem::size_of::<T>())?;
|
||||
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 {
|
||||
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
|
||||
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");
|
||||
let b = m.get(address, mem::size_of::<T>())?;
|
||||
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 m = context.module()
|
||||
.memory_by_index(self.store, DEFAULT_MEMORY_INDEX)
|
||||
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
||||
.expect("Due to validation memory should exists");
|
||||
m.set(address, &stack_value)?;
|
||||
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 address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
|
||||
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");
|
||||
m.set(address, &stack_value)?;
|
||||
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> {
|
||||
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");
|
||||
let s = m.size();
|
||||
context
|
||||
@ -622,7 +622,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> {
|
||||
let pages: u32 = context.value_stack_mut().pop_as()?;
|
||||
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");
|
||||
let m = m.grow(pages)?;
|
||||
context
|
||||
@ -1012,7 +1012,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
|
||||
impl FunctionContext {
|
||||
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 {
|
||||
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"),
|
||||
};
|
||||
FunctionContext {
|
||||
@ -1030,7 +1030,7 @@ impl FunctionContext {
|
||||
pub fn nested(&mut self, function: Rc<FuncInstance>) -> Result<Self, Error> {
|
||||
let (function_locals, module, function_return_type) = {
|
||||
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"),
|
||||
};
|
||||
let function_type = function.func_type();
|
||||
@ -1066,8 +1066,8 @@ impl FunctionContext {
|
||||
self.locals.extend(locals);
|
||||
}
|
||||
|
||||
pub fn module(&self) -> ModuleId {
|
||||
self.module
|
||||
pub fn module(&self) -> Rc<ModuleInstance> {
|
||||
Rc::clone(&self.module)
|
||||
}
|
||||
|
||||
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome, Error> {
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::Cell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::any::Any;
|
||||
use std::fmt;
|
||||
use std::collections::HashMap;
|
||||
@ -17,53 +17,6 @@ use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDE
|
||||
DEFAULT_VALUE_STACK_LIMIT};
|
||||
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)]
|
||||
pub enum ExternVal {
|
||||
Func(Rc<FuncInstance>),
|
||||
@ -106,7 +59,7 @@ impl ExternVal {
|
||||
pub enum FuncInstance {
|
||||
Internal {
|
||||
func_type: Rc<FunctionType>,
|
||||
module: ModuleId,
|
||||
module: Rc<ModuleInstance>,
|
||||
body: Rc<FuncBody>,
|
||||
},
|
||||
Host {
|
||||
@ -118,7 +71,7 @@ pub enum FuncInstance {
|
||||
impl fmt::Debug for FuncInstance {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&FuncInstance::Internal { ref func_type, module, .. } => {
|
||||
&FuncInstance::Internal { ref func_type, ref module, .. } => {
|
||||
write!(f, "Internal {{ type={:?}, module={:?} }}", func_type, module)
|
||||
},
|
||||
&FuncInstance::Host { ref func_type, .. } => {
|
||||
@ -159,7 +112,7 @@ pub struct GlobalInstance {
|
||||
}
|
||||
|
||||
impl GlobalInstance {
|
||||
fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance {
|
||||
pub fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance {
|
||||
GlobalInstance {
|
||||
val: Cell::new(val),
|
||||
mutable
|
||||
@ -187,12 +140,12 @@ pub struct ExportInstance {
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ModuleInstance {
|
||||
types: Vec<Rc<FunctionType>>,
|
||||
tables: Vec<Rc<TableInstance>>,
|
||||
funcs: Vec<Rc<FuncInstance>>,
|
||||
memories: Vec<Rc<MemoryInstance>>,
|
||||
globals: Vec<Rc<GlobalInstance>>,
|
||||
exports: HashMap<String, ExternVal>,
|
||||
types: RefCell<Vec<Rc<FunctionType>>>,
|
||||
tables: RefCell<Vec<Rc<TableInstance>>>,
|
||||
funcs: RefCell<Vec<Rc<FuncInstance>>>,
|
||||
memories: RefCell<Vec<Rc<MemoryInstance>>>,
|
||||
globals: RefCell<Vec<Rc<GlobalInstance>>>,
|
||||
exports: RefCell<HashMap<String, ExternVal>>,
|
||||
}
|
||||
|
||||
impl ModuleInstance {
|
||||
@ -202,9 +155,84 @@ impl ModuleInstance {
|
||||
|
||||
pub fn with_exports(exports: HashMap<String, ExternVal>) -> 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)]
|
||||
@ -220,20 +248,14 @@ impl Store {
|
||||
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> {
|
||||
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 {
|
||||
func_type,
|
||||
module,
|
||||
module: Rc::clone(module),
|
||||
body: Rc::new(body),
|
||||
};
|
||||
Rc::new(func)
|
||||
@ -266,8 +288,7 @@ impl Store {
|
||||
&mut self,
|
||||
module: &Module,
|
||||
extern_vals: &[ExternVal],
|
||||
instance: &mut ModuleInstance,
|
||||
module_id: ModuleId,
|
||||
instance: &Rc<ModuleInstance>,
|
||||
) -> Result<(), Error> {
|
||||
let mut aux_data = validate_module(module)?;
|
||||
|
||||
@ -277,7 +298,7 @@ impl Store {
|
||||
.unwrap_or(&[])
|
||||
{
|
||||
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) {
|
||||
(&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();
|
||||
if expected_fn_type != &actual_fn_type {
|
||||
if expected_fn_type != actual_fn_type {
|
||||
return Err(Error::Initialization(format!(
|
||||
"Expected function with type {:?}, but actual type is {:?} for entry {}",
|
||||
expected_fn_type,
|
||||
@ -300,19 +321,19 @@ impl Store {
|
||||
import.field(),
|
||||
)));
|
||||
}
|
||||
instance.funcs.push(Rc::clone(func))
|
||||
instance.push_func(Rc::clone(func))
|
||||
}
|
||||
(&External::Table(ref tt), &ExternVal::Table(ref table)) => {
|
||||
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)) => {
|
||||
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)) => {
|
||||
// TODO: check globals
|
||||
instance.globals.push(Rc::clone(global))
|
||||
instance.push_global(Rc::clone(global))
|
||||
}
|
||||
(expected_import, actual_extern_val) => {
|
||||
return Err(Error::Initialization(format!(
|
||||
@ -339,7 +360,7 @@ impl Store {
|
||||
for (index, (ty, body)) in
|
||||
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(
|
||||
"At func validation time labels are collected; Collected labels are added by index; qed",
|
||||
);
|
||||
@ -348,33 +369,33 @@ impl Store {
|
||||
opcodes: body.code().clone(),
|
||||
labels: labels,
|
||||
};
|
||||
let func_id = self.alloc_func(module_id, func_type, func_body);
|
||||
instance.funcs.push(func_id);
|
||||
let func_instance = self.alloc_func(instance, func_type, func_body);
|
||||
instance.push_func(func_instance);
|
||||
}
|
||||
}
|
||||
|
||||
for table in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) {
|
||||
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()
|
||||
.map(|ms| ms.entries())
|
||||
.unwrap_or(&[])
|
||||
{
|
||||
let memory_id = self.alloc_memory(memory)?;
|
||||
instance.memories.push(memory_id);
|
||||
let memory = self.alloc_memory(memory_type)?;
|
||||
instance.push_memory(memory);
|
||||
}
|
||||
|
||||
for global in module
|
||||
for global_entry in module
|
||||
.global_section()
|
||||
.map(|gs| gs.entries())
|
||||
.unwrap_or(&[])
|
||||
{
|
||||
let init_val = eval_init_expr(global.init_expr(), instance, self);
|
||||
let global_id = self.alloc_global(global.global_type().clone(), init_val);
|
||||
instance.globals.push(global_id);
|
||||
let init_val = eval_init_expr(global_entry.init_expr(), &*instance, self);
|
||||
let global = self.alloc_global(global_entry.global_type().clone(), init_val);
|
||||
instance.push_global(global);
|
||||
}
|
||||
|
||||
for export in module
|
||||
@ -386,34 +407,30 @@ impl Store {
|
||||
let extern_val: ExternVal = match *export.internal() {
|
||||
Internal::Function(idx) => {
|
||||
let func = instance
|
||||
.funcs
|
||||
.get(idx as usize)
|
||||
.func_by_index(idx)
|
||||
.expect("Due to validation func should exists");
|
||||
ExternVal::Func(Rc::clone(func))
|
||||
ExternVal::Func(func)
|
||||
}
|
||||
Internal::Global(idx) => {
|
||||
let global = instance
|
||||
.globals
|
||||
.get(idx as usize)
|
||||
.global_by_index(idx)
|
||||
.expect("Due to validation global should exists");
|
||||
ExternVal::Global(Rc::clone(global))
|
||||
ExternVal::Global(global)
|
||||
}
|
||||
Internal::Memory(idx) => {
|
||||
let memory = instance
|
||||
.memories
|
||||
.get(idx as usize)
|
||||
.memory_by_index(idx)
|
||||
.expect("Due to validation memory should exists");
|
||||
ExternVal::Memory(Rc::clone(memory))
|
||||
ExternVal::Memory(memory)
|
||||
}
|
||||
Internal::Table(idx) => {
|
||||
let table = instance
|
||||
.tables
|
||||
.get(idx as usize)
|
||||
.table_by_index(idx)
|
||||
.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(())
|
||||
@ -424,12 +441,10 @@ impl Store {
|
||||
module: &Module,
|
||||
extern_vals: &[ExternVal],
|
||||
state: &mut St,
|
||||
) -> Result<ModuleId, Error> {
|
||||
let mut instance = ModuleInstance::new();
|
||||
// Reserve the index of the module, but not yet push the module.
|
||||
let module_id = ModuleId((self.modules.len()) as u32);
|
||||
) -> Result<Rc<ModuleInstance>, Error> {
|
||||
let mut instance = Rc::new(ModuleInstance::new());
|
||||
|
||||
self.alloc_module_internal(module, extern_vals, &mut instance, module_id)?;
|
||||
self.alloc_module_internal(module, extern_vals, &instance)?;
|
||||
|
||||
for element_segment in module
|
||||
.elements_section()
|
||||
@ -442,16 +457,14 @@ impl Store {
|
||||
};
|
||||
|
||||
let table_inst = instance
|
||||
.tables
|
||||
.get(DEFAULT_TABLE_INDEX as usize)
|
||||
.table_by_index(DEFAULT_TABLE_INDEX)
|
||||
.expect("Due to validation default table should exists");
|
||||
for (j, func_idx) in element_segment.members().into_iter().enumerate() {
|
||||
let func = instance
|
||||
.funcs
|
||||
.get(*func_idx as usize)
|
||||
.func_by_index(*func_idx)
|
||||
.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
|
||||
.memories
|
||||
.get(DEFAULT_MEMORY_INDEX as usize)
|
||||
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
||||
.expect("Due to validation default memory should exists");
|
||||
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
|
||||
if let Some(start_fn_idx) = module.start_section() {
|
||||
let start_func = {
|
||||
let instance = self.resolve_module(module_id);
|
||||
instance
|
||||
.funcs
|
||||
.get(start_fn_idx as usize)
|
||||
.cloned()
|
||||
.func_by_index(start_fn_idx)
|
||||
.expect("Due to validation start function should exists")
|
||||
};
|
||||
self.invoke(start_func, vec![], state)?;
|
||||
}
|
||||
|
||||
Ok(module_id)
|
||||
}
|
||||
|
||||
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)
|
||||
Ok(instance)
|
||||
}
|
||||
|
||||
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::GetGlobal(idx) => {
|
||||
let global = module
|
||||
.globals
|
||||
.get(idx as usize)
|
||||
.global_by_index(idx)
|
||||
.expect("Due to validation global should exists in module");
|
||||
global.get()
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ fn native_env_function() {
|
||||
let mut program = program_with_default_env();
|
||||
let env_host_module = build_env_module();
|
||||
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 {
|
||||
memory: env_memory,
|
||||
@ -255,7 +255,7 @@ fn native_custom_error() {
|
||||
let mut program = program_with_default_env();
|
||||
let env_host_module = build_env_module();
|
||||
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 {
|
||||
memory: env_memory,
|
||||
|
@ -464,11 +464,11 @@ fn return_void() {
|
||||
let module = program.add_module("main", module, &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]);
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ fn interpreter_accumulate_u8() {
|
||||
.expect("Failed to initialize module");
|
||||
|
||||
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
|
||||
let offset: u32 = 0;
|
||||
|
Reference in New Issue
Block a user