This commit is contained in:
Sergey Pepyakin 2017-12-18 16:12:59 +03:00
parent 569d89357f
commit e74b47758a
2 changed files with 55 additions and 39 deletions

View File

@ -1,7 +1,7 @@
use std::rc::Rc; use std::rc::Rc;
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, GlobalType, MemoryType, TableType, ValueType};
use interpreter::module::{ExternVal, ModuleInstance}; use interpreter::module::{ExternVal, ModuleInstance};
use interpreter::func::FuncInstance; use interpreter::func::FuncInstance;
use interpreter::global::GlobalInstance; use interpreter::global::GlobalInstance;
@ -11,7 +11,8 @@ use interpreter::value::{RuntimeValue, TryInto};
use interpreter::Error; use interpreter::Error;
use interpreter::ImportResolver; use interpreter::ImportResolver;
pub type HostFunc<St> = Fn(&St, &[RuntimeValue]) -> Result<Option<RuntimeValue>, Error>; pub type HostFunc<St> = Fn(&St, &[RuntimeValue])
-> Result<Option<RuntimeValue>, Error>;
pub struct HostModuleBuilder<St> { pub struct HostModuleBuilder<St> {
exports: HashMap<String, ExternVal<St>>, exports: HashMap<String, ExternVal<St>>,
@ -34,10 +35,12 @@ impl<St> HostModuleBuilder<St> {
f: Cl, f: Cl,
) { ) {
let func_type = FunctionType::new(vec![], Ret::value_type()); let func_type = FunctionType::new(vec![], Ret::value_type());
let host_func = Rc::new(move |state: &St, _args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> { let host_func = Rc::new(
let result = f(state)?.into_return_val(); move |state: &St, _args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
Ok(result) let result = f(state)?.into_return_val();
}); Ok(result)
},
);
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);
@ -54,11 +57,13 @@ impl<St> HostModuleBuilder<St> {
f: Cl, f: Cl,
) { ) {
let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type()); let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type());
let host_func = Rc::new(move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> { let host_func = Rc::new(
let arg0 = P1::from_arg(&args[0]); move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let result = f(state, arg0)?.into_return_val(); let arg0 = P1::from_arg(&args[0]);
Ok(result) let result = f(state, arg0)?.into_return_val();
}); Ok(result)
},
);
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);
@ -75,13 +80,16 @@ impl<St> HostModuleBuilder<St> {
name: N, name: N,
f: Cl, f: Cl,
) { ) {
let func_type = FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type()); let func_type =
let host_func = Rc::new(move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> { FunctionType::new(vec![P1::value_type(), P2::value_type()], Ret::value_type());
let p1 = P1::from_arg(&args[0]); let host_func = Rc::new(
let p2 = P2::from_arg(&args[1]); move |state: &St, args: &[RuntimeValue]| -> Result<Option<RuntimeValue>, Error> {
let result = f(state, p1, p2)?.into_return_val(); let p1 = P1::from_arg(&args[0]);
Ok(result) let p2 = P2::from_arg(&args[1]);
}); let result = f(state, p1, p2)?.into_return_val();
Ok(result)
},
);
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);
@ -127,9 +135,7 @@ impl<St> HostModuleBuilder<St> {
pub fn build(self) -> HostModule<St> { 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
}
} }
} }
@ -157,7 +163,8 @@ impl<St> ImportResolver<St> for HostModule<St> {
field_name: &str, field_name: &str,
global_type: &GlobalType, global_type: &GlobalType,
) -> Result<Rc<GlobalInstance>, Error> { ) -> Result<Rc<GlobalInstance>, Error> {
self.internal_instance.resolve_global(field_name, global_type) self.internal_instance
.resolve_global(field_name, global_type)
} }
fn resolve_memory( fn resolve_memory(
@ -165,7 +172,8 @@ impl<St> ImportResolver<St> for HostModule<St> {
field_name: &str, field_name: &str,
memory_type: &MemoryType, memory_type: &MemoryType,
) -> Result<Rc<MemoryInstance>, Error> { ) -> Result<Rc<MemoryInstance>, Error> {
self.internal_instance.resolve_memory(field_name, memory_type) self.internal_instance
.resolve_memory(field_name, memory_type)
} }
fn resolve_table( fn resolve_table(
@ -177,7 +185,10 @@ impl<St> ImportResolver<St> for HostModule<St> {
} }
} }
pub trait FromArg where Self: Sized { pub trait FromArg
where
Self: Sized,
{
fn from_arg(arg: &RuntimeValue) -> Self; fn from_arg(arg: &RuntimeValue) -> Self;
fn value_type() -> ValueType; fn value_type() -> ValueType;
} }

View File

@ -3,12 +3,12 @@ use std::cell::RefCell;
use std::fmt; use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
use std::borrow::Cow; use std::borrow::Cow;
use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module, use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryType, Module, Opcode,
Opcode, ResizableLimits, TableType, Type}; ResizableLimits, TableType, Type};
use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance}; use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance};
use interpreter::imports::{ImportResolver, Imports}; use interpreter::imports::{ImportResolver, Imports};
use interpreter::global::GlobalInstance; use interpreter::global::GlobalInstance;
use interpreter::func::{FuncInstance, FuncBody}; use interpreter::func::{FuncBody, FuncInstance};
use validation::validate_module; use validation::validate_module;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
@ -32,12 +32,16 @@ impl<St> Clone for ExternVal<St> {
impl<St> fmt::Debug for ExternVal<St> { impl<St> fmt::Debug for ExternVal<St> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ExternVal {{ {} }}", match *self { write!(
ExternVal::Func(_) => "Func", f,
ExternVal::Table(_) => "Table", "ExternVal {{ {} }}",
ExternVal::Memory(_) => "Memory", match *self {
ExternVal::Global(_) => "Global", ExternVal::Func(_) => "Func",
}) ExternVal::Table(_) => "Table",
ExternVal::Memory(_) => "Memory",
ExternVal::Global(_) => "Global",
}
)
} }
} }
@ -244,11 +248,8 @@ impl<St> ModuleInstance<St> {
opcodes: body.code().clone(), opcodes: body.code().clone(),
labels: labels, labels: labels,
}; };
let func_instance = FuncInstance::alloc_internal( let func_instance =
Rc::clone(instance), FuncInstance::alloc_internal(Rc::clone(instance), func_type, func_body);
func_type,
func_body
);
instance.push_func(func_instance); instance.push_func(func_instance);
} }
} }
@ -625,7 +626,11 @@ fn match_limits(l1: &ResizableLimits, l2: &ResizableLimits) -> Result<(), Error>
pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> { pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
if let Some(maximum) = limits.maximum() { if let Some(maximum) = limits.maximum() {
if maximum < limits.initial() { if maximum < limits.initial() {
return Err(Error::Validation(format!("maximum limit {} is lesser than minimum {}", maximum, limits.initial()))); return Err(Error::Validation(format!(
"maximum limit {} is lesser than minimum {}",
maximum,
limits.initial()
)));
} }
} }