This commit is contained in:
Sergey Pepyakin
2017-12-18 16:46:04 +03:00
parent 9618feffd7
commit 3b74431dee
6 changed files with 88 additions and 89 deletions

View File

@ -2,7 +2,7 @@ use std::rc::Rc;
use std::fmt; use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
use std::borrow::Cow; use std::borrow::Cow;
use elements::{FunctionType, Opcodes, Local}; use elements::{FunctionType, Local, Opcodes};
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::HostFunc; use interpreter::host::HostFunc;
@ -30,12 +30,14 @@ impl<St: fmt::Debug> fmt::Debug for FuncInstance<St> {
ref func_type, ref func_type,
ref module, ref module,
.. ..
} => write!( } => {
write!(
f, f,
"Internal {{ type={:?}, module={:?} }}", "Internal {{ type={:?}, module={:?} }}",
func_type, func_type,
module module
), )
}
&FuncInstance::Host { ref func_type, .. } => { &FuncInstance::Host { ref func_type, .. } => {
write!(f, "Host {{ type={:?} }}", func_type) write!(f, "Host {{ type={:?} }}", func_type)
} }
@ -57,10 +59,7 @@ impl<St> FuncInstance<St> {
Rc::new(func) Rc::new(func)
} }
pub fn alloc_host( pub fn alloc_host(func_type: Rc<FunctionType>, host_func: Rc<HostFunc<St>>) -> Rc<Self> {
func_type: Rc<FunctionType>,
host_func: Rc<HostFunc<St>>,
) -> Rc<Self> {
let func = FuncInstance::Host { let func = FuncInstance::Host {
func_type, func_type,
host_func, host_func,
@ -94,7 +93,8 @@ impl<St> FuncInstance<St> {
let result = match *func { let result = match *func {
FuncInstance::Internal { ref func_type, .. } => { FuncInstance::Internal { ref func_type, .. } => {
let mut stack = StackWithLimit::with_data(args.into_iter().cloned(), DEFAULT_VALUE_STACK_LIMIT); let mut stack =
StackWithLimit::with_data(args.into_iter().cloned(), DEFAULT_VALUE_STACK_LIMIT);
let args = prepare_function_args(func_type, &mut stack)?; let args = prepare_function_args(func_type, &mut stack)?;
let context = FunctionContext::new( let context = FunctionContext::new(
Rc::clone(&func), Rc::clone(&func),

View File

@ -19,7 +19,10 @@ impl GlobalInstance {
pub fn set(&self, val: RuntimeValue) -> Result<(), Error> { pub fn set(&self, val: RuntimeValue) -> Result<(), Error> {
assert!(self.mutable, "Attempt to change an immutable variable"); assert!(self.mutable, "Attempt to change an immutable variable");
assert!(self.value_type() == val.value_type(), "Attempt to change variable type"); assert!(
self.value_type() == val.value_type(),
"Attempt to change variable type"
);
self.val.set(val); self.val.set(val);
Ok(()) Ok(())
} }

View File

@ -19,12 +19,14 @@ impl<'a, St: 'a> Default for Imports<'a, St> {
impl<'a, St: 'a> Imports<'a, St> { impl<'a, St: 'a> Imports<'a, St> {
pub fn new() -> 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<St>) -> Self { 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
} }

View File

@ -166,23 +166,23 @@ impl<St> ModuleInstance<St> {
} }
{ {
let imports = module let imports = module.import_section().map(|is| is.entries()).unwrap_or(
.import_section() &[],
.map(|is| is.entries()) );
.unwrap_or(&[]);
if imports.len() != extern_vals.len() { if imports.len() != extern_vals.len() {
return Err(Error::Instatiation(format!( return Err(Error::Instatiation(format!(
"extern_vals length is not equal to import section entries" "extern_vals length is not equal to import section entries"
))); )));
} }
for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter()) for (import, extern_val) in
Iterator::zip(imports.into_iter(), extern_vals.into_iter())
{ {
match (import.external(), extern_val) { match (import.external(), extern_val) {
(&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => { (&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => {
let expected_fn_type = instance let expected_fn_type = instance.type_by_index(fn_type_idx).expect(
.type_by_index(fn_type_idx) "Due to validation function type should exists",
.expect("Due to validation function type should exists"); );
let actual_fn_type = func.func_type(); let actual_fn_type = func.func_type();
if expected_fn_type != actual_fn_type { if expected_fn_type != actual_fn_type {
return Err(Error::Instatiation(format!( return Err(Error::Instatiation(format!(
@ -224,10 +224,9 @@ impl<St> ModuleInstance<St> {
} }
{ {
let funcs = module let funcs = module.function_section().map(|fs| fs.entries()).unwrap_or(
.function_section() &[],
.map(|fs| fs.entries()) );
.unwrap_or(&[]);
let bodies = module.code_section().map(|cs| cs.bodies()).unwrap_or(&[]); let bodies = module.code_section().map(|cs| cs.bodies()).unwrap_or(&[]);
debug_assert!( debug_assert!(
funcs.len() == bodies.len(), funcs.len() == bodies.len(),
@ -237,9 +236,9 @@ impl<St> ModuleInstance<St> {
for (index, (ty, body)) in for (index, (ty, body)) in
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate() Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
{ {
let func_type = instance let func_type = instance.type_by_index(ty.type_ref()).expect(
.type_by_index(ty.type_ref()) "Due to validation type should exists",
.expect("Due to validation type should exists"); );
let labels = aux_data.labels.remove(&index).expect( let labels = aux_data.labels.remove(&index).expect(
"At func validation time labels are collected; Collected labels are added by index; qed", "At func validation time labels are collected; Collected labels are added by index; qed",
); );
@ -259,54 +258,51 @@ impl<St> ModuleInstance<St> {
instance.push_table(table); instance.push_table(table);
} }
for memory_type in module for memory_type in module.memory_section().map(|ms| ms.entries()).unwrap_or(
.memory_section() &[],
.map(|ms| ms.entries()) )
.unwrap_or(&[])
{ {
let memory = alloc_memory(memory_type)?; let memory = alloc_memory(memory_type)?;
instance.push_memory(memory); instance.push_memory(memory);
} }
for global_entry in module for global_entry in module.global_section().map(|gs| gs.entries()).unwrap_or(
.global_section() &[],
.map(|gs| gs.entries()) )
.unwrap_or(&[])
{ {
let init_val = eval_init_expr(global_entry.init_expr(), &*instance); let init_val = eval_init_expr(global_entry.init_expr(), &*instance);
let global = alloc_global(global_entry.global_type().clone(), init_val); let global = alloc_global(global_entry.global_type().clone(), init_val);
instance.push_global(global); instance.push_global(global);
} }
for export in module for export in module.export_section().map(|es| es.entries()).unwrap_or(
.export_section() &[],
.map(|es| es.entries()) )
.unwrap_or(&[])
{ {
let field = export.field(); let field = export.field();
let extern_val: ExternVal<St> = 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).expect(
.func_by_index(idx) "Due to validation func should exists",
.expect("Due to validation func should exists"); );
ExternVal::Func(func) ExternVal::Func(func)
} }
Internal::Global(idx) => { Internal::Global(idx) => {
let global = instance let global = instance.global_by_index(idx).expect(
.global_by_index(idx) "Due to validation global should exists",
.expect("Due to validation global should exists"); );
ExternVal::Global(global) ExternVal::Global(global)
} }
Internal::Memory(idx) => { Internal::Memory(idx) => {
let memory = instance let memory = instance.memory_by_index(idx).expect(
.memory_by_index(idx) "Due to validation memory should exists",
.expect("Due to validation memory should exists"); );
ExternVal::Memory(memory) ExternVal::Memory(memory)
} }
Internal::Table(idx) => { Internal::Table(idx) => {
let table = instance let table = instance.table_by_index(idx).expect(
.table_by_index(idx) "Due to validation table should exists",
.expect("Due to validation table should exists"); );
ExternVal::Table(table) ExternVal::Table(table)
} }
}; };
@ -324,23 +320,22 @@ impl<St> ModuleInstance<St> {
ModuleInstance::alloc_module(module, extern_vals, &instance)?; ModuleInstance::alloc_module(module, extern_vals, &instance)?;
for element_segment in module for element_segment in module.elements_section().map(|es| es.entries()).unwrap_or(
.elements_section() &[],
.map(|es| es.entries()) )
.unwrap_or(&[])
{ {
let offset_val = match eval_init_expr(element_segment.offset(), &instance) { let offset_val = match eval_init_expr(element_segment.offset(), &instance) {
RuntimeValue::I32(v) => v as u32, RuntimeValue::I32(v) => v as u32,
_ => panic!("Due to validation elem segment offset should evaluate to i32"), _ => panic!("Due to validation elem segment offset should evaluate to i32"),
}; };
let table_inst = instance let table_inst = instance.table_by_index(DEFAULT_TABLE_INDEX).expect(
.table_by_index(DEFAULT_TABLE_INDEX) "Due to validation default table should exists",
.expect("Due to validation default table should exists"); );
for (j, func_idx) in element_segment.members().into_iter().enumerate() { for (j, func_idx) in element_segment.members().into_iter().enumerate() {
let func = instance let func = instance.func_by_index(*func_idx).expect(
.func_by_index(*func_idx) "Due to validation funcs from element segments should exists",
.expect("Due to validation funcs from element segments should exists"); );
table_inst.set(offset_val + j as u32, func)?; table_inst.set(offset_val + j as u32, func)?;
} }
@ -352,9 +347,9 @@ impl<St> ModuleInstance<St> {
_ => panic!("Due to validation data segment offset should evaluate to i32"), _ => panic!("Due to validation data segment offset should evaluate to i32"),
}; };
let memory_inst = instance let memory_inst = instance.memory_by_index(DEFAULT_MEMORY_INDEX).expect(
.memory_by_index(DEFAULT_MEMORY_INDEX) "Due to validation default memory should exists",
.expect("Due to validation default memory should exists"); );
memory_inst.set(offset_val, data_segment.value())?; memory_inst.set(offset_val, data_segment.value())?;
} }
@ -481,9 +476,9 @@ impl<'a, St: 'a> InstantiationBuilder<'a, St> {
let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?; let instance = ModuleInstance::instantiate_with_imports(self.module, imports)?;
if let Some(start_fn_idx) = self.module.start_section() { if let Some(start_fn_idx) = self.module.start_section() {
let start_func = instance let start_func = instance.func_by_index(start_fn_idx).expect(
.func_by_index(start_fn_idx) "Due to validation start function should exists",
.expect("Due to validation start function should exists"); );
FuncInstance::invoke(start_func, Cow::Borrowed(&[]), state)?; FuncInstance::invoke(start_func, Cow::Borrowed(&[]), state)?;
} }
Ok(instance) Ok(instance)
@ -590,9 +585,9 @@ fn eval_init_expr<T>(init_expr: &InitExpr, module: &ModuleInstance<T>) -> Runtim
Opcode::F32Const(v) => RuntimeValue::decode_f32(v), Opcode::F32Const(v) => RuntimeValue::decode_f32(v),
Opcode::F64Const(v) => RuntimeValue::decode_f64(v), Opcode::F64Const(v) => RuntimeValue::decode_f64(v),
Opcode::GetGlobal(idx) => { Opcode::GetGlobal(idx) => {
let global = module let global = module.global_by_index(idx).expect(
.global_by_index(idx) "Due to validation global should exists in module",
.expect("Due to validation global should exists in module"); );
global.get() global.get()
} }
_ => panic!("Due to validation init should be a const expr"), _ => panic!("Due to validation init should be a const expr"),

View File

@ -2,7 +2,7 @@ use std::u32;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use elements::{TableType, ResizableLimits}; use elements::{ResizableLimits, TableType};
use interpreter::Error; use interpreter::Error;
use interpreter::module::check_limits; use interpreter::module::check_limits;
use interpreter::func::FuncInstance; use interpreter::func::FuncInstance;
@ -13,7 +13,6 @@ pub struct TableInstance<St> {
limits: ResizableLimits, limits: ResizableLimits,
/// Table memory buffer. /// Table memory buffer.
buffer: RefCell<Vec<Option<Rc<FuncInstance<St>>>>>, buffer: RefCell<Vec<Option<Rc<FuncInstance<St>>>>>,
} }
impl<St> fmt::Debug for TableInstance<St> { impl<St> fmt::Debug for TableInstance<St> {
@ -31,9 +30,7 @@ impl<St> TableInstance<St> {
check_limits(table_type.limits())?; check_limits(table_type.limits())?;
Ok(TableInstance { Ok(TableInstance {
limits: table_type.limits().clone(), limits: table_type.limits().clone(),
buffer: RefCell::new( buffer: RefCell::new(vec![None; table_type.limits().initial() as usize]),
vec![None; table_type.limits().initial() as usize]
),
}) })
} }
@ -46,11 +43,13 @@ impl<St> TableInstance<St> {
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance<St>>, Error> { pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance<St>>, Error> {
let buffer = self.buffer.borrow(); let buffer = self.buffer.borrow();
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!(
"trying to read table item with index {} when there are only {} items", "trying to read table item with index {} when there are only {} items",
offset, offset,
buffer_len buffer_len
)))?; )),
)?;
Ok(table_elem.ok_or(Error::Table(format!( Ok(table_elem.ok_or(Error::Table(format!(
"trying to read uninitialized element on index {}", "trying to read uninitialized element on index {}",
offset offset