Add St everywhere

This commit is contained in:
Sergey Pepyakin 2017-12-15 18:23:54 +03:00
parent e5bac395fd
commit 11afa2dc2f
11 changed files with 290 additions and 379 deletions

View File

@ -5,25 +5,25 @@ use std::any::Any;
use elements::{FunctionType, Opcodes, Local}; use elements::{FunctionType, Opcodes, Local};
use interpreter::{Error, ModuleInstance}; use interpreter::{Error, ModuleInstance};
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
use interpreter::host::AnyFunc; use interpreter::host::HostFunc;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT}; use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT};
#[derive(Clone)] #[derive(Clone)]
pub enum FuncInstance { pub enum FuncInstance<St> {
Internal { Internal {
func_type: Rc<FunctionType>, func_type: Rc<FunctionType>,
module: Rc<ModuleInstance>, module: Rc<ModuleInstance<St>>,
body: Rc<FuncBody>, body: Rc<FuncBody>,
}, },
Host { Host {
func_type: Rc<FunctionType>, func_type: Rc<FunctionType>,
host_func: Rc<AnyFunc>, host_func: Rc<HostFunc<St>>,
}, },
} }
impl fmt::Debug for FuncInstance { impl<St: fmt::Debug> fmt::Debug for FuncInstance<St> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&FuncInstance::Internal { &FuncInstance::Internal {
@ -43,9 +43,9 @@ impl fmt::Debug for FuncInstance {
} }
} }
impl FuncInstance { impl<St> FuncInstance<St> {
pub fn alloc_internal( pub fn alloc_internal(
module: Rc<ModuleInstance>, module: Rc<ModuleInstance<St>>,
func_type: Rc<FunctionType>, func_type: Rc<FunctionType>,
body: FuncBody, body: FuncBody,
) -> Rc<Self> { ) -> Rc<Self> {
@ -59,7 +59,7 @@ impl FuncInstance {
pub fn alloc_host( pub fn alloc_host(
func_type: Rc<FunctionType>, func_type: Rc<FunctionType>,
host_func: Rc<AnyFunc>, host_func: Rc<HostFunc<St>>,
) -> Rc<Self> { ) -> Rc<Self> {
let func = FuncInstance::Host { let func = FuncInstance::Host {
func_type, func_type,
@ -82,14 +82,14 @@ impl FuncInstance {
} }
} }
pub fn invoke<St: 'static>( pub fn invoke(
func: Rc<FuncInstance>, func: Rc<FuncInstance<St>>,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
state: &mut St, state: &mut St,
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {
enum InvokeKind { enum InvokeKind<St> {
Internal(FunctionContext), Internal(FunctionContext<St>),
Host(Rc<AnyFunc>, Vec<RuntimeValue>), Host(Rc<HostFunc<St>>, Vec<RuntimeValue>),
} }
let result = match *func { let result = match *func {
@ -115,7 +115,7 @@ impl FuncInstance {
let mut interpreter = Interpreter::new(state); let mut interpreter = Interpreter::new(state);
interpreter.run_function(ctx) interpreter.run_function(ctx)
} }
InvokeKind::Host(host_func, args) => host_func.call_as_any(state as &mut Any, &args), InvokeKind::Host(host_func, args) => host_func(state, &args),
} }
} }
} }

View File

@ -1,6 +1,4 @@
use std::any::Any;
use std::rc::Rc; use std::rc::Rc;
use std::marker::PhantomData;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType}; use elements::{FunctionType, ValueType, GlobalType, MemoryType, TableType};
@ -13,71 +11,59 @@ use interpreter::value::RuntimeValue;
use interpreter::Error; use interpreter::Error;
use interpreter::ImportResolver; use interpreter::ImportResolver;
pub type HostFunc<St> = Fn(&mut St, &[RuntimeValue]) -> Result<Option<RuntimeValue>, Error>;
pub struct HostModuleBuilder<St> { pub struct HostModuleBuilder<St> {
exports: HashMap<String, ExternVal>, exports: HashMap<String, ExternVal<St>>,
_marker: PhantomData<St>,
} }
impl<St: 'static> HostModuleBuilder<St> { impl<St> HostModuleBuilder<St> {
pub fn new() -> Self { pub fn new() -> Self {
HostModuleBuilder { HostModuleBuilder {
exports: HashMap::new(), exports: HashMap::new(),
_marker: PhantomData,
} }
} }
pub fn insert_func0< // pub fn insert_func0<
Cl: Fn(&mut St) -> Result<Option<Ret>, Error> + 'static, // Cl: Fn(&mut St) -> Result<Option<Ret>, Error> + AnyFunc<St> + 'static,
Ret: AsReturnVal + 'static, // Ret: AsReturnVal + 'static,
F: Into<Func0<Cl, St, Ret>>, // F: Into<Cl>,
N: Into<String>, // N: Into<String>,
>( // >(
&mut self, // &mut self,
name: N, // name: N,
f: F, // f: Box<F>,
) { // ) {
let func_type = Func0::<Cl, St, Ret>::derive_func_type(); // let func_type = FunctionType::new(vec![], Ret::value_type());
let host_func = Rc::new(f.into()) as Rc<AnyFunc>; // let host_func = Rc::new(f) as Rc<AnyFunc<St>>;
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); // let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func); // self.insert_func(name, func);
} // }
pub fn with_func1<
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error> + 'static,
Ret: AsReturnVal + 'static,
P1: FromArg + 'static,
F: Into<Func1<Cl, St, Ret, P1>>,
N: Into<String>,
>(
&mut self,
name: N,
f: F,
) {
let func_type = Func1::<Cl, St, Ret, P1>::derive_func_type();
let host_func = Rc::new(f.into()) as Rc<AnyFunc>;
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func);
}
pub fn with_func2< pub fn with_func2<
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error> + 'static, Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error> + 'static,
Ret: AsReturnVal + 'static, Ret: AsReturnVal + 'static,
P1: FromArg + 'static, P1: FromArg + 'static,
P2: FromArg + 'static, P2: FromArg + 'static,
F: Into<Func2<Cl, St, Ret, P1, P2>>,
N: Into<String>, N: Into<String>,
>( >(
&mut self, &mut self,
name: N, name: N,
f: F, f: Cl,
) { ) {
let func_type = Func2::<Cl, St, Ret, P1, P2>::derive_func_type(); let func_type = FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
let host_func = Rc::new(f.into()) as Rc<AnyFunc>; let host_func = Rc::new(move |state: &mut St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let p1 = P1::from_arg(&args[0]);
let p2 = P2::from_arg(&args[1]);
let result = f(state, p1, p2);
result.map(|r| r.and_then(|r| r.as_return_val()))
});
let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); let func = FuncInstance::alloc_host(Rc::new(func_type), host_func);
self.insert_func(name, func); self.insert_func(name, func);
} }
pub fn insert_func<N: Into<String>>(&mut self, name: N, func: Rc<FuncInstance>) { pub fn insert_func<N: Into<String>>(&mut self, name: N, func: Rc<FuncInstance<St>>) {
self.insert(name, ExternVal::Func(func)); self.insert(name, ExternVal::Func(func));
} }
@ -89,7 +75,7 @@ impl<St: 'static> HostModuleBuilder<St> {
self.insert(name, ExternVal::Memory(memory)); self.insert(name, ExternVal::Memory(memory));
} }
pub fn insert_table<N: Into<String>>(&mut self, name: N, table: Rc<TableInstance>) { pub fn insert_table<N: Into<String>>(&mut self, name: N, table: Rc<TableInstance<St>>) {
self.insert(name, ExternVal::Table(table)); self.insert(name, ExternVal::Table(table));
} }
@ -103,19 +89,19 @@ impl<St: 'static> HostModuleBuilder<St> {
self self
} }
pub fn with_table<N: Into<String>>(mut self, name: N, table: Rc<TableInstance>) -> Self { pub fn with_table<N: Into<String>>(mut self, name: N, table: Rc<TableInstance<St>>) -> Self {
self.insert_table(name, table); self.insert_table(name, table);
self self
} }
fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal) { fn insert<N: Into<String>>(&mut self, name: N, extern_val: ExternVal<St>) {
match self.exports.entry(name.into()) { match self.exports.entry(name.into()) {
Entry::Vacant(v) => v.insert(extern_val), Entry::Vacant(v) => v.insert(extern_val),
Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()), Entry::Occupied(o) => panic!("Duplicate export name {}", o.key()),
}; };
} }
pub fn build(self) -> HostModule { pub fn build(self) -> HostModule<St> {
let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports)); let internal_instance = Rc::new(ModuleInstance::with_exports(self.exports));
HostModule { HostModule {
internal_instance internal_instance
@ -123,22 +109,22 @@ impl<St: 'static> HostModuleBuilder<St> {
} }
} }
pub struct HostModule { pub struct HostModule<St> {
internal_instance: Rc<ModuleInstance>, internal_instance: Rc<ModuleInstance<St>>,
} }
impl HostModule { impl<St> HostModule<St> {
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> { pub fn export_by_name(&self, name: &str) -> Option<ExternVal<St>> {
self.internal_instance.export_by_name(name) self.internal_instance.export_by_name(name)
} }
} }
impl ImportResolver for HostModule { impl<St> ImportResolver<St> for HostModule<St> {
fn resolve_func( fn resolve_func(
&self, &self,
field_name: &str, field_name: &str,
func_type: &FunctionType, func_type: &FunctionType,
) -> Result<Rc<FuncInstance>, Error> { ) -> Result<Rc<FuncInstance<St>>, Error> {
self.internal_instance.resolve_func(field_name, func_type) self.internal_instance.resolve_func(field_name, func_type)
} }
@ -162,15 +148,15 @@ impl ImportResolver for HostModule {
&self, &self,
field_name: &str, field_name: &str,
table_type: &TableType, table_type: &TableType,
) -> Result<Rc<TableInstance>, Error> { ) -> Result<Rc<TableInstance<St>>, Error> {
self.internal_instance.resolve_table(field_name, table_type) self.internal_instance.resolve_table(field_name, table_type)
} }
} }
pub trait AnyFunc { pub trait AnyFunc<St> {
fn call_as_any( fn call_as_any(
&self, &self,
state: &mut Any, state: &mut St,
args: &[RuntimeValue], args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error>; ) -> Result<Option<RuntimeValue>, Error>;
} }
@ -218,134 +204,26 @@ impl AsReturnVal for () {
} }
} }
pub struct Func0<Cl: Fn(&mut St) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal> { impl<St, Ret: AsReturnVal> AnyFunc<St> for Fn(&mut St) -> Result<Option<Ret>, Error> {
closure: Cl,
_marker: PhantomData<(St, Ret)>,
}
impl<
St: 'static,
Ret: AsReturnVal,
Cl: Fn(&mut St) -> Result<Option<Ret>, Error>,
> AnyFunc for Func0<Cl, St, Ret> {
fn call_as_any( fn call_as_any(
&self, &self,
state: &mut Any, state: &mut St,
_args: &[RuntimeValue], _args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap(); let result = self(state);
let result = (self.closure)(state);
result.map(|r| r.and_then(|r| r.as_return_val())) result.map(|r| r.and_then(|r| r.as_return_val()))
} }
} }
impl<St: 'static, Ret: AsReturnVal, Cl: Fn(&mut St) -> Result<Option<Ret>, Error>> From<Cl> impl<St, Ret: AsReturnVal, P1: FromArg, P2: FromArg> AnyFunc<St> for Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error> {
for Func0<Cl, St, Ret> {
fn from(cl: Cl) -> Self {
Func0 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
Ret: AsReturnVal,
Cl: Fn(&mut St) -> Result<Option<Ret>, Error>,
> Func0<Cl, St, Ret> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![], Ret::value_type())
}
}
pub struct Func1<Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal, P1: FromArg> {
closure: Cl,
_marker: PhantomData<(St, Ret, P1)>,
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
> AnyFunc for Func1<Cl, St, Ret, P1> {
fn call_as_any( fn call_as_any(
&self, &self,
state: &mut Any, state: &mut St,
args: &[RuntimeValue], args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap();
let p1 = P1::from_arg(&args[0]);
let result = (self.closure)(state, p1);
result.map(|r| r.and_then(|r| r.as_return_val()))
}
}
impl<St: 'static, Ret: AsReturnVal, P1: FromArg, Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>> From<Cl>
for Func1<Cl, St, Ret, P1> {
fn from(cl: Cl) -> Self {
Func1 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
Cl: Fn(&mut St, P1) -> Result<Option<Ret>, Error>,
> Func1<Cl, St, Ret, P1> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![P1::value_type()], Ret::value_type())
}
}
pub struct Func2<Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>, St, Ret: AsReturnVal, P1: FromArg, P2: FromArg> {
closure: Cl,
_marker: PhantomData<(St, Ret, P1, P2)>,
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
P2: FromArg,
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>,
> AnyFunc for Func2<Cl, St, Ret, P1, P2> {
fn call_as_any(
&self,
state: &mut Any,
args: &[RuntimeValue],
) -> Result<Option<RuntimeValue>, Error> {
let state = state.downcast_mut::<St>().unwrap();
let p1 = P1::from_arg(&args[0]); let p1 = P1::from_arg(&args[0]);
let p2 = P2::from_arg(&args[1]); let p2 = P2::from_arg(&args[1]);
let result = (self.closure)(state, p1, p2); let result = self(state, p1, p2);
result.map(|r| r.and_then(|r| r.as_return_val())) result.map(|r| r.and_then(|r| r.as_return_val()))
} }
} }
impl<St: 'static, Ret: AsReturnVal, P1: FromArg, P2: FromArg, Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>> From<Cl>
for Func2<Cl, St, Ret, P1, P2> {
fn from(cl: Cl) -> Self {
Func2 {
closure: cl,
_marker: PhantomData,
}
}
}
impl<
St: 'static,
Ret: AsReturnVal,
P1: FromArg,
P2: FromArg,
Cl: Fn(&mut St, P1, P2) -> Result<Option<Ret>, Error>,
> Func2<Cl, St, Ret, P1, P2> {
fn derive_func_type() -> FunctionType {
FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type())
}
}

View File

@ -7,38 +7,43 @@ use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance; use interpreter::table::TableInstance;
use interpreter::Error; use interpreter::Error;
#[derive(Default)] pub struct Imports<'a, St: 'a> {
pub struct Imports<'a> { modules: HashMap<String, &'a ImportResolver<St>>,
modules: HashMap<String, &'a ImportResolver>,
} }
impl<'a> Imports<'a> { impl<'a, St: 'a> Default for Imports<'a, St> {
pub fn new() -> Imports<'a> { fn default() -> Self {
Self::new()
}
}
impl<'a, St: 'a> Imports<'a, St> {
pub fn new() -> Imports<'a, St> {
Imports { Imports {
modules: HashMap::new(), modules: HashMap::new(),
} }
} }
pub fn with_resolver<N: Into<String>>(mut self, name: N, resolver: &'a ImportResolver) -> Imports<'a> { pub fn with_resolver<N: Into<String>>(mut self, name: N, resolver: &'a ImportResolver<St>) -> Self {
self.modules.insert(name.into(), resolver); self.modules.insert(name.into(), resolver);
self self
} }
pub fn push_resolver<N: Into<String>>(&mut self, name: N, resolver: &'a ImportResolver) { pub fn push_resolver<N: Into<String>>(&mut self, name: N, resolver: &'a ImportResolver<St>) {
self.modules.insert(name.into(), resolver); self.modules.insert(name.into(), resolver);
} }
pub fn resolver(&self, name: &str) -> Option<&ImportResolver> { pub fn resolver(&self, name: &str) -> Option<&ImportResolver<St>> {
self.modules.get(name).cloned() self.modules.get(name).cloned()
} }
} }
pub trait ImportResolver { pub trait ImportResolver<St> {
fn resolve_func( fn resolve_func(
&self, &self,
field_name: &str, field_name: &str,
func_type: &FunctionType, func_type: &FunctionType,
) -> Result<Rc<FuncInstance>, Error>; ) -> Result<Rc<FuncInstance<St>>, Error>;
fn resolve_global( fn resolve_global(
&self, &self,
@ -56,5 +61,5 @@ pub trait ImportResolver {
&self, &self,
field_name: &str, field_name: &str,
table_type: &TableType, table_type: &TableType,
) -> Result<Rc<TableInstance>, Error>; ) -> Result<Rc<TableInstance<St>>, Error>;
} }

View File

@ -149,7 +149,7 @@ pub use self::memory::MemoryInstance;
pub use self::table::TableInstance; pub use self::table::TableInstance;
pub use self::program::ProgramInstance; pub use self::program::ProgramInstance;
pub use self::value::RuntimeValue; pub use self::value::RuntimeValue;
pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg}; pub use self::host::{HostModule, HostModuleBuilder, AnyFunc, AsReturnVal, FromArg};
pub use self::imports::{ImportResolver, Imports}; pub use self::imports::{ImportResolver, Imports};
pub use self::module::ModuleInstance; pub use self::module::ModuleInstance;
pub use self::global::GlobalInstance; pub use self::global::GlobalInstance;

View File

@ -1,5 +1,6 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module, use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module,
Opcode, ResizableLimits, TableType, Type}; Opcode, ResizableLimits, TableType, Type};
@ -10,23 +11,44 @@ use interpreter::func::{FuncInstance, FuncBody};
use validation::validate_module; use validation::validate_module;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
#[derive(Clone, Debug)] pub enum ExternVal<St> {
pub enum ExternVal { Func(Rc<FuncInstance<St>>),
Func(Rc<FuncInstance>), Table(Rc<TableInstance<St>>),
Table(Rc<TableInstance>),
Memory(Rc<MemoryInstance>), Memory(Rc<MemoryInstance>),
Global(Rc<GlobalInstance>), Global(Rc<GlobalInstance>),
} }
impl ExternVal { impl<St> Clone for ExternVal<St> {
pub fn as_func(&self) -> Option<Rc<FuncInstance>> { fn clone(&self) -> Self {
match *self {
ExternVal::Func(ref func) => ExternVal::Func(Rc::clone(func)),
ExternVal::Table(ref table) => ExternVal::Table(Rc::clone(table)),
ExternVal::Memory(ref memory) => ExternVal::Memory(Rc::clone(memory)),
ExternVal::Global(ref global) => ExternVal::Global(Rc::clone(global)),
}
}
}
impl<St> fmt::Debug for ExternVal<St> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ExternVal {{ {} }}", match *self {
ExternVal::Func(_) => "Func",
ExternVal::Table(_) => "Table",
ExternVal::Memory(_) => "Memory",
ExternVal::Global(_) => "Global",
})
}
}
impl<St> ExternVal<St> {
pub fn as_func(&self) -> Option<Rc<FuncInstance<St>>> {
match *self { match *self {
ExternVal::Func(ref func) => Some(Rc::clone(func)), ExternVal::Func(ref func) => Some(Rc::clone(func)),
_ => None, _ => None,
} }
} }
pub fn as_table(&self) -> Option<Rc<TableInstance>> { pub fn as_table(&self) -> Option<Rc<TableInstance<St>>> {
match *self { match *self {
ExternVal::Table(ref table) => Some(Rc::clone(table)), ExternVal::Table(ref table) => Some(Rc::clone(table)),
_ => None, _ => None,
@ -49,32 +71,38 @@ impl ExternVal {
} }
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ModuleInstance { pub struct ModuleInstance<St> {
types: RefCell<Vec<Rc<FunctionType>>>, types: RefCell<Vec<Rc<FunctionType>>>,
tables: RefCell<Vec<Rc<TableInstance>>>, tables: RefCell<Vec<Rc<TableInstance<St>>>>,
funcs: RefCell<Vec<Rc<FuncInstance>>>, funcs: RefCell<Vec<Rc<FuncInstance<St>>>>,
memories: RefCell<Vec<Rc<MemoryInstance>>>, memories: RefCell<Vec<Rc<MemoryInstance>>>,
globals: RefCell<Vec<Rc<GlobalInstance>>>, globals: RefCell<Vec<Rc<GlobalInstance>>>,
exports: RefCell<HashMap<String, ExternVal>>, exports: RefCell<HashMap<String, ExternVal<St>>>,
} }
impl ModuleInstance { impl<St> ModuleInstance<St> {
fn new() -> ModuleInstance { fn new() -> ModuleInstance<St> {
ModuleInstance::default() ModuleInstance {
types: RefCell::new(Vec::new()),
tables: RefCell::new(Vec::new()),
funcs: RefCell::new(Vec::new()),
memories: RefCell::new(Vec::new()),
globals: RefCell::new(Vec::new()),
exports: RefCell::new(HashMap::new()),
}
} }
pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance { pub fn with_exports(exports: HashMap<String, ExternVal<St>>) -> ModuleInstance<St> {
ModuleInstance { let mut instance = Self::new();
exports: RefCell::new(exports), instance.exports = RefCell::new(exports);
..Default::default() instance
}
} }
pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> { pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> {
self.memories.borrow().get(idx as usize).cloned() self.memories.borrow().get(idx as usize).cloned()
} }
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance>> { pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance<St>>> {
self.tables.borrow().get(idx as usize).cloned() self.tables.borrow().get(idx as usize).cloned()
} }
@ -82,7 +110,7 @@ impl ModuleInstance {
self.globals.borrow().get(idx as usize).cloned() self.globals.borrow().get(idx as usize).cloned()
} }
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance>> { pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance<St>>> {
self.funcs.borrow().get(idx as usize).cloned() self.funcs.borrow().get(idx as usize).cloned()
} }
@ -90,11 +118,11 @@ impl ModuleInstance {
self.types.borrow().get(idx as usize).cloned() self.types.borrow().get(idx as usize).cloned()
} }
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> { pub fn export_by_name(&self, name: &str) -> Option<ExternVal<St>> {
self.exports.borrow().get(name).cloned() self.exports.borrow().get(name).cloned()
} }
fn push_func(&self, func: Rc<FuncInstance>) { fn push_func(&self, func: Rc<FuncInstance<St>>) {
self.funcs.borrow_mut().push(func); self.funcs.borrow_mut().push(func);
} }
@ -106,7 +134,7 @@ impl ModuleInstance {
self.memories.borrow_mut().push(memory) self.memories.borrow_mut().push(memory)
} }
fn push_table(&self, table: Rc<TableInstance>) { fn push_table(&self, table: Rc<TableInstance<St>>) {
self.tables.borrow_mut().push(table) self.tables.borrow_mut().push(table)
} }
@ -114,14 +142,14 @@ impl ModuleInstance {
self.globals.borrow_mut().push(global) self.globals.borrow_mut().push(global)
} }
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) { fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal<St>) {
self.exports.borrow_mut().insert(name.into(), extern_val); self.exports.borrow_mut().insert(name.into(), extern_val);
} }
fn alloc_module( fn alloc_module(
module: &Module, module: &Module,
extern_vals: &[ExternVal], extern_vals: &[ExternVal<St>],
instance: &Rc<ModuleInstance>, instance: &Rc<ModuleInstance<St>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut aux_data = validate_module(module)?; let mut aux_data = validate_module(module)?;
@ -246,7 +274,7 @@ impl ModuleInstance {
.unwrap_or(&[]) .unwrap_or(&[])
{ {
let field = export.field(); let field = export.field();
let extern_val: ExternVal = match *export.internal() { let extern_val: ExternVal<St> = match *export.internal() {
Internal::Function(idx) => { Internal::Function(idx) => {
let func = instance let func = instance
.func_by_index(idx) .func_by_index(idx)
@ -280,8 +308,8 @@ impl ModuleInstance {
fn instantiate_with_externvals( fn instantiate_with_externvals(
module: &Module, module: &Module,
extern_vals: &[ExternVal], extern_vals: &[ExternVal<St>],
) -> Result<Rc<ModuleInstance>, Error> { ) -> Result<Rc<ModuleInstance<St>>, Error> {
let instance = Rc::new(ModuleInstance::new()); let instance = Rc::new(ModuleInstance::new());
ModuleInstance::alloc_module(module, extern_vals, &instance)?; ModuleInstance::alloc_module(module, extern_vals, &instance)?;
@ -325,8 +353,8 @@ impl ModuleInstance {
fn instantiate_with_imports( fn instantiate_with_imports(
module: &Module, module: &Module,
imports: &Imports, imports: &Imports<St>,
) -> Result<Rc<ModuleInstance>, Error> { ) -> Result<Rc<ModuleInstance<St>>, 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_name = import_entry.module(); let module_name = import_entry.module();
@ -365,11 +393,11 @@ impl ModuleInstance {
Self::instantiate_with_externvals(module, &extern_vals) Self::instantiate_with_externvals(module, &extern_vals)
} }
pub fn instantiate<'a>(module: &'a Module) -> InstantiationWizard<'a> { pub fn instantiate<'a>(module: &'a Module) -> InstantiationWizard<'a, St> {
InstantiationWizard::new(module) InstantiationWizard::new(module)
} }
pub fn invoke_index<St: 'static>( pub fn invoke_index(
&self, &self,
func_idx: u32, func_idx: u32,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
@ -384,7 +412,7 @@ impl ModuleInstance {
FuncInstance::invoke(func_instance, args, state) FuncInstance::invoke(func_instance, args, state)
} }
pub fn invoke_export<St: 'static>( pub fn invoke_export(
&self, &self,
func_name: &str, func_name: &str,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
@ -409,12 +437,12 @@ impl ModuleInstance {
} }
} }
pub struct InstantiationWizard<'a> { pub struct InstantiationWizard<'a, St: 'a> {
module: &'a Module, module: &'a Module,
imports: Option<Imports<'a>>, imports: Option<Imports<'a, St>>,
} }
impl<'a> InstantiationWizard<'a> { impl<'a, St: 'a> InstantiationWizard<'a, St> {
fn new(module: &'a Module) -> Self { fn new(module: &'a Module) -> Self {
InstantiationWizard { InstantiationWizard {
module, module,
@ -422,7 +450,7 @@ impl<'a> InstantiationWizard<'a> {
} }
} }
pub fn with_imports(mut self, imports: Imports<'a>) -> Self { pub fn with_imports(mut self, imports: Imports<'a, St>) -> Self {
self.imports = Some(imports); self.imports = Some(imports);
self self
} }
@ -430,7 +458,7 @@ impl<'a> InstantiationWizard<'a> {
pub fn with_import<N: Into<String>>( pub fn with_import<N: Into<String>>(
mut self, mut self,
name: N, name: N,
import_resolver: &'a ImportResolver, import_resolver: &'a ImportResolver<St>,
) -> Self { ) -> Self {
self.imports self.imports
.get_or_insert_with(|| Imports::default()) .get_or_insert_with(|| Imports::default())
@ -438,7 +466,7 @@ impl<'a> InstantiationWizard<'a> {
self self
} }
pub fn run_start<St: 'static>(mut self, state: &mut St) -> Result<Rc<ModuleInstance>, Error> { pub fn run_start(mut self, state: &mut St) -> Result<Rc<ModuleInstance<St>>, Error> {
let imports = self.imports.get_or_insert_with(|| Imports::default()); let imports = self.imports.get_or_insert_with(|| Imports::default());
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?; let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
@ -451,7 +479,7 @@ impl<'a> InstantiationWizard<'a> {
Ok(instance) Ok(instance)
} }
pub fn assert_no_start(mut self) -> Result<Rc<ModuleInstance>, Error> { pub fn assert_no_start(mut self) -> Result<Rc<ModuleInstance<St>>, Error> {
assert!(self.module.start_section().is_none()); assert!(self.module.start_section().is_none());
let imports = self.imports.get_or_insert_with(|| Imports::default()); let imports = self.imports.get_or_insert_with(|| Imports::default());
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?; let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
@ -459,12 +487,12 @@ impl<'a> InstantiationWizard<'a> {
} }
} }
impl ImportResolver for ModuleInstance { impl<St> ImportResolver<St> for ModuleInstance<St> {
fn resolve_func( fn resolve_func(
&self, &self,
field_name: &str, field_name: &str,
_func_type: &FunctionType, _func_type: &FunctionType,
) -> Result<Rc<FuncInstance>, Error> { ) -> Result<Rc<FuncInstance<St>>, Error> {
Ok(self.export_by_name(field_name) Ok(self.export_by_name(field_name)
.ok_or_else(|| { .ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name)) Error::Validation(format!("Export {} not found", field_name))
@ -509,7 +537,7 @@ impl ImportResolver for ModuleInstance {
&self, &self,
field_name: &str, field_name: &str,
_table_type: &TableType, _table_type: &TableType,
) -> Result<Rc<TableInstance>, Error> { ) -> Result<Rc<TableInstance<St>>, Error> {
Ok(self.export_by_name(field_name) Ok(self.export_by_name(field_name)
.ok_or_else(|| { .ok_or_else(|| {
Error::Validation(format!("Export {} not found", field_name)) Error::Validation(format!("Export {} not found", field_name))
@ -525,7 +553,7 @@ fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
Rc::new(func_type) Rc::new(func_type)
} }
fn alloc_table(table_type: &TableType) -> Result<Rc<TableInstance>, Error> { fn alloc_table<St>(table_type: &TableType) -> Result<Rc<TableInstance<St>>, Error> {
let table = TableInstance::new(table_type)?; let table = TableInstance::new(table_type)?;
Ok(Rc::new(table)) Ok(Rc::new(table))
} }
@ -540,7 +568,7 @@ fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> Rc<GlobalInstance
Rc::new(global) Rc::new(global)
} }
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue { fn eval_init_expr<T>(init_expr: &InitExpr, module: &ModuleInstance<T>) -> RuntimeValue {
let code = init_expr.code(); let code = init_expr.code();
debug_assert!( debug_assert!(
code.len() == 2, code.len() == 2,

View File

@ -9,14 +9,14 @@ use interpreter::value::RuntimeValue;
use interpreter::imports::{Imports, ImportResolver}; use interpreter::imports::{Imports, ImportResolver};
/// Program instance. Program is a set of instantiated modules. /// Program instance. Program is a set of instantiated modules.
pub struct ProgramInstance { pub struct ProgramInstance<St=()> {
modules: HashMap<String, Rc<ModuleInstance>>, modules: HashMap<String, Rc<ModuleInstance<St>>>,
resolvers: HashMap<String, Box<ImportResolver>>, resolvers: HashMap<String, Box<ImportResolver<St>>>,
} }
impl ProgramInstance { impl<St> ProgramInstance<St> {
/// Create new program instance. /// Create new program instance.
pub fn new() -> Self { pub fn new() -> ProgramInstance<St> {
ProgramInstance { ProgramInstance {
modules: HashMap::new(), modules: HashMap::new(),
resolvers: HashMap::new(), resolvers: HashMap::new(),
@ -24,12 +24,12 @@ impl ProgramInstance {
} }
/// Instantiate module with validation. /// Instantiate module with validation.
pub fn add_module<'a, St: 'static>( pub fn add_module(
&mut self, &mut self,
name: &str, name: &str,
module: Module, module: Module,
state: &mut St, state: &mut St,
) -> Result<Rc<ModuleInstance>, Error> { ) -> Result<Rc<ModuleInstance<St>>, Error> {
let module_instance = { let module_instance = {
let mut imports = Imports::new(); let mut imports = Imports::new();
for (module_name, module_instance) in self.modules.iter() { for (module_name, module_instance) in self.modules.iter() {
@ -50,7 +50,7 @@ impl ProgramInstance {
pub fn add_import_resolver( pub fn add_import_resolver(
&mut self, &mut self,
name: &str, name: &str,
import_resolver: Box<ImportResolver>, import_resolver: Box<ImportResolver<St>>,
) { ) {
self.resolvers.insert(name.to_owned(), import_resolver); self.resolvers.insert(name.to_owned(), import_resolver);
} }
@ -58,16 +58,16 @@ impl ProgramInstance {
pub fn add_host_module( pub fn add_host_module(
&mut self, &mut self,
name: &str, name: &str,
host_module: HostModule, host_module: HostModule<St>,
) { ) where St: 'static {
self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box<ImportResolver>); self.resolvers.insert(name.to_owned(), Box::new(host_module) as Box<ImportResolver<St>>);
} }
pub fn insert_loaded_module(&mut self, name: &str, module: Rc<ModuleInstance>) { pub fn insert_loaded_module(&mut self, name: &str, module: Rc<ModuleInstance<St>>) {
self.modules.insert(name.to_owned(), module); self.modules.insert(name.to_owned(), module);
} }
pub fn invoke_export<St: 'static>( pub fn invoke_export(
&mut self, &mut self,
module_name: &str, module_name: &str,
func_name: &str, func_name: &str,
@ -80,7 +80,7 @@ impl ProgramInstance {
module_instance.invoke_export(func_name, args, state) module_instance.invoke_export(func_name, args, state)
} }
pub fn invoke_index<St: 'static>( pub fn invoke_index(
&mut self, &mut self,
module_name: &str, module_name: &str,
func_idx: u32, func_idx: u32,
@ -93,16 +93,19 @@ impl ProgramInstance {
module_instance.invoke_index(func_idx, args, state) module_instance.invoke_index(func_idx, args, state)
} }
pub fn invoke_func<St: 'static>( pub fn invoke_func(
&mut self, &mut self,
func_instance: Rc<FuncInstance>, func_instance: Rc<FuncInstance<St>>,
args: Vec<RuntimeValue>, args: Vec<RuntimeValue>,
state: &mut St, state: &mut St,
) -> Result<Option<RuntimeValue>, Error> { ) -> Result<Option<RuntimeValue>, Error> {
FuncInstance::invoke(Rc::clone(&func_instance), args, state) FuncInstance::invoke(Rc::clone(&func_instance), args, state)
} }
pub fn module(&self, name: &str) -> Option<Rc<ModuleInstance>> { pub fn module(&self, name: &str) -> Option<&ImportResolver<St>> {
self.modules.get(name).cloned() self.modules
.get(name)
.map(|x| &**x as &ImportResolver<St>)
.or_else(|| self.resolvers.get(name).map(|x| &**x))
} }
} }

View File

@ -17,17 +17,17 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameTy
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
/// Function interpreter. /// Function interpreter.
pub struct Interpreter<'a, St: 'static> { pub struct Interpreter<'a, St: 'a> {
state: &'a mut St, state: &'a mut St,
} }
/// Function execution context. /// Function execution context.
pub struct FunctionContext { pub struct FunctionContext<St> {
/// Is context initialized. /// Is context initialized.
pub is_initialized: bool, pub is_initialized: bool,
/// Internal function reference. /// Internal function reference.
pub function: Rc<FuncInstance>, pub function: Rc<FuncInstance<St>>,
pub module: Rc<ModuleInstance>, pub module: Rc<ModuleInstance<St>>,
/// Function return type. /// Function return type.
pub return_type: BlockType, pub return_type: BlockType,
/// Local variables. /// Local variables.
@ -42,13 +42,13 @@ pub struct FunctionContext {
/// Interpreter action to execute after executing instruction. /// Interpreter action to execute after executing instruction.
#[derive(Debug)] #[derive(Debug)]
pub enum InstructionOutcome { pub enum InstructionOutcome<St> {
/// Continue with next instruction. /// Continue with next instruction.
RunNextInstruction, RunNextInstruction,
/// Branch to given frame. /// Branch to given frame.
Branch(usize), Branch(usize),
/// Execute function call. /// Execute function call.
ExecuteCall(Rc<FuncInstance>), ExecuteCall(Rc<FuncInstance<St>>),
/// End current frame. /// End current frame.
End, End,
/// Return from current function block. /// Return from current function block.
@ -56,21 +56,21 @@ pub enum InstructionOutcome {
} }
/// Function run result. /// Function run result.
enum RunResult { enum RunResult<St> {
/// 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(Rc<FuncInstance>), NestedCall(Rc<FuncInstance<St>>),
} }
impl<'a, St: 'static> Interpreter<'a, St> { impl<'a, St: 'a> Interpreter<'a, St> {
pub fn new(state: &'a mut St) -> Interpreter<'a, St> { pub fn new(state: &'a mut St) -> Interpreter<'a, St> {
Interpreter { Interpreter {
state state
} }
} }
pub fn run_function(&mut self, function_context: FunctionContext) -> Result<Option<RuntimeValue>, Error> { pub fn run_function(&mut self, function_context: FunctionContext<St>) -> Result<Option<RuntimeValue>, Error> {
let mut function_stack = VecDeque::new(); let mut function_stack = VecDeque::new();
function_stack.push_back(function_context); function_stack.push_back(function_context);
@ -117,7 +117,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
} }
fn do_run_function(&mut self, function_context: &mut FunctionContext, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult, Error> { fn do_run_function(&mut self, function_context: &mut FunctionContext<St>, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult<St>, Error> {
loop { loop {
let instruction = &function_body[function_context.position]; let instruction = &function_body[function_context.position];
@ -155,7 +155,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
})) }))
} }
fn run_instruction(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome, Error> { fn run_instruction(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<St>, Error> {
match opcode { match opcode {
&Opcode::Unreachable => self.run_unreachable(context), &Opcode::Unreachable => self.run_unreachable(context),
&Opcode::Nop => self.run_nop(context), &Opcode::Nop => self.run_nop(context),
@ -349,25 +349,25 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
} }
fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_unreachable(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
Err(Error::Trap("programmatic".into())) Err(Error::Trap("programmatic".into()))
} }
fn run_nop(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_nop(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_block(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> { fn run_block(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
context.push_frame(labels, BlockFrameType::Block, block_type)?; context.push_frame(labels, BlockFrameType::Block, block_type)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_loop(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> { fn run_loop(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
context.push_frame(labels, BlockFrameType::Loop, block_type)?; context.push_frame(labels, BlockFrameType::Loop, block_type)?;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_if(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Error> { fn run_if(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<St>, Error> {
let branch = context.value_stack_mut().pop_as()?; let branch = context.value_stack_mut().pop_as()?;
let block_frame_type = if branch { BlockFrameType::IfTrue } else { let block_frame_type = if branch { BlockFrameType::IfTrue } else {
let else_pos = labels[&context.position]; let else_pos = labels[&context.position];
@ -382,23 +382,23 @@ impl<'a, St: 'static> Interpreter<'a, St> {
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction) context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_else(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome, Error> { fn run_else(&mut self, context: &mut FunctionContext<St>, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<St>, Error> {
let end_pos = labels[&context.position]; let end_pos = labels[&context.position];
context.pop_frame(false)?; context.pop_frame(false)?;
context.position = end_pos; context.position = end_pos;
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_end(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_end(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
context.pop_frame(false)?; context.pop_frame(false)?;
Ok(InstructionOutcome::End) Ok(InstructionOutcome::End)
} }
fn run_br(&mut self, _context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> { fn run_br(&mut self, _context: &mut FunctionContext<St>, label_idx: u32) -> Result<InstructionOutcome<St>, Error> {
Ok(InstructionOutcome::Branch(label_idx as usize)) Ok(InstructionOutcome::Branch(label_idx as usize))
} }
fn run_br_if(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Error> { fn run_br_if(&mut self, context: &mut FunctionContext<St>, label_idx: u32) -> Result<InstructionOutcome<St>, Error> {
if context.value_stack_mut().pop_as()? { if context.value_stack_mut().pop_as()? {
Ok(InstructionOutcome::Branch(label_idx as usize)) Ok(InstructionOutcome::Branch(label_idx as usize))
} else { } else {
@ -406,20 +406,20 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
} }
fn run_br_table(&mut self, context: &mut FunctionContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome, Error> { fn run_br_table(&mut self, context: &mut FunctionContext<St>, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome<St>, Error> {
let index: u32 = context.value_stack_mut().pop_as()?; let index: u32 = context.value_stack_mut().pop_as()?;
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize)) Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
} }
fn run_return(&mut self, _context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_return(&mut self, _context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
Ok(InstructionOutcome::Return) Ok(InstructionOutcome::Return)
} }
fn run_call( fn run_call(
&mut self, &mut self,
context: &mut FunctionContext, context: &mut FunctionContext<St>,
func_idx: u32, func_idx: u32,
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome<St>, Error> {
let func = context let func = context
.module() .module()
.func_by_index(func_idx) .func_by_index(func_idx)
@ -429,9 +429,9 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_call_indirect( fn run_call_indirect(
&mut self, &mut self,
context: &mut FunctionContext, context: &mut FunctionContext<St>,
type_idx: u32, type_idx: u32,
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome<St>, Error> {
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()
@ -458,7 +458,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::ExecuteCall(func_ref)) Ok(InstructionOutcome::ExecuteCall(func_ref))
} }
fn run_drop(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_drop(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
context context
.value_stack_mut() .value_stack_mut()
.pop() .pop()
@ -466,7 +466,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_select(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_select(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
context context
.value_stack_mut() .value_stack_mut()
.pop_triple() .pop_triple()
@ -482,19 +482,19 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_get_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> { fn run_get_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
context.get_local(index as usize) context.get_local(index as usize)
.map(|value| context.value_stack_mut().push(value)) .map(|value| context.value_stack_mut().push(value))
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_set_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> { fn run_set_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
let arg = context.value_stack_mut().pop()?; let arg = context.value_stack_mut().pop()?;
context.set_local(index as usize, arg) context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_tee_local(&mut self, context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome, Error> { fn run_tee_local(&mut self, context: &mut FunctionContext<St>, index: u32) -> Result<InstructionOutcome<St>, Error> {
let arg = context.value_stack().top()?.clone(); let arg = context.value_stack().top()?.clone();
context.set_local(index as usize, arg) context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
@ -502,9 +502,9 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_get_global( fn run_get_global(
&mut self, &mut self,
context: &mut FunctionContext, context: &mut FunctionContext<St>,
index: u32, index: u32,
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome<St>, Error> {
let global = context let global = context
.module() .module()
.global_by_index(index) .global_by_index(index)
@ -516,9 +516,9 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_set_global( fn run_set_global(
&mut self, &mut self,
context: &mut FunctionContext, context: &mut FunctionContext<St>,
index: u32, index: u32,
) -> Result<InstructionOutcome, Error> { ) -> Result<InstructionOutcome<St>, Error> {
let val = context.value_stack_mut().pop()?; let val = context.value_stack_mut().pop()?;
let global = context let global = context
@ -529,7 +529,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_load<T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error> fn run_load<T>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
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()
@ -541,7 +541,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_load_extend<T, U>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error> fn run_load_extend<T, U>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
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()
@ -557,7 +557,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_store<T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Error> fn run_store<T>(&mut self, context: &mut FunctionContext<St>, _align: u32, offset: u32) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert { where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
let stack_value = context let stack_value = context
.value_stack_mut() .value_stack_mut()
@ -574,10 +574,10 @@ impl<'a, St: 'static> Interpreter<'a, St> {
fn run_store_wrap<T, U>( fn run_store_wrap<T, U>(
&mut self, &mut self,
context: &mut FunctionContext, context: &mut FunctionContext<St>,
_align: u32, _align: u32,
offset: u32, offset: u32,
) -> Result<InstructionOutcome, Error> ) -> Result<InstructionOutcome<St>, Error>
where where
RuntimeValue: TryInto<T, Error>, RuntimeValue: TryInto<T, Error>,
T: WrapInto<U>, T: WrapInto<U>,
@ -597,7 +597,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_current_memory(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error> {
let m = context.module() let m = context.module()
.memory_by_index(DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
.expect("Due to validation memory should exists"); .expect("Due to validation memory should exists");
@ -608,7 +608,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> { fn run_grow_memory(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, 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(DEFAULT_MEMORY_INDEX) .memory_by_index(DEFAULT_MEMORY_INDEX)
@ -620,7 +620,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
Ok(InstructionOutcome::RunNextInstruction) Ok(InstructionOutcome::RunNextInstruction)
} }
fn run_const(&mut self, context: &mut FunctionContext, val: RuntimeValue) -> Result<InstructionOutcome, Error> { fn run_const(&mut self, context: &mut FunctionContext<St>, val: RuntimeValue) -> Result<InstructionOutcome<St>, Error> {
context context
.value_stack_mut() .value_stack_mut()
.push(val) .push(val)
@ -628,7 +628,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_eqz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_eqz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
context context
.value_stack_mut() .value_stack_mut()
@ -638,7 +638,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_eq<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_eq<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -648,7 +648,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ne<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_ne<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> { where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -658,7 +658,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_lt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_lt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
context context
.value_stack_mut() .value_stack_mut()
@ -668,7 +668,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_gt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_gt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -678,7 +678,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_lte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_lte<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -688,7 +688,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_gte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_gte<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> { where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -698,7 +698,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_clz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_clz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -708,7 +708,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ctz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_ctz<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -718,7 +718,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_popcnt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_popcnt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -728,7 +728,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_add<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_add<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -738,7 +738,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_sub<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_sub<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -748,7 +748,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_mul<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_mul<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -758,7 +758,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_div<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_div<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -770,7 +770,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rem<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_rem<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -782,7 +782,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_and<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_and<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> { where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -792,7 +792,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_or<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_or<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> { where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -802,7 +802,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_xor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_xor<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> { where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -812,7 +812,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_shl<T>(&mut self, context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome, Error> fn run_shl<T>(&mut self, context: &mut FunctionContext<St>, mask: T) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> { where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
context context
.value_stack_mut() .value_stack_mut()
@ -822,7 +822,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_shr<T, U>(&mut self, context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome, Error> fn run_shr<T, U>(&mut self, context: &mut FunctionContext<St>, mask: U) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -834,7 +834,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rotl<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_rotl<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -844,7 +844,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_rotr<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_rotr<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -854,7 +854,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_abs<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_abs<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -864,7 +864,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_neg<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_neg<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg { where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg {
context context
.value_stack_mut() .value_stack_mut()
@ -874,7 +874,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_ceil<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_ceil<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -884,7 +884,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_floor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_floor<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -894,7 +894,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_trunc<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_trunc<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -904,7 +904,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_nearest<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_nearest<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -914,7 +914,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_sqrt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_sqrt<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -924,7 +924,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_min<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_min<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -934,7 +934,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_max<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_max<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -944,7 +944,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_copysign<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_copysign<T>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> { where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context context
.value_stack_mut() .value_stack_mut()
@ -954,7 +954,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_wrap<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_wrap<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> { where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
context context
.value_stack_mut() .value_stack_mut()
@ -964,7 +964,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_trunc_to_int<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_trunc_to_int<T, U, V>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, { where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, {
context context
.value_stack_mut() .value_stack_mut()
@ -975,7 +975,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_extend<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_extend<T, U, V>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> { where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> {
context context
.value_stack_mut() .value_stack_mut()
@ -987,7 +987,7 @@ impl<'a, St: 'static> Interpreter<'a, St> {
.map(|_| InstructionOutcome::RunNextInstruction) .map(|_| InstructionOutcome::RunNextInstruction)
} }
fn run_reinterpret<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Error> fn run_reinterpret<T, U>(&mut self, context: &mut FunctionContext<St>) -> Result<InstructionOutcome<St>, Error>
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> { where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> {
context context
.value_stack_mut() .value_stack_mut()
@ -998,8 +998,8 @@ impl<'a, St: 'static> Interpreter<'a, St> {
} }
} }
impl FunctionContext { impl<St> FunctionContext<St> {
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<St>>, 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 { ref module, .. } => Rc::clone(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"),
@ -1016,7 +1016,7 @@ impl FunctionContext {
} }
} }
pub fn nested(&mut self, function: Rc<FuncInstance>) -> Result<Self, Error> { pub fn nested(&mut self, function: Rc<FuncInstance<St>>) -> 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 { ref module, .. } => Rc::clone(module), FuncInstance::Internal { ref module, .. } => Rc::clone(module),
@ -1055,11 +1055,11 @@ impl FunctionContext {
self.locals.extend(locals); self.locals.extend(locals);
} }
pub fn module(&self) -> Rc<ModuleInstance> { pub fn module(&self) -> Rc<ModuleInstance<St>> {
Rc::clone(&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<St>, Error> {
let l = self.locals.get_mut(index) let l = self.locals.get_mut(index)
.ok_or(Error::Local(format!("expected to have local with index {}", index)))?; .ok_or(Error::Local(format!("expected to have local with index {}", index)))?;
@ -1137,7 +1137,7 @@ impl FunctionContext {
} }
} }
impl fmt::Debug for FunctionContext { impl<St> fmt::Debug for FunctionContext<St> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FunctionContext") write!(f, "FunctionContext")
} }

View File

@ -8,15 +8,15 @@ use interpreter::module::check_limits;
use interpreter::func::FuncInstance; use interpreter::func::FuncInstance;
/// Table instance. /// Table instance.
pub struct TableInstance { pub struct TableInstance<St> {
/// Table limits. /// Table limits.
limits: ResizableLimits, limits: ResizableLimits,
/// Table memory buffer. /// Table memory buffer.
buffer: RwLock<Vec<Option<Rc<FuncInstance>>>>, buffer: RwLock<Vec<Option<Rc<FuncInstance<St>>>>>,
} }
impl fmt::Debug for TableInstance { impl<St> fmt::Debug for TableInstance<St> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TableInstance") f.debug_struct("TableInstance")
.field("limits", &self.limits) .field("limits", &self.limits)
@ -25,7 +25,7 @@ impl fmt::Debug for TableInstance {
} }
} }
impl TableInstance { impl<St> TableInstance<St> {
/// New instance of the table /// New instance of the table
pub fn new(table_type: &TableType) -> Result<Self, Error> { pub fn new(table_type: &TableType) -> Result<Self, Error> {
check_limits(table_type.limits())?; check_limits(table_type.limits())?;
@ -43,7 +43,7 @@ impl TableInstance {
} }
/// Get the specific value in the table /// Get the specific value in the table
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> { pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance<St>>, 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).cloned().ok_or(Error::Table(format!( let table_elem = buffer.get(offset as usize).cloned().ok_or(Error::Table(format!(
@ -58,7 +58,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: Rc<FuncInstance>) -> Result<(), Error> { pub fn set(&self, offset: u32, value: Rc<FuncInstance<St>>) -> 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!(

View File

@ -121,7 +121,7 @@ struct TestState {
pub values: Vec<i32>, pub values: Vec<i32>,
} }
fn build_env_module() -> HostModule { fn build_env_module() -> HostModule<TestState> {
let mut builder = HostModuleBuilder::<TestState>::new(); let mut builder = HostModuleBuilder::<TestState>::new();
builder.with_func2("add", |state: &mut TestState, arg: i32, unused: i32| { builder.with_func2("add", |state: &mut TestState, arg: i32, unused: i32| {
let memory_value = state.memory.get(0, 1).unwrap()[0]; let memory_value = state.memory.get(0, 1).unwrap()[0];
@ -219,7 +219,7 @@ fn native_env_function() {
fn native_env_global() { fn native_env_global() {
struct State; struct State;
let module_constructor = |host_module: HostModule| { let module_constructor = |host_module: HostModule<State>| {
let mut program = ProgramInstance::new(); let mut program = ProgramInstance::new();
program.add_host_module("env", host_module); program.add_host_module("env", host_module);

View File

@ -3,27 +3,22 @@ mod wabt;
mod wasm; mod wasm;
mod utils { mod utils {
use elements::{Internal, ExportEntry, InitExpr, Opcode, ValueType, GlobalType, GlobalEntry}; use elements::{ExportEntry, InitExpr, Opcode, ValueType, GlobalType, GlobalEntry, MemoryType, TableType};
use interpreter::ProgramInstance; use interpreter::{ProgramInstance, HostModuleBuilder, MemoryInstance, TableInstance, GlobalInstance, RuntimeValue};
use builder::module; use std::rc::Rc;
pub fn program_with_default_env() -> ProgramInstance { pub fn program_with_default_env<St: 'static>() -> ProgramInstance<St> {
let mut program = ProgramInstance::new(); let mut program = ProgramInstance::<St>::new();
let env_module = module()
.memory() let mut builder = HostModuleBuilder::<St>::new();
.with_min(256) // 256 pages. 256 * 64K = 16MB // TODO: Alloc
.build() builder.insert_memory("memory", Rc::new(MemoryInstance::new(&MemoryType::new(256, None)).unwrap()));
.with_export(ExportEntry::new("memory".into(), Internal::Memory(0))) builder.insert_table("table", Rc::new(TableInstance::new(&TableType::new(64, None)).unwrap()));
.table() builder.insert_global("tableBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
.with_min(64) builder.insert_global("memoryBase", Rc::new(GlobalInstance::new(RuntimeValue::I32(0), false)));
.build() let env_host_module = builder.build();
.with_export(ExportEntry::new("table".into(), Internal::Table(0)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0), Opcode::End]))) program.add_host_module("env", env_host_module);
.with_export(ExportEntry::new("tableBase".into(), Internal::Global(0)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0), Opcode::End])))
.with_export(ExportEntry::new("memoryBase".into(), Internal::Global(1)))
.build();
program.add_module("env", env_module, &mut ()).unwrap();
program program
} }
} }

View File

@ -1,6 +1,6 @@
use elements::deserialize_file; use elements::deserialize_file;
use elements::Module; use elements::{Module, MemoryType};
use interpreter::value::RuntimeValue; use interpreter::RuntimeValue;
use super::utils::program_with_default_env; use super::utils::program_with_default_env;
#[test] #[test]
@ -46,8 +46,10 @@ fn interpreter_accumulate_u8() {
.add_module("main", module, &mut ()) .add_module("main", module, &mut ())
.expect("Failed to initialize module"); .expect("Failed to initialize module");
let env_module = program.module("env").unwrap(); let env_memory = {
let env_memory = env_module.memory_by_index(0).unwrap(); let env_module = program.module("env").unwrap();
env_module.resolve_memory("memory", &MemoryType::new(1, None)).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;