move invoke into Interpreter
This commit is contained in:
parent
0498125070
commit
07267813db
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
48
src/func.rs
48
src/func.rs
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue