make interpreter reusable

This commit is contained in:
Andrew Dirksen 2018-11-19 15:59:23 -08:00
parent 9dd258c2bb
commit 2f7f809fd6
3 changed files with 29 additions and 11 deletions

View File

@ -7,10 +7,7 @@ use host::Externals;
use isa;
use module::ModuleInstance;
use parity_wasm::elements::Local;
use runner::{
check_function_args, FunctionContext, Interpreter, InterpreterState, RuntimeValueInternal,
DEFAULT_CALL_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT,
};
use runner::{check_function_args, Interpreter, InterpreterState, DEFAULT_CALL_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT};
use types::ValueType;
use value::RuntimeValue;
use {Signature, Trap};
@ -136,13 +133,11 @@ impl FuncInstance {
func: &FuncRef,
args: &[RuntimeValue],
externals: &mut E,
value_stack: StackWithLimit<RuntimeValueInternal>,
call_stack: StackWithLimit<FunctionContext>,
interpreter: &mut Interpreter,
) -> Result<Option<RuntimeValue>, Trap> {
check_function_args(func.signature(), &args)?;
match *func.as_internal() {
FuncInstanceInternal::Internal { .. } => {
let mut interpreter = Interpreter::new(value_stack, call_stack);
interpreter.start_execution(externals, func, args, func.signature().return_type())
}
FuncInstanceInternal::Host {
@ -167,7 +162,8 @@ impl FuncInstance {
) -> Result<Option<RuntimeValue>, Trap> {
let value_stack = StackWithLimit::with_size(StackSize::from_element_count(DEFAULT_VALUE_STACK_LIMIT));
let call_stack = StackWithLimit::with_size(StackSize::from_element_count(DEFAULT_CALL_STACK_LIMIT));
Self::invoke_configurable(func, args, externals, value_stack, call_stack)
let mut interpreter = Interpreter::new(value_stack, call_stack);
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

View File

@ -405,6 +405,7 @@ pub use self::global::{GlobalInstance, GlobalRef};
pub use self::func::{FuncInstance, FuncRef, FuncInvocation, ResumableError};
pub use self::types::{Signature, ValueType, GlobalDescriptor, TableDescriptor, MemoryDescriptor};
pub use self::common::stack::{StackWithLimit, StackSize, StackSizeLimit, StackSizeInitial};
pub use self::runner::Interpreter;
/// WebAssembly-specific sizes and units.
pub mod memory_units {

View File

@ -172,6 +172,9 @@ pub struct Interpreter {
}
impl Interpreter {
/// Initialize an interpreter that will use `value_stack` and `call_stack`.
///
/// `value_stack` `call_stack` determine the allowed stack size during later executions.
pub fn new(
value_stack: StackWithLimit<RuntimeValueInternal>,
call_stack: StackWithLimit<FunctionContext>,
@ -183,11 +186,20 @@ impl Interpreter {
}
}
pub fn state(&self) -> &InterpreterState {
// Todo, use types to prevent user from calling start_execution on an inretpreter not in Initialized
// state.
/// Wipe all data in this interpreter, so it can be safely reused.
pub fn reset(&mut self) {
self.value_stack.truncate(0);
self.call_stack.truncate(0);
self.state = InterpreterState::Initialized;
}
pub(crate) fn state(&self) -> &InterpreterState {
&self.state
}
pub fn start_execution<E: Externals>(
pub(crate) fn start_execution<E: Externals>(
&mut self,
externals: &mut E,
func: &FuncRef,
@ -220,7 +232,7 @@ impl Interpreter {
Ok(opt_return_value)
}
pub fn resume_execution<'a, E: Externals + 'a>(
pub(crate) fn resume_execution<'a, E: Externals + 'a>(
&mut self,
return_val: Option<RuntimeValue>,
externals: &'a mut E,
@ -1321,6 +1333,15 @@ impl ValueStack {
fn len(&self) -> usize {
self.0.len()
}
/// Shortens the stack, keeping the first `len` elements and dropping
/// the rest.
///
/// If `len` is greater than the stack's current length, this has no
/// effect.
fn truncate(&mut self, new_len: usize) {
self.0.truncate(new_len)
}
}
impl From<StackOverflow> for TrapKind {