Pass state in ExecutionParams

This commit is contained in:
Sergey Pepyakin
2017-12-11 16:38:52 +01:00
parent 5920cd93d5
commit 8588899f82
4 changed files with 29 additions and 19 deletions

View File

@ -20,9 +20,12 @@ const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
/// Execution context.
#[derive(Clone)]
pub struct ExecutionParams {
pub struct ExecutionParams<St: 'static> {
/// Arguments.
pub args: Vec<RuntimeValue>,
/// State that can be used by host functions,
pub state: St,
}
/// Export type.
@ -76,7 +79,7 @@ pub struct InternalFunction<'a> {
pub labels: &'a HashMap<usize, usize>,
}
impl ExecutionParams {
impl<St> ExecutionParams<St> {
/// Add argument.
pub fn add_argument(mut self, arg: RuntimeValue) -> Self {
self.args.push(arg);
@ -84,18 +87,20 @@ impl ExecutionParams {
}
}
impl Default for ExecutionParams {
impl<St: Default> Default for ExecutionParams<St> {
fn default() -> Self {
ExecutionParams {
args: Vec::default(),
state: St::default(),
}
}
}
impl<'a> From<Vec<RuntimeValue>> for ExecutionParams {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams {
impl<'a, St: Default> From<Vec<RuntimeValue>> for ExecutionParams<St> {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams<St> {
ExecutionParams {
args: args
args: args,
state: St::default(),
}
}
}

View File

@ -22,11 +22,11 @@ impl ProgramInstance {
}
/// Instantiate module with validation.
pub fn add_module<'a>(
pub fn add_module<'a, St: 'static>(
&mut self,
name: &str,
module: Module,
start_exec_params: ExecutionParams,
start_exec_params: ExecutionParams<St>,
) -> Result<ModuleId, Error> {
let mut extern_vals = Vec::new();
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {

View File

@ -18,8 +18,9 @@ use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX, BlockFrame, BlockFrameTy
use common::stack::StackWithLimit;
/// Function interpreter.
pub struct Interpreter<'store> {
pub struct Interpreter<'store, St: 'static> {
store: &'store mut Store,
state: &'store mut St,
}
/// Function execution context.
@ -64,10 +65,11 @@ enum RunResult {
NestedCall(FunctionContext),
}
impl<'store> Interpreter<'store> {
pub fn new(store: &mut Store) -> Interpreter {
impl<'store, St: 'static> Interpreter<'store, St> {
pub fn new(store: &'store mut Store, state: &'store mut St) -> Interpreter<'store, St> {
Interpreter {
store
store,
state
}
}
@ -95,7 +97,7 @@ impl<'store> Interpreter<'store> {
},
FuncInstance::Host { host_func, .. } => {
let args: Vec<_> = function_context.locals.drain(..).collect();
let result = self.store.invoke_host(host_func, args)?;
let result = self.store.invoke_host(self.state, host_func, args)?;
RunResult::Return(result)
},
}

View File

@ -2,6 +2,7 @@
#![allow(unused)]
use std::sync::Arc;
use std::any::Any;
use std::collections::HashMap;
use elements::{FunctionType, GlobalEntry, GlobalType, InitExpr, MemoryType, Module,
Opcode, Opcodes, Local, TableType, Type, Internal};
@ -371,11 +372,11 @@ impl Store {
Ok(())
}
pub fn instantiate_module(
pub fn instantiate_module<St: 'static>(
&mut self,
module: &Module,
extern_vals: &[ExternVal],
start_exec_params: ExecutionParams,
start_exec_params: ExecutionParams<St>,
) -> Result<ModuleId, Error> {
let mut instance = ModuleInstance::new();
// Reserve the index of the module, but not yet push the module.
@ -447,8 +448,8 @@ impl Store {
Ok(module_id)
}
fn invoke(&mut self, func: FuncId, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
let ExecutionParams { args } = params;
fn invoke<St>(&mut self, func: FuncId, params: ExecutionParams<St>) -> Result<Option<RuntimeValue>, Error> {
let ExecutionParams { args, mut state } = params;
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let outer = CallerContext::topmost(&mut args);
let inner = {
@ -457,11 +458,13 @@ impl Store {
let args = prepare_function_args(&func_signature, outer.value_stack)?;
FunctionContext::new(self, func, outer.value_stack_limit, outer.frame_stack_limit, &func_signature, args)
};
let mut interpreter = Interpreter::new(self);
let mut interpreter = Interpreter::new(self, &mut state);
interpreter.run_function(inner)
}
pub fn invoke_host(&mut self, host_func: HostFuncId, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
pub fn invoke_host<St: 'static>(&mut self, state: &mut St, host_func: HostFuncId, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
let host_func_instance = self.host_funcs.get(host_func.0 as usize).expect("ID should be always valid");
host_func_instance.call_as_any(state as &mut Any, &args);
panic!()
}