diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index e92c637..f5ecfbf 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -20,9 +20,12 @@ const DEFAULT_FRAME_STACK_LIMIT: usize = 1024; /// Execution context. #[derive(Clone)] -pub struct ExecutionParams { +pub struct ExecutionParams { /// Arguments. pub args: Vec, + + /// 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, } -impl ExecutionParams { +impl ExecutionParams { /// 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 Default for ExecutionParams { fn default() -> Self { ExecutionParams { args: Vec::default(), + state: St::default(), } } } -impl<'a> From> for ExecutionParams { - fn from(args: Vec) -> ExecutionParams { +impl<'a, St: Default> From> for ExecutionParams { + fn from(args: Vec) -> ExecutionParams { ExecutionParams { - args: args + args: args, + state: St::default(), } } } diff --git a/src/interpreter/program.rs b/src/interpreter/program.rs index 365a139..153c757 100644 --- a/src/interpreter/program.rs +++ b/src/interpreter/program.rs @@ -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, ) -> Result { let mut extern_vals = Vec::new(); for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) { diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index 42a90b1..fe477ec 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -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) }, } diff --git a/src/interpreter/store.rs b/src/interpreter/store.rs index b3cc024..f06a54f 100644 --- a/src/interpreter/store.rs +++ b/src/interpreter/store.rs @@ -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( &mut self, module: &Module, extern_vals: &[ExternVal], - start_exec_params: ExecutionParams, + start_exec_params: ExecutionParams, ) -> Result { 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, Error> { - let ExecutionParams { args } = params; + fn invoke(&mut self, func: FuncId, params: ExecutionParams) -> Result, 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) -> Result, Error> { + pub fn invoke_host(&mut self, state: &mut St, host_func: HostFuncId, args: Vec) -> Result, 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!() }