Clean module stuff

This commit is contained in:
Sergey Pepyakin
2017-12-11 18:47:57 +01:00
parent 65b5fbc83e
commit ebbfa6acf6
5 changed files with 16 additions and 195 deletions

View File

@ -130,7 +130,6 @@ impl From<common::stack::Error> for Error {
} }
} }
mod native;
mod memory; mod memory;
mod module; mod module;
mod program; mod program;
@ -146,9 +145,8 @@ mod host;
mod tests; mod tests;
pub use self::memory::MemoryInstance; pub use self::memory::MemoryInstance;
pub use self::module::{ItemIndex, ExportEntryType, CallerContext, ExecutionParams, FunctionSignature}; pub use self::module::{ItemIndex, ExportEntryType, ExecutionParams};
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::variable::{VariableInstance, VariableType, ExternalVariableValue}; pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
pub use self::native::{UserDefinedElements, UserFunctionExecutor, UserFunctionDescriptor};

View File

@ -1,17 +1,9 @@
use std::collections::HashMap; use elements::{InitExpr, Opcode, Type, FunctionType, Internal, External, ResizableLimits, Local, ValueType, BlockType};
use std::iter::repeat;
use std::sync::{Arc, Weak};
use std::fmt;
use elements::{Module, InitExpr, Opcode, Type, FunctionType, Internal, External, ResizableLimits, Local, ValueType, BlockType};
use interpreter::Error; use interpreter::Error;
use interpreter::native::UserFunctionDescriptor; use interpreter::runner::{FunctionContext};
use interpreter::memory::MemoryInstance; use interpreter::VariableType;
use interpreter::runner::{FunctionContext, prepare_function_args}; use interpreter::RuntimeValue;
use interpreter::table::TableInstance;
use interpreter::value::{RuntimeValue, TryInto};
use interpreter::variable::{VariableInstance, VariableType};
use common::stack::StackWithLimit; use common::stack::StackWithLimit;
use interpreter::store::FuncId;
/// Maximum number of entries in value stack. /// Maximum number of entries in value stack.
const DEFAULT_VALUE_STACK_LIMIT: usize = 16384; const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
@ -26,24 +18,13 @@ pub struct ExecutionParams<'a, St: 'static> {
/// Export type. /// Export type.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ExportEntryType<'a> { pub enum ExportEntryType {
/// Any type. /// Any type.
Any, Any,
/// Type of function.
Function(FunctionSignature<'a>),
/// Type of global. /// Type of global.
Global(VariableType), Global(VariableType),
} }
/// Function signature.
#[derive(Debug, Clone)]
pub enum FunctionSignature<'a> {
/// Module function reference.
Module(&'a FunctionType),
/// Native user function refrence.
User(&'a UserFunctionDescriptor),
}
/// Item index in items index space. /// Item index in items index space.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum ItemIndex { pub enum ItemIndex {
@ -65,23 +46,6 @@ pub struct CallerContext<'a> {
pub value_stack: &'a mut StackWithLimit<RuntimeValue>, pub value_stack: &'a mut StackWithLimit<RuntimeValue>,
} }
/// Internal function ready for interpretation.
pub struct InternalFunction<'a> {
/// Function locals.
pub locals: &'a [Local],
/// Function body.
pub body: &'a [Opcode],
/// Function labels.
pub labels: &'a HashMap<usize, usize>,
}
impl<'a, St> ExecutionParams<'a, St> {
/// Add argument.
pub fn add_argument(mut self, arg: RuntimeValue) -> Self {
self
}
}
impl<'a> CallerContext<'a> { impl<'a> CallerContext<'a> {
/// Top most args /// Top most args
pub fn topmost(args: &'a mut StackWithLimit<RuntimeValue>) -> Self { pub fn topmost(args: &'a mut StackWithLimit<RuntimeValue>) -> Self {
@ -111,41 +75,3 @@ pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
Ok(()) Ok(())
} }
impl<'a> FunctionSignature<'a> {
/// Get return type of this function.
pub fn return_type(&self) -> Option<ValueType> {
match self {
&FunctionSignature::Module(ft) => ft.return_type(),
&FunctionSignature::User(fd) => fd.return_type(),
}
}
/// Get parameters of this function.
pub fn params(&self) -> &[ValueType] {
match self {
&FunctionSignature::Module(ft) => ft.params(),
&FunctionSignature::User(fd) => fd.params(),
}
}
}
impl<'a> PartialEq for FunctionSignature<'a> {
fn eq<'b>(&self, other: &FunctionSignature<'b>) -> bool {
match self {
&FunctionSignature::Module(ft1) => match other {
&FunctionSignature::Module(ft2) => ft1 == ft2,
&FunctionSignature::User(ft2) => ft1.params() == ft2.params() && ft1.return_type() == ft2.return_type(),
},
&FunctionSignature::User(ft1) => match other {
&FunctionSignature::User(ft2) => ft1 == ft2,
&FunctionSignature::Module(ft2) => ft1.params() == ft2.params() && ft1.return_type() == ft2.return_type(),
},
}
}
}
impl<'a> From<&'a FunctionType> for FunctionSignature<'a> {
fn from(other: &'a FunctionType) -> Self {
FunctionSignature::Module(other)
}
}

View File

@ -1,100 +0,0 @@
use std::sync::Arc;
use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ExecutionParams, ItemIndex,
CallerContext, ExportEntryType, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::{VariableInstance, VariableType};
/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;
/// User functions executor.
pub trait UserFunctionExecutor {
/// Execute function with given name.
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}
/// User function descriptor
#[derive(Debug, Clone)]
pub enum UserFunctionDescriptor {
/// Static function definition
Static(&'static str, &'static [ValueType], Option<ValueType>),
/// Dynamic heap function definition
Heap(String, Vec<ValueType>, Option<ValueType>),
}
impl UserFunctionDescriptor {
/// New function with statically known params
pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
UserFunctionDescriptor::Static(name, params, result)
}
/// New function with statically unknown params
pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
UserFunctionDescriptor::Heap(name, params, result)
}
/// Name of the function
pub fn name(&self) -> &str {
match self {
&UserFunctionDescriptor::Static(name, _, _) => name,
&UserFunctionDescriptor::Heap(ref name, _, _) => name,
}
}
/// Arguments of the function
pub fn params(&self) -> &[ValueType] {
match self {
&UserFunctionDescriptor::Static(_, params, _) => params,
&UserFunctionDescriptor::Heap(_, ref params, _) => params,
}
}
/// Return type of the function
pub fn return_type(&self) -> Option<ValueType> {
match self {
&UserFunctionDescriptor::Static(_, _, result) => result,
&UserFunctionDescriptor::Heap(_, _, result) => result,
}
}
}
/// Set of user-defined module elements.
pub struct UserDefinedElements<E: UserFunctionExecutor> {
/// User globals list.
pub globals: HashMap<String, Arc<VariableInstance>>,
/// User functions list.
pub functions: Cow<'static, [UserFunctionDescriptor]>,
/// Functions executor.
pub executor: Option<E>,
}
/// Native module instance.
pub struct NativeModuleInstance<E: UserFunctionExecutor> {
/// User function executor.
executor: RwLock<Option<E>>,
/// By-name functions index.
functions_by_name: HashMap<String, u32>,
/// User functions list.
functions: Cow<'static, [UserFunctionDescriptor]>,
/// By-name functions index.
globals_by_name: HashMap<String, u32>,
/// User globals list.
globals: Vec<Arc<VariableInstance>>,
}
impl<'a> PartialEq for UserFunctionDescriptor {
fn eq(&self, other: &Self) -> bool {
self.params() == other.params()
&& self.return_type() == other.return_type()
}
}

View File

@ -5,10 +5,10 @@ use std::{u32, usize};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::iter::repeat; use std::iter::repeat;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, Local}; use elements::{Opcode, BlockType, Local, FunctionType};
use interpreter::Error; use interpreter::Error;
use interpreter::store::{Store, FuncId, ModuleId, FuncInstance}; use interpreter::store::{Store, FuncId, ModuleId, FuncInstance};
use interpreter::module::{CallerContext, FunctionSignature, ExecutionParams}; use interpreter::module::{CallerContext, ExecutionParams};
use interpreter::value::{ use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto,
@ -970,7 +970,7 @@ impl<'store, St: 'static> Interpreter<'store, St> {
} }
impl<'a> FunctionContext { impl<'a> FunctionContext {
pub fn new<'store>(store: &'store Store, function: FuncId, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<RuntimeValue>) -> Self { pub fn new<'store>(store: &'store Store, function: FuncId, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionType, args: Vec<RuntimeValue>) -> Self {
let func_instance = function.resolve(store); let func_instance = function.resolve(store);
let module = match *func_instance { let module = match *func_instance {
FuncInstance::Internal { module, .. } => module, FuncInstance::Internal { module, .. } => module,
@ -996,10 +996,8 @@ impl<'a> FunctionContext {
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"),
}; };
let function_type = func_instance.func_type().resolve(store); let function_type = func_instance.func_type().resolve(store);
// TODO: function_signature
let function_signature = FunctionSignature::Module(&function_type);
let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult); let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult);
let function_locals = prepare_function_args(&function_signature, &mut self.value_stack)?; let function_locals = prepare_function_args(function_type, &mut self.value_stack)?;
(function_locals, module, function_return_type) (function_locals, module, function_return_type)
}; };
@ -1129,7 +1127,7 @@ fn effective_address(address: u32, offset: u32) -> Result<u32, Error> {
} }
} }
pub fn prepare_function_args(function_type: &FunctionSignature, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, 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().rev().map(|param_type| { let mut args = function_type.params().iter().rev().map(|param_type| {
let param_value = caller_stack.pop()?; let param_value = caller_stack.pop()?;
let actual_type = param_value.variable_type(); let actual_type = param_value.variable_type();

View File

@ -6,7 +6,7 @@ use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use elements::{FunctionType, GlobalEntry, GlobalType, InitExpr, Internal, Local, MemoryType, use elements::{FunctionType, GlobalEntry, GlobalType, InitExpr, Internal, Local, MemoryType,
Module, Opcode, Opcodes, TableType, Type}; Module, Opcode, Opcodes, TableType, Type};
use interpreter::{CallerContext, Error, ExecutionParams, FunctionSignature, MemoryInstance, use interpreter::{Error, ExecutionParams, MemoryInstance,
RuntimeValue, TableInstance}; RuntimeValue, TableInstance};
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter}; use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
use interpreter::host::AnyFunc; use interpreter::host::AnyFunc;
@ -488,14 +488,13 @@ impl Store {
let result = match *func.resolve(self) { let result = match *func.resolve(self) {
FuncInstance::Internal { func_type, .. } => { FuncInstance::Internal { func_type, .. } => {
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT); let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let outer = CallerContext::topmost(&mut args); let func_signature = func_type.resolve(self);
let func_signature = FunctionSignature::Module(func_type.resolve(self)); let args = prepare_function_args(&func_signature, &mut args)?;
let args = prepare_function_args(&func_signature, outer.value_stack)?;
let context = FunctionContext::new( let context = FunctionContext::new(
self, self,
func, func,
outer.value_stack_limit, DEFAULT_VALUE_STACK_LIMIT,
outer.frame_stack_limit, DEFAULT_FRAME_STACK_LIMIT,
&func_signature, &func_signature,
args, args,
); );