make the value stack limit and call stack limit as a config parameter
This commit is contained in:
parent
8ca6b4b860
commit
a05fe3f9cd
|
@ -8,7 +8,7 @@ extern crate wabt;
|
|||
|
||||
use std::error;
|
||||
use std::fs::File;
|
||||
use wasmi::{ImportsBuilder, Module, ModuleInstance, NopExternals, RuntimeValue};
|
||||
use wasmi::{ImportsBuilder, InterpreterConfig, Module, ModuleInstance, NopExternals, RuntimeValue};
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
|
@ -30,7 +30,7 @@ fn bench_tiny_keccak(b: &mut Bencher) {
|
|||
"./wasm-kernel/target/wasm32-unknown-unknown/release/wasm_kernel.wasm",
|
||||
).expect("failed to load wasm_kernel. Is `build.rs` broken?");
|
||||
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -52,7 +52,7 @@ fn bench_rev_comp(b: &mut Bencher) {
|
|||
"./wasm-kernel/target/wasm32-unknown-unknown/release/wasm_kernel.wasm",
|
||||
).expect("failed to load wasm_kernel. Is `build.rs` broken?");
|
||||
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -107,7 +107,7 @@ fn bench_regex_redux(b: &mut Bencher) {
|
|||
"./wasm-kernel/target/wasm32-unknown-unknown/release/wasm_kernel.wasm",
|
||||
).expect("failed to load wasm_kernel. Is `build.rs` broken?");
|
||||
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&wasm_kernel, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -163,7 +163,7 @@ r#"
|
|||
|
||||
let module = Module::from_buffer(&wasm).unwrap();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -197,7 +197,7 @@ r#"
|
|||
|
||||
let module = Module::from_buffer(&wasm).unwrap();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -232,7 +232,7 @@ fn recursive_ok(b: &mut Bencher) {
|
|||
).unwrap();
|
||||
let module = Module::from_buffer(&wasm).unwrap();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -266,7 +266,7 @@ fn recursive_trap(b: &mut Bencher) {
|
|||
).unwrap();
|
||||
let module = Module::from_buffer(&wasm).unwrap();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("failed to instantiate wasm module")
|
||||
.assert_no_start();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate wasmi;
|
|||
|
||||
use std::env::args;
|
||||
use std::fs::File;
|
||||
use wasmi::{ModuleInstance, NopExternals, RuntimeValue, ImportsBuilder, Module};
|
||||
use wasmi::{ModuleInstance, NopExternals, RuntimeValue, ImportsBuilder, InterpreterConfig, Module};
|
||||
|
||||
fn load_from_file(filename: &str) -> Module {
|
||||
use std::io::prelude::*;
|
||||
|
@ -31,7 +31,7 @@ fn main() {
|
|||
// - a module declaration
|
||||
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
||||
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
||||
let main = ModuleInstance::new(&module, &ImportsBuilder::default())
|
||||
let main = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.run_start(&mut NopExternals)
|
||||
.expect("Failed to run start function in module");
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate wasmi;
|
|||
use std::env::args;
|
||||
|
||||
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};
|
||||
use wasmi::{RuntimeValue, ModuleInstance, NopExternals, ImportsBuilder};
|
||||
use wasmi::{RuntimeValue, ModuleInstance, NopExternals, ImportsBuilder, InterpreterConfig};
|
||||
|
||||
|
||||
fn main() {
|
||||
|
@ -76,7 +76,7 @@ fn main() {
|
|||
// - a module declaration
|
||||
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
|
||||
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
|
||||
let main = ModuleInstance::new(&loaded_module, &ImportsBuilder::default())
|
||||
let main = ModuleInstance::new(&loaded_module, &ImportsBuilder::default(), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.run_start(&mut NopExternals)
|
||||
.expect("Failed to run start function in module");
|
||||
|
|
|
@ -7,8 +7,8 @@ use std::fs::File;
|
|||
use wasmi::{
|
||||
Error as InterpreterError, ModuleInstance, ModuleRef,
|
||||
Externals, RuntimeValue, FuncRef, ModuleImportResolver,
|
||||
FuncInstance, HostError, ImportsBuilder, Signature, ValueType,
|
||||
RuntimeArgs, Trap,
|
||||
FuncInstance, HostError, ImportsBuilder, InterpreterConfig, Signature,
|
||||
ValueType, RuntimeArgs, Trap,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -201,7 +201,7 @@ fn instantiate(path: &str) -> Result<ModuleRef, Error> {
|
|||
let mut imports = ImportsBuilder::new();
|
||||
imports.push_resolver("env", &RuntimeModuleImportResolver);
|
||||
|
||||
let instance = ModuleInstance::new(&module, &imports)?
|
||||
let instance = ModuleInstance::new(&module, &imports, &InterpreterConfig::default())?
|
||||
.assert_no_start();
|
||||
|
||||
Ok(instance)
|
||||
|
|
|
@ -7,9 +7,9 @@ use std::env::args;
|
|||
use std::fs::File;
|
||||
use wasmi::{
|
||||
Error, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance, GlobalRef,
|
||||
ImportsBuilder, MemoryDescriptor, MemoryInstance, MemoryRef, Module,
|
||||
ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue, Signature,
|
||||
TableDescriptor, TableInstance, TableRef};
|
||||
ImportsBuilder, InterpreterConfig, MemoryDescriptor, MemoryInstance,
|
||||
MemoryRef, Module, ModuleImportResolver, ModuleInstance, NopExternals,
|
||||
RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef};
|
||||
use wasmi::memory_units::*;
|
||||
|
||||
fn load_from_file(filename: &str) -> Module {
|
||||
|
@ -75,6 +75,7 @@ fn main() {
|
|||
.with_resolver("global.Math", &ResolveAll)
|
||||
.with_resolver("asm2wasm", &ResolveAll)
|
||||
.with_resolver("spectest", &ResolveAll),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.run_start(&mut NopExternals)
|
||||
.expect("Failed to run start function in module");
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
|||
use parity_wasm::elements::Local;
|
||||
use {Trap, TrapKind, Signature};
|
||||
use host::Externals;
|
||||
use runner::{check_function_args, Interpreter, InterpreterState};
|
||||
use runner::{check_function_args, InterpreterConfig, Interpreter, InterpreterState};
|
||||
use value::RuntimeValue;
|
||||
use types::ValueType;
|
||||
use module::ModuleInstance;
|
||||
|
@ -141,11 +141,12 @@ impl FuncInstance {
|
|||
func: &FuncRef,
|
||||
args: &[RuntimeValue],
|
||||
externals: &mut E,
|
||||
config: &InterpreterConfig,
|
||||
) -> Result<Option<RuntimeValue>, Trap> {
|
||||
check_function_args(func.signature(), &args).map_err(|_| TrapKind::UnexpectedSignature)?;
|
||||
match *func.as_internal() {
|
||||
FuncInstanceInternal::Internal { .. } => {
|
||||
let mut interpreter = Interpreter::new(func, args)?;
|
||||
let mut interpreter = Interpreter::new(func, args, config)?;
|
||||
interpreter.start_execution(externals)
|
||||
}
|
||||
FuncInstanceInternal::Host {
|
||||
|
@ -172,11 +173,12 @@ impl FuncInstance {
|
|||
pub fn invoke_resumable<'args>(
|
||||
func: &FuncRef,
|
||||
args: &'args [RuntimeValue],
|
||||
config: &InterpreterConfig,
|
||||
) -> Result<FuncInvocation<'args>, Trap> {
|
||||
check_function_args(func.signature(), &args).map_err(|_| TrapKind::UnexpectedSignature)?;
|
||||
match *func.as_internal() {
|
||||
FuncInstanceInternal::Internal { .. } => {
|
||||
let interpreter = Interpreter::new(func, args)?;
|
||||
let interpreter = Interpreter::new(func, args, config)?;
|
||||
Ok(FuncInvocation {
|
||||
kind: FuncInvocationKind::Internal(interpreter),
|
||||
})
|
||||
|
|
|
@ -80,19 +80,19 @@ pub trait ImportResolver {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder};
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder, InterpreterConfig};
|
||||
/// #
|
||||
/// # struct EnvModuleResolver;
|
||||
/// # impl ::wasmi::ModuleImportResolver for EnvModuleResolver { }
|
||||
/// # fn func() -> Result<(), ::wasmi::Error> {
|
||||
/// # let module = wasmi::Module::from_buffer(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]).unwrap();
|
||||
/// # let other_instance = ModuleInstance::new(&module, &ImportsBuilder::default())?.assert_no_start();
|
||||
/// # let other_instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())?.assert_no_start();
|
||||
///
|
||||
/// let imports = ImportsBuilder::new()
|
||||
/// .with_resolver("env", &EnvModuleResolver)
|
||||
/// // Note, that ModuleInstance can be a resolver too.
|
||||
/// .with_resolver("other_instance", &other_instance);
|
||||
/// let instance = ModuleInstance::new(&module, &imports)?.assert_no_start();
|
||||
/// let instance = ModuleInstance::new(&module, &imports, &InterpreterConfig::default())?.assert_no_start();
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
//! extern crate wasmi;
|
||||
//! extern crate wabt;
|
||||
//!
|
||||
//! use wasmi::{ModuleInstance, ImportsBuilder, NopExternals, RuntimeValue};
|
||||
//! use wasmi::{ModuleInstance, ImportsBuilder, InterpreterConfig, NopExternals, RuntimeValue};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! // Parse WAT (WebAssembly Text format) into wasm bytecode.
|
||||
|
@ -76,7 +76,8 @@
|
|||
//! let instance =
|
||||
//! ModuleInstance::new(
|
||||
//! &module,
|
||||
//! &ImportsBuilder::default()
|
||||
//! &ImportsBuilder::default(),
|
||||
//! &InterpreterConfig::default()
|
||||
//! )
|
||||
//! .expect("failed to instantiate wasm module")
|
||||
//! .assert_no_start();
|
||||
|
@ -380,6 +381,7 @@ pub use self::module::{ModuleInstance, ModuleRef, ExternVal, NotStartedModuleRef
|
|||
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::runner::InterpreterConfig;
|
||||
|
||||
/// WebAssembly-specific sizes and units.
|
||||
pub mod memory_units {
|
||||
|
|
|
@ -9,6 +9,7 @@ use {Module, Error, Signature, MemoryInstance, RuntimeValue, TableInstance};
|
|||
use imports::ImportResolver;
|
||||
use global::{GlobalInstance, GlobalRef};
|
||||
use func::{FuncRef, FuncBody, FuncInstance};
|
||||
use runner::InterpreterConfig;
|
||||
use table::TableRef;
|
||||
use memory::MemoryRef;
|
||||
use host::Externals;
|
||||
|
@ -155,6 +156,7 @@ pub struct ModuleInstance {
|
|||
memories: RefCell<Vec<MemoryRef>>,
|
||||
globals: RefCell<Vec<GlobalRef>>,
|
||||
exports: RefCell<HashMap<String, ExternVal>>,
|
||||
config: InterpreterConfig,
|
||||
}
|
||||
|
||||
impl ModuleInstance {
|
||||
|
@ -166,6 +168,7 @@ impl ModuleInstance {
|
|||
memories: RefCell::new(Vec::new()),
|
||||
globals: RefCell::new(Vec::new()),
|
||||
exports: RefCell::new(HashMap::new()),
|
||||
config: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,6 +402,7 @@ impl ModuleInstance {
|
|||
pub fn with_externvals<'a, 'i, I: Iterator<Item = &'i ExternVal>>(
|
||||
loaded_module: &'a Module,
|
||||
extern_vals: I,
|
||||
config: &InterpreterConfig,
|
||||
) -> Result<NotStartedModuleRef<'a>, Error> {
|
||||
let module = loaded_module.module();
|
||||
|
||||
|
@ -449,6 +453,7 @@ impl ModuleInstance {
|
|||
Ok(NotStartedModuleRef {
|
||||
loaded_module,
|
||||
instance: module_ref,
|
||||
config: config.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -474,14 +479,15 @@ impl ModuleInstance {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder, NopExternals};
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder, InterpreterConfig, NopExternals};
|
||||
/// # fn func() -> Result<(), ::wasmi::Error> {
|
||||
/// # let module = wasmi::Module::from_buffer(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]).unwrap();
|
||||
///
|
||||
/// // ModuleInstance::new returns instance which `start` function isn't called.
|
||||
/// let not_started = ModuleInstance::new(
|
||||
/// &module,
|
||||
/// &ImportsBuilder::default()
|
||||
/// &ImportsBuilder::default(),
|
||||
/// &InterpreterConfig::default()
|
||||
/// )?;
|
||||
/// // Call `start` function if any.
|
||||
/// let instance = not_started.run_start(&mut NopExternals)?;
|
||||
|
@ -494,14 +500,15 @@ impl ModuleInstance {
|
|||
/// instantiated module without calling `start` function.
|
||||
///
|
||||
/// ```rust
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder, NopExternals};
|
||||
/// use wasmi::{ModuleInstance, ImportsBuilder, InterpreterConfig, NopExternals};
|
||||
/// # fn func() -> Result<(), ::wasmi::Error> {
|
||||
/// # let module = wasmi::Module::from_buffer(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]).unwrap();
|
||||
///
|
||||
/// // This will panic if the module actually contain `start` function.
|
||||
/// let not_started = ModuleInstance::new(
|
||||
/// &module,
|
||||
/// &ImportsBuilder::default()
|
||||
/// &ImportsBuilder::default(),
|
||||
/// &InterpreterConfig::default()
|
||||
/// )?.assert_no_start();
|
||||
///
|
||||
/// # Ok(())
|
||||
|
@ -515,6 +522,7 @@ impl ModuleInstance {
|
|||
pub fn new<'m, I: ImportResolver>(
|
||||
loaded_module: &'m Module,
|
||||
imports: &I,
|
||||
config: &InterpreterConfig
|
||||
) -> Result<NotStartedModuleRef<'m>, Error> {
|
||||
let module = loaded_module.module();
|
||||
|
||||
|
@ -551,7 +559,7 @@ impl ModuleInstance {
|
|||
extern_vals.push(extern_val);
|
||||
}
|
||||
|
||||
Self::with_externvals(loaded_module, extern_vals.iter())
|
||||
Self::with_externvals(loaded_module, extern_vals.iter(), config)
|
||||
}
|
||||
|
||||
/// Invoke exported function by a name.
|
||||
|
@ -574,7 +582,7 @@ impl ModuleInstance {
|
|||
/// ```rust
|
||||
/// # extern crate wasmi;
|
||||
/// # extern crate wabt;
|
||||
/// # use wasmi::{ModuleInstance, ImportsBuilder, NopExternals, RuntimeValue};
|
||||
/// # use wasmi::{ModuleInstance, ImportsBuilder, InterpreterConfig, NopExternals, RuntimeValue};
|
||||
/// # fn main() {
|
||||
/// # let wasm_binary: Vec<u8> = wabt::wat2wasm(
|
||||
/// # r#"
|
||||
|
@ -590,7 +598,8 @@ impl ModuleInstance {
|
|||
/// # let module = wasmi::Module::from_buffer(&wasm_binary).expect("failed to load wasm");
|
||||
/// # let instance = ModuleInstance::new(
|
||||
/// # &module,
|
||||
/// # &ImportsBuilder::default()
|
||||
/// # &ImportsBuilder::default(),
|
||||
/// # &InterpreterConfig::default()
|
||||
/// # ).expect("failed to instantiate wasm module").assert_no_start();
|
||||
/// assert_eq!(
|
||||
/// instance.invoke_export(
|
||||
|
@ -624,7 +633,7 @@ impl ModuleInstance {
|
|||
};
|
||||
|
||||
check_function_args(func_instance.signature(), &args)?;
|
||||
FuncInstance::invoke(&func_instance, args, externals)
|
||||
FuncInstance::invoke(&func_instance, args, externals, &self.config)
|
||||
.map_err(|t| Error::Trap(t))
|
||||
}
|
||||
|
||||
|
@ -657,6 +666,7 @@ impl ModuleInstance {
|
|||
pub struct NotStartedModuleRef<'a> {
|
||||
loaded_module: &'a Module,
|
||||
instance: ModuleRef,
|
||||
config: InterpreterConfig,
|
||||
}
|
||||
|
||||
impl<'a> NotStartedModuleRef<'a> {
|
||||
|
@ -683,7 +693,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)?;
|
||||
FuncInstance::invoke(&start_func, &[], state, &self.config)?;
|
||||
}
|
||||
Ok(self.instance)
|
||||
}
|
||||
|
@ -765,6 +775,7 @@ pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
|
|||
mod tests {
|
||||
use imports::ImportsBuilder;
|
||||
use func::FuncInstance;
|
||||
use runner::InterpreterConfig;
|
||||
use types::{Signature, ValueType};
|
||||
use super::{ModuleInstance, ExternVal};
|
||||
use tests::parse_wat;
|
||||
|
@ -781,7 +792,8 @@ mod tests {
|
|||
);
|
||||
ModuleInstance::new(
|
||||
&module_with_start,
|
||||
&ImportsBuilder::default()
|
||||
&ImportsBuilder::default(),
|
||||
&InterpreterConfig::default()
|
||||
).unwrap().assert_no_start();
|
||||
}
|
||||
|
||||
|
@ -801,6 +813,7 @@ mod tests {
|
|||
[
|
||||
ExternVal::Func(FuncInstance::alloc_host(Signature::new(&[][..], None), 0),)
|
||||
].iter(),
|
||||
&InterpreterConfig::default()
|
||||
).is_ok()
|
||||
);
|
||||
|
||||
|
@ -812,11 +825,12 @@ mod tests {
|
|||
ExternVal::Func(FuncInstance::alloc_host(Signature::new(&[][..], None), 0)),
|
||||
ExternVal::Func(FuncInstance::alloc_host(Signature::new(&[][..], None), 1)),
|
||||
].iter(),
|
||||
&InterpreterConfig::default()
|
||||
).is_err()
|
||||
);
|
||||
|
||||
// externval vector is shorter than import count.
|
||||
assert!(ModuleInstance::with_externvals(&module_with_single_import, [].iter(),).is_err());
|
||||
assert!(ModuleInstance::with_externvals(&module_with_single_import, [].iter(), &InterpreterConfig::default()).is_err());
|
||||
|
||||
// externval vector has an unexpected type.
|
||||
assert!(
|
||||
|
@ -828,6 +842,7 @@ mod tests {
|
|||
0
|
||||
),)
|
||||
].iter(),
|
||||
&InterpreterConfig::default()
|
||||
).is_err()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,9 @@ use nan_preserving_float::{F32, F64};
|
|||
use isa;
|
||||
|
||||
/// Maximum number of entries in value stack.
|
||||
pub const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::std::mem::size_of::<RuntimeValue>();
|
||||
const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::std::mem::size_of::<RuntimeValue>();
|
||||
|
||||
// TODO: Make these parameters changeble.
|
||||
pub const DEFAULT_CALL_STACK_LIMIT: usize = 64 * 1024;
|
||||
const DEFAULT_CALL_STACK_LIMIT: usize = 64 * 1024;
|
||||
|
||||
/// Interpreter action to execute after executing instruction.
|
||||
pub enum InstructionOutcome {
|
||||
|
@ -65,17 +64,35 @@ enum RunResult {
|
|||
NestedCall(FuncRef),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Config parameters for interpreter
|
||||
pub struct InterpreterConfig {
|
||||
pub value_stack_limit: usize,
|
||||
pub call_stack_limit: usize,
|
||||
}
|
||||
|
||||
impl Default for InterpreterConfig {
|
||||
fn default() -> Self {
|
||||
return InterpreterConfig {
|
||||
value_stack_limit: DEFAULT_VALUE_STACK_LIMIT,
|
||||
call_stack_limit: DEFAULT_CALL_STACK_LIMIT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Function interpreter.
|
||||
pub struct Interpreter {
|
||||
value_stack: ValueStack,
|
||||
call_stack: Vec<FunctionContext>,
|
||||
return_type: Option<ValueType>,
|
||||
state: InterpreterState,
|
||||
config: InterpreterConfig,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new(func: &FuncRef, args: &[RuntimeValue]) -> Result<Interpreter, Trap> {
|
||||
let mut value_stack = ValueStack::with_limit(DEFAULT_VALUE_STACK_LIMIT);
|
||||
pub fn new(func: &FuncRef, args: &[RuntimeValue], config: &InterpreterConfig) -> Result<Interpreter, Trap> {
|
||||
let mut value_stack = ValueStack::with_limit(config.value_stack_limit);
|
||||
for arg in args {
|
||||
value_stack
|
||||
.push(*arg)
|
||||
|
@ -97,6 +114,7 @@ impl Interpreter {
|
|||
call_stack,
|
||||
return_type,
|
||||
state: InterpreterState::Initialized,
|
||||
config: config.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -187,7 +205,7 @@ impl Interpreter {
|
|||
}
|
||||
},
|
||||
RunResult::NestedCall(nested_func) => {
|
||||
if self.call_stack.len() + 1 >= DEFAULT_CALL_STACK_LIMIT {
|
||||
if self.call_stack.len() + 1 >= self.config.call_stack_limit {
|
||||
return Err(TrapKind::StackOverflow.into());
|
||||
}
|
||||
|
||||
|
@ -202,7 +220,7 @@ impl Interpreter {
|
|||
// 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 FuncInstance::invoke(&nested_func, &args, externals, &self.config) {
|
||||
Ok(val) => val,
|
||||
Err(trap) => {
|
||||
if trap.kind().is_host() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use {
|
||||
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
|
||||
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder, InterpreterConfig,
|
||||
MemoryInstance, MemoryRef, TableInstance, TableRef, ModuleImportResolver, ModuleInstance, ModuleRef,
|
||||
RuntimeValue, RuntimeArgs, TableDescriptor, MemoryDescriptor, Trap, TrapKind, ResumableError,
|
||||
};
|
||||
|
@ -239,7 +239,7 @@ fn call_host_func() {
|
|||
|
||||
let mut env = TestHost::new();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -270,14 +270,14 @@ fn resume_call_host_func() {
|
|||
|
||||
let mut env = TestHost::new();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
let export = instance.export_by_name("test").unwrap();
|
||||
let func_instance = export.as_func().unwrap();
|
||||
|
||||
let mut invocation = FuncInstance::invoke_resumable(&func_instance, &[]).unwrap();
|
||||
let mut invocation = FuncInstance::invoke_resumable(&func_instance, &[], &InterpreterConfig::default()).unwrap();
|
||||
let result = invocation.start_execution(&mut env);
|
||||
match result {
|
||||
Err(ResumableError::Trap(_)) => {},
|
||||
|
@ -312,7 +312,7 @@ fn host_err() {
|
|||
|
||||
let mut env = TestHost::new();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -347,7 +347,7 @@ fn modify_mem_with_host_funcs() {
|
|||
|
||||
let mut env = TestHost::new();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -391,7 +391,7 @@ fn pull_internal_mem_from_module() {
|
|||
trap_sub_result: None,
|
||||
};
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -442,7 +442,7 @@ fn recursion() {
|
|||
|
||||
let mut env = TestHost::new();
|
||||
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env))
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &env), &InterpreterConfig::default())
|
||||
.expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -554,6 +554,7 @@ fn defer_providing_externals() {
|
|||
let instance = ModuleInstance::new(
|
||||
&module,
|
||||
&ImportsBuilder::new().with_resolver("host", &host_import_resolver),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -673,6 +674,7 @@ fn two_envs_one_externals() {
|
|||
let trusted_instance = ModuleInstance::new(
|
||||
&trusted_module,
|
||||
&ImportsBuilder::new().with_resolver("env", &PrivilegedResolver),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -681,6 +683,7 @@ fn two_envs_one_externals() {
|
|||
&ImportsBuilder::new()
|
||||
.with_resolver("env", &OrdinaryResolver)
|
||||
.with_resolver("trusted", &trusted_instance),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -788,6 +791,7 @@ fn dynamically_add_host_func() {
|
|||
let instance = ModuleInstance::new(
|
||||
&module,
|
||||
&ImportsBuilder::new().with_resolver("env", &host_externals),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use {
|
||||
Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
|
||||
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
|
||||
TableInstance, TableRef, Module, GlobalDescriptor, TableDescriptor, MemoryDescriptor,
|
||||
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
|
||||
TableInstance, TableRef, Module, GlobalDescriptor, TableDescriptor, MemoryDescriptor,
|
||||
InterpreterConfig
|
||||
};
|
||||
use memory_units::Pages;
|
||||
use std::fs::File;
|
||||
|
@ -93,6 +94,7 @@ fn interpreter_inc_i32() {
|
|||
let instance = ModuleInstance::new(
|
||||
&module,
|
||||
&ImportsBuilder::new().with_resolver("env", &env),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
@ -124,6 +126,7 @@ fn interpreter_accumulate_u8() {
|
|||
let instance = ModuleInstance::new(
|
||||
&module,
|
||||
&ImportsBuilder::new().with_resolver("env", &env),
|
||||
&InterpreterConfig::default()
|
||||
).expect("Failed to instantiate module")
|
||||
.assert_no_start();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::collections::HashMap;
|
|||
use wabt::script::{self, Action, Command, CommandKind, ScriptParser, Value};
|
||||
use wasmi::memory_units::Pages;
|
||||
use wasmi::{Error as InterpreterError, Externals, FuncInstance, FuncRef, GlobalDescriptor,
|
||||
GlobalInstance, GlobalRef, ImportResolver, ImportsBuilder, MemoryDescriptor,
|
||||
GlobalInstance, GlobalRef, ImportResolver, ImportsBuilder, InterpreterConfig, MemoryDescriptor,
|
||||
MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, ModuleRef,
|
||||
RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, Trap};
|
||||
|
||||
|
@ -261,7 +261,7 @@ fn try_load_module(wasm: &[u8]) -> Result<Module, Error> {
|
|||
|
||||
fn try_load(wasm: &[u8], spec_driver: &mut SpecDriver) -> Result<(), Error> {
|
||||
let module = try_load_module(wasm)?;
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())?;
|
||||
let instance = ModuleInstance::new(&module, &ImportsBuilder::default(), &InterpreterConfig::default())?;
|
||||
instance
|
||||
.run_start(spec_driver.spec_module())
|
||||
.map_err(|trap| Error::Start(trap))?;
|
||||
|
@ -274,7 +274,7 @@ fn load_module(
|
|||
spec_driver: &mut SpecDriver,
|
||||
) -> Result<ModuleRef, Error> {
|
||||
let module = try_load_module(wasm)?;
|
||||
let instance = ModuleInstance::new(&module, spec_driver)
|
||||
let instance = ModuleInstance::new(&module, spec_driver, &InterpreterConfig::default())
|
||||
.map_err(|e| Error::Load(e.to_string()))?
|
||||
.run_start(spec_driver.spec_module())
|
||||
.map_err(|trap| Error::Start(trap))?;
|
||||
|
|
Loading…
Reference in New Issue