move invoke into Interpreter

This commit is contained in:
Andrew Dirksen 2018-11-21 16:58:33 -08:00
parent 0498125070
commit 07267813db
4 changed files with 55 additions and 68 deletions

View File

@ -1,7 +1,7 @@
use std::error;
use std::fs::File;
use test::Bencher;
use wasmi::{FuncInstance, ImportsBuilder, Interpreter, Module, ModuleInstance, NopExternals, RuntimeValue};
use wasmi::{ImportsBuilder, Interpreter, Module, ModuleInstance, NopExternals, RuntimeValue};
// Load a module from a file.
fn load_from_file(filename: &str) -> Result<Module, Box<error::Error>> {
@ -39,7 +39,7 @@ fn bench_tiny_keccak(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
FuncInstance::invoke_configurable(&func, &[test_data_ptr], &mut NopExternals, &mut interpreter).unwrap()
interpreter.invoke(&func, &[test_data_ptr], &mut NopExternals).unwrap()
});
}
@ -85,7 +85,7 @@ fn bench_rev_comp(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
FuncInstance::invoke_configurable(&func, &[test_data_ptr], &mut NopExternals, &mut interpreter).unwrap()
interpreter.invoke(&func, &[test_data_ptr], &mut NopExternals).unwrap()
});
// Verify the result.
@ -142,7 +142,7 @@ fn bench_regex_redux(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
FuncInstance::invoke_configurable(&func, &[test_data_ptr], &mut NopExternals, &mut interpreter).unwrap()
interpreter.invoke(&func, &[test_data_ptr], &mut NopExternals).unwrap()
});
}
@ -174,9 +174,9 @@ fn fac_recursive(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
let value =
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I64(25)], &mut NopExternals, &mut interpreter)
.unwrap();
let value = interpreter
.invoke(&func, &[RuntimeValue::I64(25)], &mut NopExternals)
.unwrap();
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
});
}
@ -214,9 +214,9 @@ fn fac_opt(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
let value =
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I64(25)], &mut NopExternals, &mut interpreter)
.unwrap();
let value = interpreter
.invoke(&func, &[RuntimeValue::I64(25)], &mut NopExternals)
.unwrap();
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
});
}
@ -255,9 +255,9 @@ fn recursive_ok(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
let value =
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I32(8000)], &mut NopExternals, &mut interpreter)
.unwrap();
let value = interpreter
.invoke(&func, &[RuntimeValue::I32(8000)], &mut NopExternals)
.unwrap();
assert_matches!(value, Some(RuntimeValue::I32(0)));
});
}
@ -295,7 +295,8 @@ fn recursive_trap(b: &mut Bencher) {
b.iter(|| {
interpreter.reset();
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I32(1000)], &mut NopExternals, &mut interpreter)
interpreter
.invoke(&func, &[RuntimeValue::I32(1000)], &mut NopExternals)
.unwrap_err();
});
}

View File

@ -6,7 +6,7 @@ use host::Externals;
use isa;
use module::ModuleInstance;
use parity_wasm::elements::Local;
use runner::{check_function_args, Interpreter, InterpreterState};
use runner::{Interpreter, InterpreterState};
use types::ValueType;
use value::RuntimeValue;
use {Signature, Trap};
@ -117,50 +117,6 @@ impl FuncInstance {
}
}
/// Invoke this function with extra configuration parameters.
///
/// This is an experimental API
///
/// # 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_configurable<E: Externals>(
func: &FuncRef,
args: &[RuntimeValue],
externals: &mut E,
interpreter: &mut Interpreter,
) -> Result<Option<RuntimeValue>, Trap> {
check_function_args(func.signature(), &args)?;
match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => interpreter.start_execution(externals, func, args),
FuncInstanceInternal::Host {
ref host_func_index, ..
} => externals.invoke_index(*host_func_index, args.into()),
}
}
/// 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>(
func: &FuncRef,
args: &[RuntimeValue],
externals: &mut E,
) -> Result<Option<RuntimeValue>, Trap> {
let mut interpreter = Interpreter::new();
Self::invoke_configurable(func, args, externals, &mut interpreter)
}
/// Invoke the function, get a resumable handle. This handle can then be used to [`start_execution`]. If a
/// Host trap happens, caller can use [`resume_execution`] to feed the expected return value back in, and then
/// continue the execution.
@ -267,7 +223,7 @@ impl FuncInvocation {
if interpreter.state() != &InterpreterState::Initialized {
return Err(ResumableError::AlreadyStarted);
}
Ok(interpreter.start_execution(externals, func, args)?)
Ok(interpreter.start_execution(func, args, externals)?)
}
FuncInvocationKind::Host {
ref mut finished,

View File

@ -21,6 +21,7 @@ use host::Externals;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
use types::{GlobalDescriptor, TableDescriptor, MemoryDescriptor};
use memory_units::Pages;
use runner::Interpreter;
/// Reference to a [`ModuleInstance`].
///
@ -629,7 +630,7 @@ impl ModuleInstance {
}
};
FuncInstance::invoke(&func_instance, args, externals)
Interpreter::new().invoke(&func_instance, args, externals)
.map_err(|t| Error::Trap(t))
}
@ -688,7 +689,7 @@ impl<'a> NotStartedModuleRef<'a> {
let start_func = self.instance.func_by_index(start_fn_idx).expect(
"Due to validation start function should exists",
);
FuncInstance::invoke(&start_func, &[], state)?;
Interpreter::new().invoke(&start_func, &[], state)?;
}
Ok(self.instance)
}

View File

@ -5,8 +5,8 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
use core::fmt;
use core::ops;
use core::{u32, usize};
use func::{FuncInstance, FuncInstanceInternal, FuncRef};
use host::Externals;
use func::{FuncInstanceInternal, FuncRef};
use host::{Externals, RuntimeArgs};
use isa;
use memory::MemoryRef;
use memory_units::Pages;
@ -222,11 +222,35 @@ impl Interpreter {
&self.state
}
pub(crate) fn start_execution<E: Externals>(
/// Run func using this interpreter.
///
/// # 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>(
&mut self,
externals: &mut E,
func: &FuncRef,
args: &[RuntimeValue],
externals: &mut E,
) -> Result<Option<RuntimeValue>, Trap> {
check_function_args(func.signature(), &args)?;
match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => self.start_execution(func, args, externals),
FuncInstanceInternal::Host {
ref host_func_index, ..
} => externals.invoke_index(*host_func_index, args.into()),
}
}
pub(crate) fn start_execution<E: Externals>(
&mut self,
func: &FuncRef,
args: &[RuntimeValue],
externals: &mut E,
) -> Result<Option<RuntimeValue>, Trap> {
// Ensure that the VM has not been executed. This is checked in `FuncInvocation::start_execution`.
assert!(self.state == InterpreterState::Initialized);
@ -318,12 +342,17 @@ impl Interpreter {
self.call_stack.push(function_context)?;
self.call_stack.push(nested_context)?;
}
FuncInstanceInternal::Host { ref signature, .. } => {
FuncInstanceInternal::Host {
ref signature,
host_func_index,
} => {
let args = prepare_function_args(signature, &mut self.value_stack);
// We push the function context first. If the VM is not resumable, it does no harm. If it is, we then save the context here.
self.call_stack.push(function_context)?;
let return_val = match FuncInstance::invoke(&nested_func, &args, externals) {
let return_val = match externals
.invoke_index(host_func_index, RuntimeArgs::from(args.as_ref()))
{
Ok(val) => val,
Err(trap) => {
if trap.kind().is_host() {