2018-01-17 15:32:33 +00:00
|
|
|
use std::rc::Rc;
|
|
|
|
use std::fmt;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::borrow::Cow;
|
2018-01-18 13:39:14 +00:00
|
|
|
use parity_wasm::elements::{Local, Opcodes};
|
2018-01-18 12:48:43 +00:00
|
|
|
use {Error, Signature};
|
2018-01-17 15:32:33 +00:00
|
|
|
use host::Externals;
|
|
|
|
use runner::{prepare_function_args, FunctionContext, Interpreter};
|
|
|
|
use value::RuntimeValue;
|
|
|
|
use module::ModuleRef;
|
|
|
|
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 {
|
2018-01-18 12:48:43 +00:00
|
|
|
signature: Rc<Signature>,
|
2018-01-17 15:32:33 +00:00
|
|
|
module: ModuleRef,
|
|
|
|
body: Rc<FuncBody>,
|
|
|
|
},
|
|
|
|
Host {
|
2018-01-18 12:48:43 +00:00
|
|
|
signature: Signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
host_func_index: usize,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for FuncInstance {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
&FuncInstance::Internal {
|
2018-01-18 12:48:43 +00:00
|
|
|
ref signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
..
|
|
|
|
} => {
|
2018-01-18 12:48:43 +00:00
|
|
|
// We can't write description of self.module here, because it generate
|
|
|
|
// debug string for function instances and this will lead to infinite loop.
|
2018-01-17 15:32:33 +00:00
|
|
|
write!(
|
|
|
|
f,
|
2018-01-18 12:48:43 +00:00
|
|
|
"Internal {{ signature={:?} }}",
|
|
|
|
signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
)
|
|
|
|
}
|
2018-01-18 12:48:43 +00:00
|
|
|
&FuncInstance::Host { ref signature, .. } => {
|
|
|
|
write!(f, "Host {{ signature={:?} }}", signature)
|
2018-01-17 15:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FuncInstance {
|
|
|
|
pub(crate) fn alloc_internal(
|
|
|
|
module: ModuleRef,
|
2018-01-18 12:48:43 +00:00
|
|
|
signature: Rc<Signature>,
|
2018-01-17 15:32:33 +00:00
|
|
|
body: FuncBody,
|
|
|
|
) -> FuncRef {
|
|
|
|
let func = FuncInstance::Internal {
|
2018-01-18 12:48:43 +00:00
|
|
|
signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
module: module,
|
|
|
|
body: Rc::new(body),
|
|
|
|
};
|
|
|
|
FuncRef(Rc::new(func))
|
|
|
|
}
|
|
|
|
|
2018-01-18 12:48:43 +00:00
|
|
|
pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
|
2018-01-17 15:32:33 +00:00
|
|
|
let func = FuncInstance::Host {
|
2018-01-18 12:48:43 +00:00
|
|
|
signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
host_func_index,
|
|
|
|
};
|
|
|
|
FuncRef(Rc::new(func))
|
|
|
|
}
|
|
|
|
|
2018-01-18 12:48:43 +00:00
|
|
|
pub fn signature(&self) -> &Signature {
|
2018-01-17 15:32:33 +00:00
|
|
|
match *self {
|
2018-01-18 12:48:43 +00:00
|
|
|
FuncInstance::Internal { ref signature, .. } => signature,
|
|
|
|
FuncInstance::Host { ref signature, .. } => signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn body(&self) -> Option<Rc<FuncBody>> {
|
|
|
|
match *self {
|
|
|
|
FuncInstance::Internal { ref body, .. } => Some(Rc::clone(body)),
|
|
|
|
FuncInstance::Host { .. } => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn invoke<E: Externals>(
|
|
|
|
func: FuncRef,
|
|
|
|
args: Cow<[RuntimeValue]>,
|
|
|
|
externals: &mut E,
|
|
|
|
) -> Result<Option<RuntimeValue>, Error> {
|
|
|
|
enum InvokeKind<'a> {
|
|
|
|
Internal(FunctionContext),
|
|
|
|
Host(usize, &'a [RuntimeValue]),
|
|
|
|
}
|
|
|
|
|
|
|
|
let result = match *func {
|
2018-01-18 12:48:43 +00:00
|
|
|
FuncInstance::Internal { ref signature, .. } => {
|
2018-01-17 15:32:33 +00:00
|
|
|
let mut stack =
|
|
|
|
StackWithLimit::with_data(args.into_iter().cloned(), DEFAULT_VALUE_STACK_LIMIT);
|
2018-01-18 12:48:43 +00:00
|
|
|
let args = prepare_function_args(signature, &mut stack)?;
|
2018-01-17 15:32:33 +00:00
|
|
|
let context = FunctionContext::new(
|
|
|
|
func.clone(),
|
|
|
|
DEFAULT_VALUE_STACK_LIMIT,
|
|
|
|
DEFAULT_FRAME_STACK_LIMIT,
|
2018-01-18 12:48:43 +00:00
|
|
|
signature,
|
2018-01-17 15:32:33 +00:00
|
|
|
args,
|
|
|
|
);
|
|
|
|
InvokeKind::Internal(context)
|
|
|
|
}
|
|
|
|
FuncInstance::Host { ref host_func_index, .. } => {
|
|
|
|
InvokeKind::Host(*host_func_index, &*args)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match result {
|
|
|
|
InvokeKind::Internal(ctx) => {
|
|
|
|
let mut interpreter = Interpreter::new(externals);
|
|
|
|
interpreter.run_function(ctx)
|
|
|
|
}
|
|
|
|
InvokeKind::Host(host_func, args) => externals.invoke_index(host_func, args),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct FuncBody {
|
|
|
|
pub locals: Vec<Local>,
|
|
|
|
pub opcodes: Opcodes,
|
|
|
|
pub labels: HashMap<usize, usize>,
|
|
|
|
}
|