This commit is contained in:
Svyatoslav Nikolsky
2017-06-19 12:35:17 +03:00
parent ad390c95fd
commit 8a17a012c5
8 changed files with 39 additions and 54 deletions

View File

@ -104,7 +104,7 @@ fn run_action(program: &ProgramInstance, action: &test::Action)
let module = module.trim_left_matches('$');
let module = program.module(&module).expect(&format!("Expected program to have loaded module {}", module));
module.export_entry(field.as_ref(), None, &ExportEntryType::Any)
module.export_entry(field.as_ref(), &ExportEntryType::Any)
.and_then(|i| match i {
elements::Internal::Global(global_index) => Ok(ItemIndex::IndexSpace(global_index)),
_ => Err(InterpreterError::Global(format!("Expected to have exported global with name {}", field))),

View File

@ -104,8 +104,8 @@ impl ModuleInstanceInterface for EnvModuleInstance {
self.instance.execute_export(name, params)
}
fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error> {
self.instance.export_entry(name, externals, required_type)
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
self.instance.export_entry(name, required_type)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
@ -120,11 +120,11 @@ impl ModuleInstanceInterface for EnvModuleInstance {
self.instance.global(index, variable_type)
}
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
self.instance.function_type(function_index, externals)
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionType, Error> {
self.instance.function_type(function_index)
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionType, Error> {
self.instance.function_type_by_index(type_index)
}

View File

@ -1,7 +1,7 @@
use std::sync::Arc;
use std::collections::HashMap;
use parking_lot::RwLock;
use elements::{FunctionType, Internal, ValueType, Opcode};
use elements::{FunctionType, Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction};
@ -74,12 +74,13 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
self.env.execute_export(name, params)
}
fn export_entry<'b>(&self, name: &str, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>, required_type: &ExportEntryType) -> Result<Internal, Error> {
fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
if let Some(index) = self.by_name.get(name) {
// TODO: check type
return Ok(Internal::Function(NATIVE_INDEX_FUNC_MIN + *index));
}
self.env.export_entry(name, externals, required_type)
self.env.export_entry(name, required_type)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
@ -94,14 +95,14 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
self.env.global(index, variable_type)
}
fn function_type<'b>(&self, function_index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<FunctionType, Error> {
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionType, Error> {
let index = match function_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
};
if index < NATIVE_INDEX_FUNC_MIN {
return self.env.function_type(function_index, externals);
return self.env.function_type(function_index);
}
self.functions
@ -110,8 +111,8 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
.map(|f| FunctionType::new(f.params.clone(), f.result.clone()))
}
fn function_type_by_index<'b>(&self, type_index: u32) -> Result<FunctionType, Error> {
self.function_type(ItemIndex::Internal(type_index), None)
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionType, Error> {
self.function_type(ItemIndex::Internal(type_index))
}
fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
@ -139,6 +140,6 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
}
/// Create wrapper for env module with given native user functions.
pub fn env_native_module(env: Arc<ModuleInstanceInterface>, user_functions: UserFunctions) -> Result<NativeModuleInstance, Error> {
pub fn env_native_module<'a>(env: Arc<ModuleInstanceInterface>, user_functions: UserFunctions<'a>) -> Result<NativeModuleInstance, Error> {
NativeModuleInstance::new(env, user_functions)
}

View File

@ -161,7 +161,7 @@ impl ModuleImports {
fn external_export<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry, required_type: &ExportEntryType) -> Result<(Arc<ModuleInstanceInterface + 'a>, Internal), Error> {
self.module(externals, import.module())
.and_then(|m|
m.export_entry(import.field(), externals, required_type)
m.export_entry(import.field(), required_type)
.map(|e| (m, e)))
}
}

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::iter::repeat;
use std::sync::{Arc, Weak};
use std::fmt;
use elements::{Module, InitExpr, Opcode, Type, FunctionType, FuncBody, Internal, External, BlockType, ResizableLimits, Local};
use elements::{Module, InitExpr, Opcode, Type, FunctionType, Internal, External, BlockType, ResizableLimits, Local};
use interpreter::Error;
use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance;
@ -48,7 +48,7 @@ pub trait ModuleInstanceInterface {
/// Execute function with the given export name.
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>;
/// Get export entry.
fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error>;
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error>;
/// Get table reference.
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error>;
/// Get memory reference.
@ -56,9 +56,9 @@ pub trait ModuleInstanceInterface {
/// Get global reference.
fn global(&self, index: ItemIndex, variable_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error>;
/// Get function type for given function index.
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error>;
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionType, Error>;
/// Get function type for given function index.
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error>;
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionType, Error>;
/// Get function reference.
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>;
/// Get function indirect reference.
@ -66,7 +66,7 @@ pub trait ModuleInstanceInterface {
/// Get internal function for interpretation.
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error>;
/// Call function with given internal index.
fn call_internal_function<'a>(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error>;
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error>;
}
/// Item index in items index space.
@ -227,19 +227,6 @@ impl ModuleInstance {
}),
}
}
fn check_function_type(&self, function_index: ItemIndex, required_function_type: Option<&FunctionType>, externals: Option<&HashMap<String, Arc<ModuleInstanceInterface>>>) -> Result<(), Error> {
if let Some(ref required_function_type) = required_function_type {
let actual_function_type = self.function_type(function_index, externals)?;
if **required_function_type != actual_function_type {
return Err(Error::Function(format!("expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
actual_function_type.params(), actual_function_type.return_type())));
}
}
Ok(())
}
}
impl ModuleInstanceInterface for ModuleInstance {
@ -289,12 +276,12 @@ impl ModuleInstanceInterface for ModuleInstance {
// get export entry in external module
let external_module = self.imports.module(externals, import.module())?;
let export_entry = external_module.export_entry(import.field(), externals, &ExportEntryType::Function(import_function_type.clone()))?;
let export_entry = external_module.export_entry(import.field(), &ExportEntryType::Function(import_function_type.clone()))?;
// export entry points to function in function index space
// and Internal::Function points to type in type section
let export_function_type = match export_entry {
Internal::Function(function_index) => external_module.function_type(ItemIndex::IndexSpace(function_index), externals)?,
Internal::Function(function_index) => external_module.function_type(ItemIndex::IndexSpace(function_index))?,
_ => return Err(Error::Validation(format!("Export with name {} from module {} is not a function", import.field(), import.module()))),
};
@ -413,7 +400,7 @@ impl ModuleInstanceInterface for ModuleInstance {
self.execute_index(index, params)
}
fn export_entry<'a>(&self, name: &str, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, required_type: &ExportEntryType) -> Result<Internal, Error> {
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
self.module.export_section()
.ok_or(Error::Program(format!("trying to import {} from module without export section", name)))
.and_then(|s| s.entries().iter()
@ -425,7 +412,7 @@ impl ModuleInstanceInterface for ModuleInstance {
},
&ExportEntryType::Function(ref required_type) => match e.internal() {
&Internal::Function(function_index) =>
self.function_type(ItemIndex::IndexSpace(function_index), externals)
self.function_type(ItemIndex::IndexSpace(function_index))
.map(|ft| &ft == required_type)
.unwrap_or(false),
_ => false,
@ -474,7 +461,7 @@ impl ModuleInstanceInterface for ModuleInstance {
}
}
fn function_type<'a>(&self, function_index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<FunctionType, Error> {
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionType, Error> {
match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index))
@ -490,7 +477,7 @@ impl ModuleInstanceInterface for ModuleInstance {
}
}
fn function_type_by_index<'a>(&self, type_index: u32) -> Result<FunctionType, Error> {
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionType, Error> {
self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index)))
.and_then(|s| match s.types().get(type_index as usize) {
@ -512,7 +499,7 @@ impl ModuleInstanceInterface for ModuleInstance {
.expect("parse_function_index has returned External(index); it is only returned when import section exists; qed")
.entries().get(index as usize)
.expect("parse_function_index has returned External(index); it is only returned when entry with index exists in import section exists; qed");
let required_function_type = self.function_type(ItemIndex::External(index), externals)?;
let required_function_type = self.function_type(ItemIndex::External(index))?;
let internal_function_index = self.imports.function(externals, import_entry, Some(&required_function_type))?;
Ok(InternalFunctionReference {
module: self.imports.module(externals, import_entry.module())?,
@ -531,7 +518,7 @@ impl ModuleInstanceInterface for ModuleInstance {
let module = self.imports.module(externals, &module)?;
let required_function_type = self.function_type_by_index(type_idx)?;
let actual_function_type = module.function_type(ItemIndex::IndexSpace(index), externals)?;
let actual_function_type = module.function_type(ItemIndex::IndexSpace(index))?;
if required_function_type != actual_function_type {
return Err(Error::Function(format!("expected indirect function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
@ -556,8 +543,8 @@ impl ModuleInstanceInterface for ModuleInstance {
}
fn call_internal_function(&self, mut outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
let function_type = self.function_type(ItemIndex::Internal(index), None)?;
let mut args = prepare_function_args(&function_type, outer.value_stack)?;
let function_type = self.function_type(ItemIndex::Internal(index))?;
let args = prepare_function_args(&function_type, outer.value_stack)?;
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index };
let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
Interpreter::run_function(inner)

View File

@ -7,7 +7,7 @@ use std::iter::repeat;
use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, FunctionType, Local};
use interpreter::Error;
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, CallerContext, ItemIndex, InternalFunctionReference};
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, InternalFunctionReference};
use interpreter::stack::StackWithLimit;
use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
@ -220,8 +220,8 @@ impl Interpreter {
match opcode {
&Opcode::Unreachable => Interpreter::run_unreachable(context),
&Opcode::Nop => Interpreter::run_nop(context),
&Opcode::Block(block_type, ref ops) => Interpreter::run_block(context, block_type, ops.elements()),
&Opcode::Loop(block_type, ref ops) => Interpreter::run_loop(context, block_type, ops.elements()),
&Opcode::Block(block_type, _) => Interpreter::run_block(context, block_type),
&Opcode::Loop(block_type, _) => Interpreter::run_loop(context, block_type),
&Opcode::If(block_type, ref ops) => Interpreter::run_if(context, block_type, ops.elements()),
&Opcode::Else => Interpreter::run_else(context),
&Opcode::End => Interpreter::run_end(context),
@ -438,13 +438,13 @@ impl Interpreter {
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_block<'a, 'b>(context: &'b mut FunctionContext<'a>, block_type: BlockType, body: &[Opcode]) -> Result<InstructionOutcome<'a>, Error> {
fn run_block<'a, 'b>(context: &'b mut FunctionContext<'a>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
let frame_position = context.position;
context.push_frame(BlockFrameType::Block, frame_position, frame_position + 1, frame_position + 1, block_type)?;
Ok(InstructionOutcome::ExecuteBlock)
}
fn run_loop<'a, 'b>(context: &'b mut FunctionContext<'a>, block_type: BlockType, body: &[Opcode]) -> Result<InstructionOutcome<'a>, Error> {
fn run_loop<'a, 'b>(context: &'b mut FunctionContext<'a>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
let frame_position = context.position;
context.push_frame(BlockFrameType::Loop, frame_position, frame_position, frame_position + 1, block_type)?;
Ok(InstructionOutcome::ExecuteBlock)
@ -501,7 +501,7 @@ impl Interpreter {
let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
let function_reference = context.module().function_reference_indirect(DEFAULT_TABLE_INDEX, type_idx, table_func_idx, Some(context.externals))?;
let required_function_type = context.module().function_type_by_index(type_idx)?;
let actual_function_type = function_reference.module.function_type(ItemIndex::Internal(function_reference.internal_index), Some(context.externals))?;
let actual_function_type = function_reference.module.function_type(ItemIndex::Internal(function_reference.internal_index))?;
if required_function_type != actual_function_type {
return Err(Error::Function(format!("expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
required_function_type.params(), required_function_type.return_type(),
@ -1022,7 +1022,7 @@ impl<'a> FunctionContext<'a> {
}
pub fn nested(&mut self, function: InternalFunctionReference<'a>) -> Result<Self, Error> {
let function_type = function.module.function_type(ItemIndex::Internal(function.internal_index), Some(self.externals))?;
let function_type = function.module.function_type(ItemIndex::Internal(function.internal_index))?;
let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult);
let function_locals = prepare_function_args(&function_type, &mut self.value_stack)?;

View File

@ -46,14 +46,12 @@ impl<T> StackWithLimit<T> where T: Clone {
self.values
.back()
.ok_or(Error::Stack("non-empty stack expected".into()))
.map_err(|e| { panic!("1") })
}
pub fn top_mut(&mut self) -> Result<&mut T, Error> {
self.values
.back_mut()
.ok_or(Error::Stack("non-empty stack expected".into()))
.map_err(|e| { panic!("2") })
}
pub fn get(&self, index: usize) -> Result<&T, Error> {
@ -90,7 +88,6 @@ impl<T> StackWithLimit<T> where T: Clone {
self.values
.pop_back()
.ok_or(Error::Stack("non-empty stack expected".into()))
.map_err(|e| { panic!("3") })
}
pub fn resize(&mut self, new_size: usize, dummy: T) {

View File

@ -807,7 +807,7 @@ fn callindirect_2() {
assert_eq!(module.execute_index(3, vec![RuntimeValue::I32(10), RuntimeValue::I32(4), RuntimeValue::I32(0)].into()).unwrap().unwrap(), RuntimeValue::I32(14));
assert_eq!(module.execute_index(3, vec![RuntimeValue::I32(10), RuntimeValue::I32(4), RuntimeValue::I32(1)].into()).unwrap().unwrap(), RuntimeValue::I32(6));
assert_eq!(module.execute_index(3, vec![RuntimeValue::I32(10), RuntimeValue::I32(4), RuntimeValue::I32(2)].into()).unwrap_err(),
Error::Function("expected function with signature ([I32, I32]) -> Some(I32) when got with ([I32]) -> Some(I32)".into()));
Error::Function("expected indirect function with signature ([I32, I32]) -> Some(I32) when got with ([I32]) -> Some(I32)".into()));
assert_eq!(module.execute_index(3, vec![RuntimeValue::I32(10), RuntimeValue::I32(4), RuntimeValue::I32(3)].into()).unwrap_err(),
Error::Table("trying to read table item with index 3 when there are only 3 items".into()));
}