Convert *Ref types to a newtype.

This commit is contained in:
Sergey Pepyakin 2018-01-05 16:22:20 +03:00
parent 9b11d1c96c
commit 8c7dc1b529
10 changed files with 108 additions and 68 deletions

View File

@ -3,7 +3,6 @@ use std::fmt;
use std::collections::HashMap;
use std::borrow::Cow;
use elements::{FunctionType, Local, Opcodes};
use interpreter::module::FuncRef;
use interpreter::{Error, ModuleInstance};
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
use interpreter::host::HostFunc;
@ -12,6 +11,16 @@ use interpreter::state::HostState;
use common::stack::StackWithLimit;
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT};
#[derive(Clone, Debug)]
pub struct FuncRef(Rc<FuncInstance>);
impl ::std::ops::Deref for FuncRef {
type Target = FuncInstance;
fn deref(&self) -> &FuncInstance {
&self.0
}
}
#[derive(Clone)]
pub enum FuncInstance {
Internal {
@ -52,21 +61,21 @@ impl FuncInstance {
module: Rc<ModuleInstance>,
func_type: Rc<FunctionType>,
body: FuncBody,
) -> Rc<Self> {
) -> FuncRef {
let func = FuncInstance::Internal {
func_type,
module: module,
body: Rc::new(body),
};
Rc::new(func)
FuncRef(Rc::new(func))
}
pub fn alloc_host(func_type: Rc<FunctionType>, host_func: Rc<HostFunc>) -> Rc<Self> {
pub fn alloc_host(func_type: Rc<FunctionType>, host_func: Rc<HostFunc>) -> FuncRef {
let func = FuncInstance::Host {
func_type,
host_func,
};
Rc::new(func)
FuncRef(Rc::new(func))
}
pub fn func_type(&self) -> Rc<FunctionType> {
@ -99,7 +108,7 @@ impl FuncInstance {
StackWithLimit::with_data(args.into_iter().cloned(), DEFAULT_VALUE_STACK_LIMIT);
let args = prepare_function_args(func_type, &mut stack)?;
let context = FunctionContext::new(
Rc::clone(&func),
func.clone(),
DEFAULT_VALUE_STACK_LIMIT,
DEFAULT_FRAME_STACK_LIMIT,
func_type,

View File

@ -1,8 +1,19 @@
use std::rc::Rc;
use std::cell::Cell;
use elements::ValueType;
use elements::{ValueType, GlobalType};
use interpreter::value::RuntimeValue;
use interpreter::Error;
#[derive(Clone, Debug)]
pub struct GlobalRef(Rc<GlobalInstance>);
impl ::std::ops::Deref for GlobalRef {
type Target = GlobalInstance;
fn deref(&self) -> &GlobalInstance {
&self.0
}
}
#[derive(Debug)]
pub struct GlobalInstance {
val: Cell<RuntimeValue>,
@ -17,6 +28,11 @@ impl GlobalInstance {
}
}
pub fn alloc(global_type: &GlobalType, val: RuntimeValue) -> GlobalRef {
let global = GlobalInstance::new(val, global_type.is_mutable());
GlobalRef(Rc::new(global))
}
pub fn set(&self, val: RuntimeValue) -> Result<(), Error> {
assert!(self.mutable, "Attempt to change an immutable variable");
assert!(

View File

@ -1,11 +1,12 @@
use interpreter::module::GlobalRef;
use std::rc::Rc;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use elements::{FunctionType, GlobalType, MemoryType, TableType, ValueType};
use interpreter::module::{ExternVal, ModuleInstance, FuncRef};
use interpreter::module::MemoryRef;
use interpreter::module::TableRef;
use interpreter::module::{ExternVal, ModuleInstance};
use interpreter::func::FuncRef;
use interpreter::global::GlobalRef;
use interpreter::memory::MemoryRef;
use interpreter::table::TableRef;
use interpreter::func::FuncInstance;
use interpreter::global::GlobalInstance;
use interpreter::memory::MemoryInstance;

View File

@ -1,9 +1,9 @@
use interpreter::module::GlobalRef;
use std::collections::HashMap;
use elements::{FunctionType, GlobalType, MemoryType, TableType};
use interpreter::module::MemoryRef;
use interpreter::module::FuncRef;
use interpreter::module::TableRef;
use interpreter::global::GlobalRef;
use interpreter::memory::MemoryRef;
use interpreter::func::FuncRef;
use interpreter::table::TableRef;
use interpreter::Error;
pub struct Imports<'a> {

View File

@ -2,6 +2,7 @@ use std::u32;
use std::ops::Range;
use std::cmp;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;
use elements::{MemoryType, ResizableLimits};
use interpreter::Error;
@ -12,6 +13,16 @@ pub const LINEAR_MEMORY_PAGE_SIZE: u32 = 65536;
/// Maximal number of pages.
const LINEAR_MEMORY_MAX_PAGES: u32 = 65536;
#[derive(Clone, Debug)]
pub struct MemoryRef(Rc<MemoryInstance>);
impl ::std::ops::Deref for MemoryRef {
type Target = MemoryInstance;
fn deref(&self) -> &MemoryInstance {
&self.0
}
}
/// Linear memory instance.
pub struct MemoryInstance {
/// Memofy limits.
@ -78,6 +89,11 @@ impl MemoryInstance {
Ok(memory)
}
pub fn alloc(mem_type: &MemoryType) -> Result<MemoryRef, Error> {
let memory = MemoryInstance::new(&mem_type)?;
Ok(MemoryRef(Rc::new(memory)))
}
/// Return linear memory limits.
pub fn limits(&self) -> &ResizableLimits {
&self.limits

View File

@ -151,13 +151,13 @@ mod state;
#[cfg(test)]
mod tests;
pub use self::memory::MemoryInstance;
pub use self::table::TableInstance;
pub use self::memory::{MemoryInstance, MemoryRef};
pub use self::table::{TableInstance, TableRef};
pub use self::program::ProgramInstance;
pub use self::value::RuntimeValue;
pub use self::host::{HostModule, HostModuleBuilder, HostFunc, IntoReturnVal, FromArg};
pub use self::imports::{ImportResolver, Imports};
pub use self::module::{ModuleInstance, FuncRef, MemoryRef, GlobalRef, TableRef};
pub use self::global::GlobalInstance;
pub use self::func::FuncInstance;
pub use self::module::ModuleInstance;
pub use self::global::{GlobalInstance, GlobalRef};
pub use self::func::{FuncInstance, FuncRef};
pub use self::state::{HostState, StateKey};

View File

@ -7,17 +7,14 @@ use elements::{External, FunctionType, GlobalType, InitExpr, Internal, MemoryTyp
ResizableLimits, TableType, Type};
use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance};
use interpreter::imports::{ImportResolver, Imports};
use interpreter::global::GlobalInstance;
use interpreter::func::{FuncBody, FuncInstance};
use interpreter::global::{GlobalInstance, GlobalRef};
use interpreter::func::{FuncRef, FuncBody, FuncInstance};
use interpreter::table::TableRef;
use interpreter::state::HostState;
use interpreter::memory::MemoryRef;
use validation::validate_module;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
pub type FuncRef = Rc<FuncInstance>;
pub type TableRef = Rc<TableInstance>;
pub type MemoryRef = Rc<MemoryInstance>;
pub type GlobalRef = Rc<GlobalInstance>;
pub enum ExternVal {
Func(FuncRef),
Table(TableRef),
@ -28,10 +25,10 @@ pub enum ExternVal {
impl Clone for ExternVal {
fn clone(&self) -> Self {
match *self {
ExternVal::Func(ref func) => ExternVal::Func(Rc::clone(func)),
ExternVal::Table(ref table) => ExternVal::Table(Rc::clone(table)),
ExternVal::Memory(ref memory) => ExternVal::Memory(Rc::clone(memory)),
ExternVal::Global(ref global) => ExternVal::Global(Rc::clone(global)),
ExternVal::Func(ref func) => ExternVal::Func(func.clone()),
ExternVal::Table(ref table) => ExternVal::Table(table.clone()),
ExternVal::Memory(ref memory) => ExternVal::Memory(memory.clone()),
ExternVal::Global(ref global) => ExternVal::Global(global.clone()),
}
}
}
@ -54,28 +51,28 @@ impl fmt::Debug for ExternVal {
impl ExternVal {
pub fn as_func(&self) -> Option<FuncRef> {
match *self {
ExternVal::Func(ref func) => Some(Rc::clone(func)),
ExternVal::Func(ref func) => Some(func.clone()),
_ => None,
}
}
pub fn as_table(&self) -> Option<TableRef> {
match *self {
ExternVal::Table(ref table) => Some(Rc::clone(table)),
ExternVal::Table(ref table) => Some(table.clone()),
_ => None,
}
}
pub fn as_memory(&self) -> Option<MemoryRef> {
match *self {
ExternVal::Memory(ref memory) => Some(Rc::clone(memory)),
ExternVal::Memory(ref memory) => Some(memory.clone()),
_ => None,
}
}
pub fn as_global(&self) -> Option<GlobalRef> {
match *self {
ExternVal::Global(ref global) => Some(Rc::clone(global)),
ExternVal::Global(ref global) => Some(global.clone()),
_ => None,
}
}
@ -198,15 +195,15 @@ impl ModuleInstance {
import.field(),
)));
}
instance.push_func(Rc::clone(func))
instance.push_func(func.clone())
}
(&External::Table(ref tt), &ExternVal::Table(ref table)) => {
match_limits(table.limits(), tt.limits())?;
instance.push_table(Rc::clone(table));
instance.push_table(table.clone());
}
(&External::Memory(ref mt), &ExternVal::Memory(ref memory)) => {
match_limits(memory.limits(), mt.limits())?;
instance.push_memory(Rc::clone(memory));
instance.push_memory(memory.clone());
}
(&External::Global(ref gl), &ExternVal::Global(ref global)) => {
if gl.content_type() != global.value_type() {
@ -216,7 +213,7 @@ impl ModuleInstance {
global.value_type(),
)));
}
instance.push_global(Rc::clone(global))
instance.push_global(global.clone());
}
(expected_import, actual_extern_val) => {
return Err(Error::Instantiation(format!(
@ -260,7 +257,7 @@ impl ModuleInstance {
}
for table_type in module.table_section().map(|ts| ts.entries()).unwrap_or(&[]) {
let table = alloc_table(table_type)?;
let table = TableInstance::alloc(table_type)?;
instance.push_table(table);
}
@ -268,7 +265,7 @@ impl ModuleInstance {
&[],
)
{
let memory = alloc_memory(memory_type)?;
let memory = MemoryInstance::alloc(memory_type)?;
instance.push_memory(memory);
}
@ -277,7 +274,7 @@ impl ModuleInstance {
)
{
let init_val = eval_init_expr(global_entry.init_expr(), &*instance);
let global = alloc_global(global_entry.global_type().clone(), init_val);
let global = GlobalInstance::alloc(global_entry.global_type(), init_val);
instance.push_global(global);
}
@ -444,7 +441,7 @@ impl ModuleInstance {
}
};
FuncInstance::invoke(Rc::clone(&func_instance), Cow::Borrowed(args), state)
FuncInstance::invoke(func_instance.clone(), Cow::Borrowed(args), state)
}
}
@ -564,21 +561,6 @@ fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
Rc::new(func_type)
}
fn alloc_table(table_type: &TableType) -> Result<TableRef, Error> {
let table = TableInstance::new(table_type)?;
Ok(Rc::new(table))
}
fn alloc_memory(mem_type: &MemoryType) -> Result<MemoryRef, Error> {
let memory = MemoryInstance::new(&mem_type)?;
Ok(Rc::new(memory))
}
fn alloc_global(global_type: GlobalType, val: RuntimeValue) -> GlobalRef {
let global = GlobalInstance::new(val, global_type.is_mutable());
Rc::new(global)
}
fn eval_init_expr(init_expr: &InitExpr, module: &ModuleInstance) -> RuntimeValue {
let code = init_expr.code();
debug_assert!(

View File

@ -3,8 +3,8 @@ use std::collections::HashMap;
use std::borrow::Cow;
use elements::Module;
use interpreter::Error;
use interpreter::module::{ModuleInstance, FuncRef};
use interpreter::func::FuncInstance;
use interpreter::module::{ModuleInstance};
use interpreter::func::{FuncInstance, FuncRef};
use interpreter::host::HostModule;
use interpreter::value::RuntimeValue;
use interpreter::imports::{Imports, ImportResolver};
@ -102,7 +102,7 @@ impl ProgramInstance {
args: &[RuntimeValue],
state: &'a mut HostState<'a>,
) -> Result<Option<RuntimeValue>, Error> {
FuncInstance::invoke(Rc::clone(&func_instance), Cow::Borrowed(args), state)
FuncInstance::invoke(func_instance.clone(), Cow::Borrowed(args), state)
}
pub fn resolver(&self, name: &str) -> Option<&ImportResolver> {

View File

@ -8,7 +8,7 @@ use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, Local, FunctionType};
use interpreter::Error;
use interpreter::module::ModuleInstance;
use interpreter::module::FuncRef;
use interpreter::func::FuncRef;
use interpreter::func::FuncInstance;
use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
@ -77,7 +77,7 @@ impl<'a, 'b: 'a> Interpreter<'a, 'b> {
loop {
let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed");
let function_ref = Rc::clone(&function_context.function);
let function_ref = function_context.function.clone();
let function_body = function_ref.body().expect("Host functions checked in function_return below; Internal functions always have a body; qed");
if !function_context.is_initialized() {
let return_type = function_context.return_type;
@ -99,13 +99,13 @@ impl<'a, 'b: 'a> Interpreter<'a, 'b> {
RunResult::NestedCall(nested_func) => {
match *nested_func {
FuncInstance::Internal { .. } => {
let nested_context = function_context.nested(Rc::clone(&nested_func))?;
let nested_context = function_context.nested(nested_func.clone())?;
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)?;
let return_val = FuncInstance::invoke(Rc::clone(&nested_func), args.into(), self.state)?;
let return_val = FuncInstance::invoke(nested_func.clone(), args.into(), self.state)?;
if let Some(return_val) = return_val {
function_context.value_stack_mut().push(return_val)?;
}

View File

@ -1,11 +1,22 @@
use std::u32;
use std::fmt;
use std::cell::RefCell;
use std::rc::Rc;
use elements::{ResizableLimits, TableType};
use interpreter::Error;
use interpreter::module::FuncRef;
use interpreter::func::FuncRef;
use interpreter::module::check_limits;
#[derive(Clone, Debug)]
pub struct TableRef(Rc<TableInstance>);
impl ::std::ops::Deref for TableRef {
type Target = TableInstance;
fn deref(&self) -> &TableInstance {
&self.0
}
}
/// Table instance.
pub struct TableInstance {
/// Table limits.
@ -24,8 +35,13 @@ impl fmt::Debug for TableInstance {
}
impl TableInstance {
/// New instance of the table
pub fn new(table_type: &TableType) -> Result<Self, Error> {
pub fn alloc(table_type: &TableType) -> Result<TableRef, Error> {
let table = TableInstance::new(table_type)?;
Ok(TableRef(Rc::new(table)))
}
pub fn new(table_type: &TableType) -> Result<TableInstance, Error> {
check_limits(table_type.limits())?;
Ok(TableInstance {
limits: table_type.limits().clone(),