Migrate on Signature type.

This commit is contained in:
Sergey Pepyakin 2018-01-18 15:48:43 +03:00
parent fa1cba92c9
commit e9470373f7
7 changed files with 103 additions and 78 deletions

View File

@ -3,7 +3,7 @@ use std::fmt;
use std::collections::HashMap;
use std::borrow::Cow;
use parity_wasm::elements::{FunctionType, Local, Opcodes};
use Error;
use {Error, Signature};
use host::Externals;
use runner::{prepare_function_args, FunctionContext, Interpreter};
use value::RuntimeValue;
@ -24,12 +24,12 @@ impl ::std::ops::Deref for FuncRef {
#[derive(Clone)]
pub enum FuncInstance {
Internal {
func_type: Rc<FunctionType>,
signature: Rc<Signature>,
module: ModuleRef,
body: Rc<FuncBody>,
},
Host {
func_type: FunctionType,
signature: Signature,
host_func_index: usize,
},
}
@ -38,19 +38,19 @@ impl fmt::Debug for FuncInstance {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&FuncInstance::Internal {
ref func_type,
ref module,
ref signature,
..
} => {
// We can't write description of self.module here, because it generate
// debug string for function instances and this will lead to infinite loop.
write!(
f,
"Internal {{ type={:?}, module={:?} }}",
func_type,
module
"Internal {{ signature={:?} }}",
signature,
)
}
&FuncInstance::Host { ref func_type, .. } => {
write!(f, "Host {{ type={:?} }}", func_type)
&FuncInstance::Host { ref signature, .. } => {
write!(f, "Host {{ signature={:?} }}", signature)
}
}
}
@ -59,29 +59,29 @@ impl fmt::Debug for FuncInstance {
impl FuncInstance {
pub(crate) fn alloc_internal(
module: ModuleRef,
func_type: Rc<FunctionType>,
signature: Rc<Signature>,
body: FuncBody,
) -> FuncRef {
let func = FuncInstance::Internal {
func_type,
signature,
module: module,
body: Rc::new(body),
};
FuncRef(Rc::new(func))
}
pub fn alloc_host(func_type: FunctionType, host_func_index: usize) -> FuncRef {
pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
let func = FuncInstance::Host {
func_type,
signature,
host_func_index,
};
FuncRef(Rc::new(func))
}
pub fn func_type(&self) -> &FunctionType {
pub fn signature(&self) -> &Signature {
match *self {
FuncInstance::Internal { ref func_type, .. } => func_type,
FuncInstance::Host { ref func_type, .. } => func_type,
FuncInstance::Internal { ref signature, .. } => signature,
FuncInstance::Host { ref signature, .. } => signature,
}
}
@ -103,15 +103,15 @@ impl FuncInstance {
}
let result = match *func {
FuncInstance::Internal { ref func_type, .. } => {
FuncInstance::Internal { ref signature, .. } => {
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(signature, &mut stack)?;
let context = FunctionContext::new(
func.clone(),
DEFAULT_VALUE_STACK_LIMIT,
DEFAULT_FRAME_STACK_LIMIT,
func_type,
signature,
args,
);
InvokeKind::Internal(context)

View File

@ -5,14 +5,14 @@ use memory::MemoryRef;
use func::FuncRef;
use table::TableRef;
use module::ModuleRef;
use Error;
use {Error, Signature};
pub trait ImportResolver {
fn resolve_func(
&self,
module_name: &str,
field_name: &str,
func_type: &FunctionType,
func_type: &Signature,
) -> Result<FuncRef, Error>;
fn resolve_global(
@ -75,11 +75,11 @@ impl<'a> ImportResolver for ImportsBuilder<'a> {
&self,
module_name: &str,
field_name: &str,
func_type: &FunctionType,
signature: &Signature,
) -> Result<FuncRef, Error> {
self.resolver(module_name).ok_or_else(||
Error::Instantiation(format!("Module {} not found", module_name))
)?.resolve_func(field_name, func_type)
)?.resolve_func(field_name, signature)
}
fn resolve_global(
@ -120,7 +120,7 @@ pub trait ModuleImportResolver {
fn resolve_func(
&self,
field_name: &str,
_func_type: &FunctionType,
_signature: &Signature,
) -> Result<FuncRef, Error> {
Err(Error::Instantiation(
format!("Export {} not found", field_name),
@ -162,7 +162,7 @@ impl ModuleImportResolver for ModuleRef {
fn resolve_func(
&self,
field_name: &str,
_func_type: &FunctionType,
_signature: &Signature,
) -> Result<FuncRef, Error> {
Ok(self.export_by_name(field_name)
.ok_or_else(|| {

View File

@ -10,6 +10,7 @@ extern crate byteorder;
use std::fmt;
use std::error;
use parity_wasm::elements::{FunctionType, ValueType};
/// Internal interpreter error.
#[derive(Debug)]
@ -97,6 +98,33 @@ impl From<::common::stack::Error> for Error {
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Signature {
func_type: FunctionType,
}
impl Signature {
pub fn new(params: &[ValueType], return_type: Option<ValueType>) -> Signature {
Signature {
func_type: FunctionType::new(params.to_vec(), return_type),
}
}
pub fn params(&self) -> &[ValueType] {
self.func_type.params()
}
pub fn return_type(&self) -> Option<ValueType> {
self.func_type.return_type()
}
}
impl From<FunctionType> for Signature {
fn from(func_type: FunctionType) -> Signature {
Signature { func_type }
}
}
mod validation;
mod common;
mod memory;

View File

@ -4,7 +4,7 @@ use std::fmt;
use std::collections::HashMap;
use std::borrow::Cow;
use parity_wasm::elements::{External, FunctionType, InitExpr, Internal, Opcode, ResizableLimits, Type};
use {Error, MemoryInstance, RuntimeValue, TableInstance};
use {Error, Signature, MemoryInstance, RuntimeValue, TableInstance};
use imports::ImportResolver;
use global::{GlobalInstance, GlobalRef};
use func::{FuncRef, FuncBody, FuncInstance};
@ -89,7 +89,7 @@ impl ExternVal {
#[derive(Debug)]
pub struct ModuleInstance {
types: RefCell<Vec<Rc<FunctionType>>>,
signatures: RefCell<Vec<Rc<Signature>>>,
tables: RefCell<Vec<TableRef>>,
funcs: RefCell<Vec<FuncRef>>,
memories: RefCell<Vec<MemoryRef>>,
@ -101,7 +101,7 @@ impl ModuleInstance {
fn default() -> Self {
ModuleInstance {
funcs: RefCell::new(Vec::new()),
types: RefCell::new(Vec::new()),
signatures: RefCell::new(Vec::new()),
tables: RefCell::new(Vec::new()),
memories: RefCell::new(Vec::new()),
globals: RefCell::new(Vec::new()),
@ -129,16 +129,16 @@ impl ModuleInstance {
self.exports.borrow().get(name).cloned()
}
pub(crate) fn type_by_index(&self, idx: u32) -> Option<Rc<FunctionType>> {
self.types.borrow().get(idx as usize).cloned()
pub(crate) fn signature_by_index(&self, idx: u32) -> Option<Rc<Signature>> {
self.signatures.borrow().get(idx as usize).cloned()
}
fn push_func(&self, func: FuncRef) {
self.funcs.borrow_mut().push(func);
}
fn push_type(&self, func_type: Rc<FunctionType>) {
self.types.borrow_mut().push(func_type)
fn push_signature(&self, signature: Rc<Signature>) {
self.signatures.borrow_mut().push(signature)
}
fn push_memory(&self, memory: MemoryRef) {
@ -165,8 +165,8 @@ impl ModuleInstance {
let instance = ModuleRef(Rc::new(ModuleInstance::default()));
for &Type::Function(ref ty) in module.type_section().map(|ts| ts.types()).unwrap_or(&[]) {
let type_id = alloc_func_type(ty.clone());
instance.push_type(type_id);
let signature = Rc::new(ty.clone().into());
instance.push_signature(signature);
}
{
@ -184,10 +184,10 @@ impl ModuleInstance {
{
match (import.external(), extern_val) {
(&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => {
let expected_fn_type = instance.type_by_index(fn_type_idx).expect(
let expected_fn_type = instance.signature_by_index(fn_type_idx).expect(
"Due to validation function type should exists",
);
let actual_fn_type = func.func_type();
let actual_fn_type = func.signature();
if &*expected_fn_type != actual_fn_type {
return Err(Error::Instantiation(format!(
"Expected function with type {:?}, but actual type is {:?} for entry {}",
@ -241,7 +241,7 @@ impl ModuleInstance {
for (index, (ty, body)) in
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
{
let func_type = instance.type_by_index(ty.type_ref()).expect(
let signature = instance.signature_by_index(ty.type_ref()).expect(
"Due to validation type should exists",
);
let labels = labels.get(&index).expect(
@ -253,7 +253,7 @@ impl ModuleInstance {
labels: labels,
};
let func_instance =
FuncInstance::alloc_internal(instance.clone(), func_type, func_body);
FuncInstance::alloc_internal(instance.clone(), signature, func_body);
instance.push_func(func_instance);
}
}
@ -386,7 +386,8 @@ impl ModuleInstance {
let &Type::Function(ref func_type) = types
.get(fn_ty_idx as usize)
.expect("Due to validation functions should have valid types");
let func = imports.resolve_func(module_name, field_name, func_type)?;
let signature = func_type.clone().into();
let func = imports.resolve_func(module_name, field_name, &signature)?;
ExternVal::Func(func)
}
External::Table(ref table_type) => {
@ -478,10 +479,6 @@ impl<'a> NotStartedModuleRef<'a> {
}
}
fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
Rc::new(func_type)
}
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue {
let code = init_expr.code();
debug_assert!(

View File

@ -5,7 +5,7 @@ use std::fmt::{self, Display};
use std::iter::repeat;
use std::collections::{HashMap, VecDeque};
use parity_wasm::elements::{Opcode, BlockType, Local, FunctionType};
use Error;
use {Error, Signature};
use module::ModuleRef;
use func::FuncRef;
use func::FuncInstance;
@ -102,8 +102,8 @@ impl<'a, E: Externals> Interpreter<'a, E> {
function_stack.push_back(function_context);
function_stack.push_back(nested_context);
},
FuncInstance::Host { ref func_type, .. } => {
let args = prepare_function_args(func_type, &mut function_context.value_stack)?;
FuncInstance::Host { ref signature, .. } => {
let args = prepare_function_args(signature, &mut function_context.value_stack)?;
let return_val = FuncInstance::invoke(nested_func.clone(), args.into(), self.externals)?;
if let Some(return_val) = return_val {
function_context.value_stack_mut().push(return_val)?;
@ -428,7 +428,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
fn run_call_indirect(
&mut self,
context: &mut FunctionContext,
type_idx: u32,
signature_idx: u32,
) -> Result<InstructionOutcome, Error> {
let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
let table = context
@ -438,10 +438,10 @@ impl<'a, E: Externals> Interpreter<'a, E> {
let func_ref = table.get(table_func_idx)?;
{
let actual_function_type = func_ref.func_type();
let actual_function_type = func_ref.signature();
let required_function_type = context
.module()
.type_by_index(type_idx)
.signature_by_index(signature_idx)
.expect("Due to validation type should exists");
if &*required_function_type != actual_function_type {
@ -1001,7 +1001,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
}
impl FunctionContext {
pub fn new<'store>(function: FuncRef, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
pub fn new<'store>(function: FuncRef, value_stack_limit: usize, frame_stack_limit: usize, signature: &Signature, args: Vec<RuntimeValue>) -> Self {
let module = match *function {
FuncInstance::Internal { ref module, .. } => module.clone(),
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
@ -1010,7 +1010,7 @@ impl FunctionContext {
is_initialized: false,
function: function,
module: module,
return_type: function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult),
return_type: signature.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult),
value_stack: StackWithLimit::with_limit(value_stack_limit),
frame_stack: StackWithLimit::with_limit(frame_stack_limit),
locals: args,
@ -1024,7 +1024,7 @@ impl FunctionContext {
FuncInstance::Internal { ref module, .. } => module.clone(),
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
};
let function_type = function.func_type();
let function_type = function.signature();
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)?;
(function_locals, module, function_return_type)
@ -1151,8 +1151,8 @@ fn effective_address(address: u32, offset: u32) -> Result<u32, Error> {
}
}
pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, Error> {
let mut args = function_type.params().iter().cloned().rev().map(|expected_type| {
pub fn prepare_function_args(signature: &Signature, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, Error> {
let mut args = signature.params().iter().cloned().rev().map(|expected_type| {
let param_value = caller_stack.pop()?;
let actual_type = param_value.value_type();
if actual_type != expected_type {

View File

@ -2,7 +2,7 @@
use parity_wasm::elements::{deserialize_buffer, FunctionType, MemoryType, TableType, ValueType};
use validation::{validate_module, ValidatedModule};
use {
Error, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
MemoryInstance, MemoryRef, TableInstance, TableRef, ModuleImportResolver, ModuleInstance, ModuleRef,
RuntimeValue, TryInto,
};
@ -144,14 +144,14 @@ impl Externals for TestHost {
}
impl TestHost {
fn check_signature(&self, index: usize, func_type: &FunctionType) -> bool {
fn check_signature(&self, index: usize, signature: &Signature) -> bool {
if index == RECURSE_FUNC_INDEX {
// This function requires special handling because it is polymorphic.
if func_type.params().len() != 1 {
if signature.params().len() != 1 {
return false;
}
let param_type = func_type.params()[0];
return func_type.return_type() == Some(param_type);
let param_type = signature.params()[0];
return signature.return_type() == Some(param_type);
}
let (params, ret_ty): (&[ValueType], Option<ValueType>) = match index {
@ -162,12 +162,12 @@ impl TestHost {
_ => return false,
};
func_type.params() == params && func_type.return_type() == ret_ty
signature.params() == params && signature.return_type() == ret_ty
}
}
impl ModuleImportResolver for TestHost {
fn resolve_func(&self, field_name: &str, func_type: &FunctionType) -> Result<FuncRef, Error> {
fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, Error> {
let index = match field_name {
"sub" => SUB_FUNC_INDEX,
"err" => ERR_FUNC_INDEX,
@ -181,15 +181,15 @@ impl ModuleImportResolver for TestHost {
}
};
if !self.check_signature(index, func_type) {
if !self.check_signature(index, signature) {
return Err(Error::Instantiation(format!(
"Export `{}` doesnt match expected type {:?}",
field_name,
func_type
signature
)));
}
Ok(FuncInstance::alloc_host(func_type.clone(), index))
Ok(FuncInstance::alloc_host(signature.clone(), index))
}
fn resolve_memory(
@ -424,22 +424,22 @@ fn defer_providing_externals() {
fn resolve_func(
&self,
field_name: &str,
func_type: &FunctionType,
signature: &Signature,
) -> Result<FuncRef, Error> {
if field_name != "inc" {
return Err(Error::Instantiation(
format!("Export {} not found", field_name),
));
}
if func_type.params() != &[ValueType::I32] || func_type.return_type() != None {
if signature.params() != &[ValueType::I32] || signature.return_type() != None {
return Err(Error::Instantiation(format!(
"Export `{}` doesnt match expected type {:?}",
field_name,
func_type
signature
)));
}
Ok(FuncInstance::alloc_host(func_type.clone(), INC_FUNC_INDEX))
Ok(FuncInstance::alloc_host(signature.clone(), INC_FUNC_INDEX))
}
fn resolve_memory(
@ -552,7 +552,7 @@ fn two_envs_one_externals() {
fn resolve_func(
&self,
field_name: &str,
func_type: &FunctionType,
signature: &Signature,
) -> Result<FuncRef, Error> {
let index = match field_name {
"ordinary" => ORDINARY_FUNC_INDEX,
@ -564,7 +564,7 @@ fn two_envs_one_externals() {
}
};
Ok(FuncInstance::alloc_host(func_type.clone(), index))
Ok(FuncInstance::alloc_host(signature.clone(), index))
}
}
@ -572,7 +572,7 @@ fn two_envs_one_externals() {
fn resolve_func(
&self,
field_name: &str,
func_type: &FunctionType,
signature: &Signature,
) -> Result<FuncRef, Error> {
let index = match field_name {
"ordinary" => ORDINARY_FUNC_INDEX,
@ -588,7 +588,7 @@ fn two_envs_one_externals() {
}
};
Ok(FuncInstance::alloc_host(func_type.clone(), index))
Ok(FuncInstance::alloc_host(signature.clone(), index))
}
}
@ -663,7 +663,7 @@ fn dynamically_add_host_func() {
self.added_funcs += 1;
let added_func = FuncInstance::alloc_host(
FunctionType::new(vec![], Some(ValueType::I32)),
Signature::new(&[], Some(ValueType::I32)),
host_func_index as usize,
);
self.table.set(table_index, Some(added_func))?;
@ -682,7 +682,7 @@ fn dynamically_add_host_func() {
fn resolve_func(
&self,
field_name: &str,
func_type: &FunctionType,
signature: &Signature,
) -> Result<FuncRef, Error> {
let index = match field_name {
"add_func" => ADD_FUNC_FUNC_INDEX,
@ -692,7 +692,7 @@ fn dynamically_add_host_func() {
))
}
};
Ok(FuncInstance::alloc_host(func_type.clone(), index))
Ok(FuncInstance::alloc_host(signature.clone(), index))
}
fn resolve_table(

View File

@ -1,6 +1,6 @@
use parity_wasm::elements::deserialize_file;
use parity_wasm::elements::{FunctionType, GlobalType, MemoryType, Module, TableType};
use {Error, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
use {Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
TableInstance, TableRef};
use validation::validate_module;
@ -24,7 +24,7 @@ impl Env {
}
impl ModuleImportResolver for Env {
fn resolve_func(&self, _field_name: &str, _func_type: &FunctionType) -> Result<FuncRef, Error> {
fn resolve_func(&self, _field_name: &str, _func_type: &Signature) -> Result<FuncRef, Error> {
Err(Error::Instantiation(
"env module doesn't provide any functions".into(),
))