move invoke into Interpreter
This commit is contained in:
parent
0498125070
commit
07267813db
|
@ -1,7 +1,7 @@
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use test::Bencher;
|
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.
|
// Load a module from a file.
|
||||||
fn load_from_file(filename: &str) -> Result<Module, Box<error::Error>> {
|
fn load_from_file(filename: &str) -> Result<Module, Box<error::Error>> {
|
||||||
|
@ -39,7 +39,7 @@ fn bench_tiny_keccak(b: &mut Bencher) {
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
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(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
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.
|
// Verify the result.
|
||||||
|
@ -142,7 +142,7 @@ fn bench_regex_redux(b: &mut Bencher) {
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
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(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
interpreter.reset();
|
||||||
let value =
|
let value = interpreter
|
||||||
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I64(25)], &mut NopExternals, &mut interpreter)
|
.invoke(&func, &[RuntimeValue::I64(25)], &mut NopExternals)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
|
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -214,9 +214,9 @@ fn fac_opt(b: &mut Bencher) {
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
interpreter.reset();
|
||||||
let value =
|
let value = interpreter
|
||||||
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I64(25)], &mut NopExternals, &mut interpreter)
|
.invoke(&func, &[RuntimeValue::I64(25)], &mut NopExternals)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
|
assert_matches!(value, Some(RuntimeValue::I64(7034535277573963776)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -255,9 +255,9 @@ fn recursive_ok(b: &mut Bencher) {
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
interpreter.reset();
|
||||||
let value =
|
let value = interpreter
|
||||||
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I32(8000)], &mut NopExternals, &mut interpreter)
|
.invoke(&func, &[RuntimeValue::I32(8000)], &mut NopExternals)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_matches!(value, Some(RuntimeValue::I32(0)));
|
assert_matches!(value, Some(RuntimeValue::I32(0)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,8 @@ fn recursive_trap(b: &mut Bencher) {
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
interpreter.reset();
|
interpreter.reset();
|
||||||
FuncInstance::invoke_configurable(&func, &[RuntimeValue::I32(1000)], &mut NopExternals, &mut interpreter)
|
interpreter
|
||||||
|
.invoke(&func, &[RuntimeValue::I32(1000)], &mut NopExternals)
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
48
src/func.rs
48
src/func.rs
|
@ -6,7 +6,7 @@ use host::Externals;
|
||||||
use isa;
|
use isa;
|
||||||
use module::ModuleInstance;
|
use module::ModuleInstance;
|
||||||
use parity_wasm::elements::Local;
|
use parity_wasm::elements::Local;
|
||||||
use runner::{check_function_args, Interpreter, InterpreterState};
|
use runner::{Interpreter, InterpreterState};
|
||||||
use types::ValueType;
|
use types::ValueType;
|
||||||
use value::RuntimeValue;
|
use value::RuntimeValue;
|
||||||
use {Signature, Trap};
|
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
|
/// 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
|
/// Host trap happens, caller can use [`resume_execution`] to feed the expected return value back in, and then
|
||||||
/// continue the execution.
|
/// continue the execution.
|
||||||
|
@ -267,7 +223,7 @@ impl FuncInvocation {
|
||||||
if interpreter.state() != &InterpreterState::Initialized {
|
if interpreter.state() != &InterpreterState::Initialized {
|
||||||
return Err(ResumableError::AlreadyStarted);
|
return Err(ResumableError::AlreadyStarted);
|
||||||
}
|
}
|
||||||
Ok(interpreter.start_execution(externals, func, args)?)
|
Ok(interpreter.start_execution(func, args, externals)?)
|
||||||
}
|
}
|
||||||
FuncInvocationKind::Host {
|
FuncInvocationKind::Host {
|
||||||
ref mut finished,
|
ref mut finished,
|
||||||
|
|
|
@ -21,6 +21,7 @@ use host::Externals;
|
||||||
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
||||||
use types::{GlobalDescriptor, TableDescriptor, MemoryDescriptor};
|
use types::{GlobalDescriptor, TableDescriptor, MemoryDescriptor};
|
||||||
use memory_units::Pages;
|
use memory_units::Pages;
|
||||||
|
use runner::Interpreter;
|
||||||
|
|
||||||
/// Reference to a [`ModuleInstance`].
|
/// 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))
|
.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(
|
let start_func = self.instance.func_by_index(start_fn_idx).expect(
|
||||||
"Due to validation start function should exists",
|
"Due to validation start function should exists",
|
||||||
);
|
);
|
||||||
FuncInstance::invoke(&start_func, &[], state)?;
|
Interpreter::new().invoke(&start_func, &[], state)?;
|
||||||
}
|
}
|
||||||
Ok(self.instance)
|
Ok(self.instance)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops;
|
use core::ops;
|
||||||
use core::{u32, usize};
|
use core::{u32, usize};
|
||||||
use func::{FuncInstance, FuncInstanceInternal, FuncRef};
|
use func::{FuncInstanceInternal, FuncRef};
|
||||||
use host::Externals;
|
use host::{Externals, RuntimeArgs};
|
||||||
use isa;
|
use isa;
|
||||||
use memory::MemoryRef;
|
use memory::MemoryRef;
|
||||||
use memory_units::Pages;
|
use memory_units::Pages;
|
||||||
|
@ -222,11 +222,35 @@ impl Interpreter {
|
||||||
&self.state
|
&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,
|
&mut self,
|
||||||
externals: &mut E,
|
|
||||||
func: &FuncRef,
|
func: &FuncRef,
|
||||||
args: &[RuntimeValue],
|
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> {
|
) -> Result<Option<RuntimeValue>, Trap> {
|
||||||
// Ensure that the VM has not been executed. This is checked in `FuncInvocation::start_execution`.
|
// Ensure that the VM has not been executed. This is checked in `FuncInvocation::start_execution`.
|
||||||
assert!(self.state == InterpreterState::Initialized);
|
assert!(self.state == InterpreterState::Initialized);
|
||||||
|
@ -318,12 +342,17 @@ impl Interpreter {
|
||||||
self.call_stack.push(function_context)?;
|
self.call_stack.push(function_context)?;
|
||||||
self.call_stack.push(nested_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);
|
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.
|
// 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)?;
|
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,
|
Ok(val) => val,
|
||||||
Err(trap) => {
|
Err(trap) => {
|
||||||
if trap.kind().is_host() {
|
if trap.kind().is_host() {
|
||||||
|
|
Loading…
Reference in New Issue