wasmi/src/func.rs

140 lines
3.2 KiB
Rust
Raw Normal View History

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>,
}