wasmi/src/func.rs

164 lines
4.4 KiB
Rust
Raw Normal View History

2018-01-22 16:57:00 +00:00
use std::rc::{Rc, Weak};
2018-01-17 15:32:33 +00:00
use std::fmt;
use std::collections::HashMap;
2018-01-18 13:39:14 +00:00
use parity_wasm::elements::{Local, Opcodes};
use {Trap, TrapKind, Signature};
2018-01-17 15:32:33 +00:00
use host::Externals;
use runner::{check_function_args, Interpreter};
2018-01-17 15:32:33 +00:00
use value::RuntimeValue;
2018-01-22 16:57:00 +00:00
use module::ModuleInstance;
2018-01-17 15:32:33 +00:00
/// Reference to a function (See [`FuncInstance`] for details).
2018-01-23 16:38:49 +00:00
///
/// This reference has a reference-counting semantics.
///
/// [`FuncInstance`]: struct.FuncInstance.html
2018-01-17 15:32:33 +00:00
#[derive(Clone, Debug)]
pub struct FuncRef(Rc<FuncInstance>);
impl ::std::ops::Deref for FuncRef {
type Target = FuncInstance;
fn deref(&self) -> &FuncInstance {
2018-01-17 15:32:33 +00:00
&self.0
}
}
2018-01-23 16:38:49 +00:00
/// Runtime representation of a function.
///
/// Functions are the unit of orgianization of code in WebAssembly. Each function takes a sequence of values
/// as parameters and either optionally return a value or trap.
2018-01-25 15:10:39 +00:00
/// Functions can call other function including itself (i.e recursive calls are allowed) and imported functions
/// (i.e functions defined in another module or by the host environment).
2018-01-23 16:38:49 +00:00
///
/// Functions can be defined either:
///
/// - by a wasm module,
/// - by the host environment and passed to a wasm module as an import.
/// See more in [`Externals`].
///
/// [`Externals`]: trait.Externals.html
pub struct FuncInstance(FuncInstanceInternal);
2018-01-17 15:32:33 +00:00
#[derive(Clone)]
pub(crate) enum FuncInstanceInternal {
2018-01-17 15:32:33 +00:00
Internal {
2018-01-18 12:48:43 +00:00
signature: Rc<Signature>,
2018-01-22 16:57:00 +00:00
module: Weak<ModuleInstance>,
2018-01-17 15:32:33 +00:00
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.as_internal() {
&FuncInstanceInternal::Internal {
2018-01-18 12:48:43 +00:00
ref signature,
2018-01-17 15:32:33 +00:00
..
} => {
2018-01-23 11:26:45 +00:00
// We can't write description of self.module here, because it generate
2018-01-18 12:48:43 +00:00
// 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
)
}
&FuncInstanceInternal::Host { ref signature, .. } => {
2018-01-18 12:48:43 +00:00
write!(f, "Host {{ signature={:?} }}", signature)
2018-01-17 15:32:33 +00:00
}
}
}
}
impl FuncInstance {
/// Allocate a function instance for a host function.
///
/// When this function instance will be called by the wasm code,
/// the instance of [`Externals`] will be invoked by calling `invoke_index`
/// with specified `host_func_index` here.
/// This call will be made with the `signature` provided here.
///
/// [`Externals`]: trait.Externals.html
pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
let func = FuncInstanceInternal::Host {
signature,
host_func_index,
};
FuncRef(Rc::new(FuncInstance(func)))
}
/// Returns [signature] of this function instance.
///
/// This function instance can only be called with matching signatures.
///
/// [signature]: struct.Signature.html
pub fn signature(&self) -> &Signature {
match *self.as_internal() {
FuncInstanceInternal::Internal { ref signature, .. } => signature,
FuncInstanceInternal::Host { ref signature, .. } => signature,
}
}
pub(crate) fn as_internal(&self) -> &FuncInstanceInternal {
&self.0
}
2018-01-17 15:32:33 +00:00
pub(crate) fn alloc_internal(
2018-01-22 16:57:00 +00:00
module: Weak<ModuleInstance>,
2018-01-18 12:48:43 +00:00
signature: Rc<Signature>,
2018-01-17 15:32:33 +00:00
body: FuncBody,
) -> FuncRef {
let func = FuncInstanceInternal::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(FuncInstance(func)))
2018-01-17 15:32:33 +00:00
}
pub(crate) fn body(&self) -> Option<Rc<FuncBody>> {
match *self.as_internal() {
FuncInstanceInternal::Internal { ref body, .. } => Some(Rc::clone(body)),
FuncInstanceInternal::Host { .. } => None,
2018-01-17 15:32:33 +00:00
}
}
/// Invoke this function.
///
/// # Errors
///
/// Returns `Err` if `args` types is not match function [`signature`] or
/// if [`Trap`] at execution time occured.
///
/// [`signature`]: #method.signature
/// [`Trap`]: #enum.Trap.html
pub fn invoke<E: Externals>(
2018-01-23 15:12:41 +00:00
func: &FuncRef,
args: &[RuntimeValue],
2018-01-17 15:32:33 +00:00
externals: &mut E,
) -> Result<Option<RuntimeValue>, Trap> {
check_function_args(func.signature(), &args).map_err(|_| TrapKind::UnexpectedSignature)?;
match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => {
let mut interpreter = Interpreter::new(externals);
interpreter.start_execution(func, args)
2018-01-17 15:32:33 +00:00
}
FuncInstanceInternal::Host {
ref host_func_index,
..
} => externals.invoke_index(*host_func_index, args.into()),
2018-01-17 15:32:33 +00:00
}
}
}
#[derive(Clone, Debug)]
pub struct FuncBody {
pub locals: Vec<Local>,
pub opcodes: Opcodes,
pub labels: HashMap<usize, usize>,
}