diff --git a/lib/jit/src/action.rs b/lib/jit/src/action.rs index 3dd6c8a867..820ba51d7e 100644 --- a/lib/jit/src/action.rs +++ b/lib/jit/src/action.rs @@ -254,7 +254,11 @@ pub fn inspect_memory<'instance>( /// Read a global in this `Instance` identified by an export name. pub fn get(instance: &Instance, global_name: &str) -> Result { let (definition, global) = match unsafe { instance.lookup_immutable(global_name) } { - Some(Export::Global { definition, global }) => (definition, global), + Some(Export::Global { + definition, + vmctx: _, + global, + }) => (definition, global), Some(_) => { return Err(ActionError::Kind(format!( "exported item \"{}\" is not a global variable", diff --git a/lib/jit/src/context.rs b/lib/jit/src/context.rs index ba23305548..4037e92d16 100644 --- a/lib/jit/src/context.rs +++ b/lib/jit/src/context.rs @@ -1,6 +1,7 @@ +use crate::action::{get, inspect_memory, invoke}; use crate::{ - instantiate, ActionError, ActionOutcome, Compiler, Instance, InstanceIndex, Namespace, - RuntimeValue, SetupError, + instantiate, ActionError, ActionOutcome, Compiler, Instance, Namespace, RuntimeValue, + SetupError, }; use cranelift_codegen::isa::TargetIsa; use std::borrow::ToOwned; @@ -96,13 +97,10 @@ impl Context { ) } - /// Return the instance index for the instance with the given name. - pub fn get_instance_index( - &mut self, - instance_name: &str, - ) -> Result { + /// Return the instance associated with the given name. + pub fn get_instance(&mut self, instance_name: &str) -> Result<&mut Instance, UnknownInstance> { self.namespace - .get_instance_index(instance_name) + .get_instance(instance_name) .ok_or_else(|| UnknownInstance { instance_name: instance_name.to_string(), }) @@ -113,72 +111,84 @@ impl Context { &mut self, instance_name: Option, data: &[u8], - ) -> Result { + ) -> Result { let instance = self.instantiate(data).map_err(ActionError::Setup)?; - Ok(self.instance(instance_name, instance)) + self.optionally_name_instance(instance_name, instance.clone()); + Ok(instance) } - /// Install a new `Instance` in this `Namespace`, optionally with the - /// given name, and return its index. - pub fn instance(&mut self, instance_name: Option, instance: Instance) -> InstanceIndex { - self.namespace.instance(instance_name, instance) + /// If `name` isn't None, register it for the given instance. + pub fn optionally_name_instance(&mut self, name: Option, instance: Instance) { + if let Some(name) = name { + self.namespace.name_instance(name, instance); + } + } + + /// Register a name for the given instance. + pub fn name_instance(&mut self, name: String, instance: Instance) { + self.namespace.name_instance(name, instance); } /// Register an additional name for an existing registered instance. pub fn alias(&mut self, name: &str, as_name: String) -> Result<(), UnknownInstance> { - let index = self.get_instance_index(&name)?; - self.alias_for_indexed(index, as_name); + let instance = self.get_instance(&name)?.clone(); + self.name_instance(as_name, instance); Ok(()) } - /// Register an additional name for an existing registered instance. - pub fn alias_for_indexed(&mut self, index: InstanceIndex, as_name: String) { - self.namespace.alias_for_indexed(index, as_name) - } - - /// Invoke an exported function from an instance. - pub fn invoke( + /// Invoke an exported function from a named instance. + pub fn invoke_named( &mut self, instance_name: &str, field: &str, args: &[RuntimeValue], ) -> Result { - let index = self - .get_instance_index(&instance_name) - .map_err(ContextError::Instance)?; - self.invoke_indexed(index, field, args) + let mut instance = self + .get_instance(&instance_name) + .map_err(ContextError::Instance)? + .clone(); + self.invoke(&mut instance, field, args) .map_err(ContextError::Action) } /// Invoke an exported function from an instance. - pub fn invoke_indexed( + pub fn invoke( &mut self, - index: InstanceIndex, + instance: &mut Instance, field: &str, args: &[RuntimeValue], ) -> Result { - self.namespace - .invoke(&mut *self.compiler, index, field, &args) + invoke(&mut *self.compiler, instance, field, &args) } /// Get the value of an exported global variable from an instance. - pub fn get(&mut self, instance_name: &str, field: &str) -> Result { - let index = self - .get_instance_index(&instance_name) - .map_err(ContextError::Instance)?; - self.get_indexed(index, field).map_err(ContextError::Action) - } - - /// Get the value of an exported global variable from an instance. - pub fn get_indexed( + pub fn get_named( &mut self, - index: InstanceIndex, + instance_name: &str, field: &str, - ) -> Result { - self.namespace - .get(index, field) - .map(|value| ActionOutcome::Returned { - values: vec![value], - }) + ) -> Result { + let mut instance = self + .get_instance(&instance_name) + .map_err(ContextError::Instance)? + .clone(); + self.get(&mut instance, field).map_err(ContextError::Action) + } + + /// Get the value of an exported global variable from an instance. + pub fn get(&mut self, instance: &Instance, field: &str) -> Result { + get(instance, field).map(|value| ActionOutcome::Returned { + values: vec![value], + }) + } + + /// Get a slice of memory from an instance. + pub fn inspect_memory<'instance>( + &self, + instance: &'instance Instance, + field_name: &str, + start: usize, + len: usize, + ) -> Result<&'instance [u8], ActionError> { + inspect_memory(instance, field_name, start, len) } } diff --git a/lib/jit/src/lib.rs b/lib/jit/src/lib.rs index a6ff8447a5..23bdeb8ec3 100644 --- a/lib/jit/src/lib.rs +++ b/lib/jit/src/lib.rs @@ -56,7 +56,7 @@ pub use crate::compiler::Compiler; pub use crate::context::{Context, ContextError, UnknownInstance}; pub use crate::instantiate::{instantiate, CompiledModule, SetupError}; pub use crate::link::link_module; -pub use crate::namespace::{InstanceIndex, Namespace}; +pub use crate::namespace::Namespace; pub use crate::resolver::{NullResolver, Resolver}; pub use crate::target_tunables::target_tunables; diff --git a/lib/jit/src/link.rs b/lib/jit/src/link.rs index be88aba381..aa42554a67 100644 --- a/lib/jit/src/link.rs +++ b/lib/jit/src/link.rs @@ -5,14 +5,15 @@ use core::ptr::write_unaligned; use cranelift_codegen::binemit::Reloc; use cranelift_entity::PrimaryMap; use cranelift_wasm::{DefinedFuncIndex, Global, GlobalInit, Memory, Table, TableElementType}; +use std::collections::HashSet; use std::vec::Vec; use wasmtime_environ::{ MemoryPlan, MemoryStyle, Module, Relocation, RelocationTarget, Relocations, TablePlan, }; use wasmtime_runtime::libcalls; use wasmtime_runtime::{ - Export, Imports, LinkError, VMFunctionBody, VMFunctionImport, VMGlobalImport, VMMemoryImport, - VMTableImport, + Export, Imports, Instance, LinkError, VMFunctionBody, VMFunctionImport, VMGlobalImport, + VMMemoryImport, VMTableImport, }; /// Links a module that has been compiled with `compiled_module` in `wasmtime-environ`. @@ -22,6 +23,8 @@ pub fn link_module( relocations: Relocations, resolver: &mut dyn Resolver, ) -> Result { + let mut dependencies = HashSet::new(); + let mut function_imports = PrimaryMap::with_capacity(module.imported_funcs.len()); for (index, (ref module_name, ref field)) in module.imported_funcs.iter() { match resolver.resolve(module_name, field) { @@ -41,6 +44,7 @@ pub fn link_module( signature, import_signature) )); } + dependencies.insert(Instance::from_vmctx(vmctx)); function_imports.push(VMFunctionImport { body: address, vmctx, @@ -78,6 +82,7 @@ pub fn link_module( module_name, field, ))); } + dependencies.insert(Instance::from_vmctx(vmctx)); table_imports.push(VMTableImport { from: definition, vmctx, @@ -131,6 +136,7 @@ pub fn link_module( } assert!(memory.offset_guard_size >= import_memory.offset_guard_size); + dependencies.insert(Instance::from_vmctx(vmctx)); memory_imports.push(VMMemoryImport { from: definition, vmctx, @@ -156,7 +162,17 @@ pub fn link_module( for (index, (ref module_name, ref field)) in module.imported_globals.iter() { match resolver.resolve(module_name, field) { Some(export_value) => match export_value { - Export::Global { definition, global } => { + Export::Table { .. } | Export::Memory { .. } | Export::Function { .. } => { + return Err(LinkError(format!( + "{}/{}: exported global incompatible with global import", + module_name, field + ))); + } + Export::Global { + definition, + vmctx, + global, + } => { let imported_global = module.globals[index]; if !is_global_compatible(&global, &imported_global) { return Err(LinkError(format!( @@ -164,14 +180,9 @@ pub fn link_module( module_name, field ))); } + dependencies.insert(Instance::from_vmctx(vmctx)); global_imports.push(VMGlobalImport { from: definition }); } - Export::Table { .. } | Export::Memory { .. } | Export::Function { .. } => { - return Err(LinkError(format!( - "{}/{}: exported global incompatible with global import", - module_name, field - ))); - } }, None => { return Err(LinkError(format!( @@ -186,6 +197,7 @@ pub fn link_module( relocate(allocated_functions, relocations, module); Ok(Imports::new( + dependencies, function_imports, table_imports, memory_imports, diff --git a/lib/jit/src/namespace.rs b/lib/jit/src/namespace.rs index e5c2eb24e8..93cd459b7a 100644 --- a/lib/jit/src/namespace.rs +++ b/lib/jit/src/namespace.rs @@ -3,29 +3,17 @@ //! and resolve imports to exports among them. use super::HashMap; -use crate::action::{get, inspect_memory, invoke}; -use crate::action::{ActionError, ActionOutcome, RuntimeValue}; -use crate::compiler::Compiler; use crate::resolver::Resolver; -use cranelift_entity::PrimaryMap; use std::string::String; use wasmtime_runtime::{Export, Instance}; -/// An opaque reference to an `Instance` within a `Namespace`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct InstanceIndex(u32); -entity_impl!(InstanceIndex, "instance"); - /// A namespace containing instances keyed by name. /// /// Note that `Namespace` implements the `Resolver` trait, so it can resolve /// imports using defined exports. pub struct Namespace { /// Mapping from identifiers to indices in `self.instances`. - names: HashMap, - - /// The instances, available by index. - instances: PrimaryMap, + names: HashMap, } impl Namespace { @@ -33,62 +21,25 @@ impl Namespace { pub fn new() -> Self { Self { names: HashMap::new(), - instances: PrimaryMap::new(), } } /// Install a new `Instance` in this `Namespace`, optionally with the /// given name, and return its index. - pub fn instance(&mut self, instance_name: Option, instance: Instance) -> InstanceIndex { - let index = self.instances.push(instance); - if let Some(instance_name) = instance_name { - self.names.insert(instance_name, index); - } - index + pub fn name_instance(&mut self, name: String, instance: Instance) { + self.names.insert(name, instance); } /// Get the instance index registered with the given `instance_name`. - pub fn get_instance_index(&mut self, instance_name: &str) -> Option { - self.names.get_mut(instance_name).cloned() - } - - /// Register an additional name for an existing registered instance. - pub fn alias_for_indexed(&mut self, existing_index: InstanceIndex, new_name: String) { - self.names.insert(new_name, existing_index); - } - - /// Invoke an exported function from an instance. - pub fn invoke( - &mut self, - compiler: &mut Compiler, - index: InstanceIndex, - field_name: &str, - args: &[RuntimeValue], - ) -> Result { - invoke(compiler, &mut self.instances[index], field_name, args) - } - - /// Get a slice of memory from an instance. - pub fn inspect_memory( - &self, - index: InstanceIndex, - field_name: &str, - start: usize, - len: usize, - ) -> Result<&[u8], ActionError> { - inspect_memory(&self.instances[index], field_name, start, len) - } - - /// Get the value of an exported global from an instance. - pub fn get(&self, index: InstanceIndex, field_name: &str) -> Result { - get(&self.instances[index], field_name) + pub fn get_instance(&mut self, name: &str) -> Option<&mut Instance> { + self.names.get_mut(name) } } impl Resolver for Namespace { - fn resolve(&mut self, instance: &str, field: &str) -> Option { - if let Some(index) = self.names.get(instance) { - self.instances[*index].lookup(field) + fn resolve(&mut self, name: &str, field: &str) -> Option { + if let Some(instance) = self.names.get_mut(name) { + instance.lookup(field) } else { None } diff --git a/lib/runtime/src/export.rs b/lib/runtime/src/export.rs index 9a34fc7de2..f705fdaba6 100644 --- a/lib/runtime/src/export.rs +++ b/lib/runtime/src/export.rs @@ -42,6 +42,8 @@ pub enum Export { Global { /// The address of the global storage. definition: *mut VMGlobalDefinition, + /// Pointer to the containing VMContext. + vmctx: *mut VMContext, /// The global declaration, used for compatibilty checking. global: Global, }, @@ -88,7 +90,15 @@ impl Export { } /// Construct a global export value. - pub fn global(definition: *mut VMGlobalDefinition, global: Global) -> Self { - Export::Global { definition, global } + pub fn global( + definition: *mut VMGlobalDefinition, + vmctx: *mut VMContext, + global: Global, + ) -> Self { + Export::Global { + definition, + vmctx, + global, + } } } diff --git a/lib/runtime/src/imports.rs b/lib/runtime/src/imports.rs index 724198b91e..c2ea6e3ee3 100644 --- a/lib/runtime/src/imports.rs +++ b/lib/runtime/src/imports.rs @@ -1,10 +1,15 @@ +use crate::instance::Instance; use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport}; use cranelift_entity::{BoxedSlice, PrimaryMap}; use cranelift_wasm::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex}; +use std::collections::HashSet; /// Resolved import pointers. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Imports { + /// The set of instances that the imports depend on. + pub dependencies: HashSet, + /// Resolved addresses for imported functions. pub functions: BoxedSlice, @@ -21,12 +26,14 @@ pub struct Imports { impl Imports { /// Construct a new `Imports` instance. pub fn new( + dependencies: HashSet, function_imports: PrimaryMap, table_imports: PrimaryMap, memory_imports: PrimaryMap, global_imports: PrimaryMap, ) -> Self { Self { + dependencies, functions: function_imports.into_boxed_slice(), tables: table_imports.into_boxed_slice(), memories: memory_imports.into_boxed_slice(), @@ -37,6 +44,7 @@ impl Imports { /// Construct a new `Imports` instance with no imports. pub fn none() -> Self { Self { + dependencies: HashSet::new(), functions: PrimaryMap::new().into_boxed_slice(), tables: PrimaryMap::new().into_boxed_slice(), memories: PrimaryMap::new().into_boxed_slice(), diff --git a/lib/runtime/src/instance.rs b/lib/runtime/src/instance.rs index 4a8023ea6c..5c827e466d 100644 --- a/lib/runtime/src/instance.rs +++ b/lib/runtime/src/instance.rs @@ -27,7 +27,7 @@ use cranelift_wasm::{ use indexmap; use std::borrow::ToOwned; use std::boxed::Box; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::rc::Rc; use std::string::{String, ToString}; use wasmtime_environ::{DataInitializer, Module, TableElements, VMOffsets}; @@ -184,6 +184,17 @@ fn global_mut<'vmctx>( /// FIXME: Should this be pub(crate)? #[repr(C)] pub struct InstanceContents { + /// The number of references to this `InstanceContents`. + refcount: usize, + + /// Instances from which this `InstanceContents` imports. These won't + /// create reference cycles because wasm instances can't cyclically + /// import from each other. + dependencies: HashSet, + + /// The allocated contents. + mmap: Mmap, + /// The `Module` this `Instance` was instantiated from. module: Rc, @@ -600,42 +611,13 @@ impl InstanceContents { } } -/// A wrapper around an `Mmap` holding an `InstanceContents`. -struct MmapField { - /// The allocated contents. - mmap: Mmap, -} - -#[allow(clippy::cast_ptr_alignment)] -impl MmapField { - /// Return the contained contents. - fn contents(&self) -> &InstanceContents { - assert!(self.mmap.len() >= mem::size_of::()); - unsafe { &*(self.mmap.as_ptr() as *const InstanceContents) } - } - - /// Return the contained contents. - fn contents_mut(&mut self) -> &mut InstanceContents { - assert!(self.mmap.len() >= mem::size_of::()); - unsafe { &mut *(self.mmap.as_mut_ptr() as *mut InstanceContents) } - } -} - -impl Drop for MmapField { - fn drop(&mut self) { - /// Drop the `InstanceContents`. - assert!(self.mmap.len() >= mem::size_of::()); - mem::drop(mem::replace(self.contents_mut(), unsafe { mem::zeroed() })); - } -} - /// An Instance of a WebAssembly module. /// /// Note that compiled wasm code passes around raw pointers to `Instance`, so /// this shouldn't be moved. +#[derive(Hash, PartialEq, Eq)] pub struct Instance { - /// The `Mmap` containing the contents of the instance. - mmap_field: MmapField, + instance: *mut InstanceContents, } impl Instance { @@ -679,6 +661,9 @@ impl Instance { #[allow(clippy::cast_ptr_alignment)] let contents_ptr = contents_mmap.as_mut_ptr() as *mut InstanceContents; let contents = InstanceContents { + refcount: 1, + dependencies: imports.dependencies, + mmap: contents_mmap, module, global_exports, offsets, @@ -776,48 +761,52 @@ impl Instance { // invoked automatically at instantiation time. contents.invoke_start_function()?; - Ok(Self { - mmap_field: MmapField { - mmap: contents_mmap, - }, - }) + Ok(Self { instance: contents }) + } + + /// Create a new `InstanceHandle` pointing at the instance + /// pointed to by the given `VMContext` pointer. + pub fn from_vmctx(vmctx: *mut VMContext) -> Self { + let instance = unsafe { (&mut *vmctx).instance_contents() }; + instance.refcount += 1; + Self { instance } } /// Return a reference to the vmctx used by compiled wasm code. pub fn vmctx(&self) -> &VMContext { - self.mmap_field.contents().vmctx() + self.contents().vmctx() } /// Return a raw pointer to the vmctx used by compiled wasm code. pub fn vmctx_ptr(&self) -> *const VMContext { - self.mmap_field.contents().vmctx_ptr() + self.contents().vmctx_ptr() } /// Return a mutable reference to the vmctx used by compiled wasm code. pub fn vmctx_mut(&mut self) -> &mut VMContext { - self.mmap_field.contents_mut().vmctx_mut() + self.contents_mut().vmctx_mut() } /// Return a mutable raw pointer to the vmctx used by compiled wasm code. pub fn vmctx_mut_ptr(&mut self) -> *mut VMContext { - self.mmap_field.contents_mut().vmctx_mut_ptr() + self.contents_mut().vmctx_mut_ptr() } /// Lookup an export with the given name. pub fn lookup(&mut self, field: &str) -> Option { - self.mmap_field.contents_mut().lookup(field) + self.contents_mut().lookup(field) } /// Lookup an export with the given name. This takes an immutable reference, /// and the result is an `Export` that the type system doesn't prevent from /// being used to mutate the instance, so this function is unsafe. pub unsafe fn lookup_immutable(&self, field: &str) -> Option { - self.mmap_field.contents().lookup_immutable(field) + self.contents().lookup_immutable(field) } /// Lookup an export with the given export declaration. pub fn lookup_by_declaration(&mut self, export: &wasmtime_environ::Export) -> Export { - self.mmap_field.contents_mut().lookup_by_declaration(export) + self.contents_mut().lookup_by_declaration(export) } /// Lookup an export with the given export declaration. This takes an immutable @@ -827,9 +816,7 @@ impl Instance { &self, export: &wasmtime_environ::Export, ) -> Export { - self.mmap_field - .contents() - .lookup_immutable_by_declaration(export) + self.contents().lookup_immutable_by_declaration(export) } /// Return an iterator over the exports of this instance. @@ -838,12 +825,45 @@ impl Instance { /// are export names, and the values are export declarations which can be /// resolved `lookup_by_declaration`. pub fn exports(&self) -> indexmap::map::Iter { - self.mmap_field.contents().exports() + self.contents().exports() } /// Return a reference to the custom state attached to this instance. pub fn host_state(&mut self) -> &mut Any { - self.mmap_field.contents_mut().host_state() + self.contents_mut().host_state() + } +} + +impl Instance { + /// Return the contained contents. + pub fn contents(&self) -> &InstanceContents { + unsafe { &*(self.instance as *const InstanceContents) } + } + + /// Return the contained contents. + pub fn contents_mut(&mut self) -> &mut InstanceContents { + unsafe { &mut *(self.instance as *mut InstanceContents) } + } +} + +impl Clone for Instance { + fn clone(&self) -> Self { + unsafe { &mut *(self.instance as *mut InstanceContents) }.refcount += 1; + Instance { + instance: self.instance, + } + } +} + +impl Drop for Instance { + fn drop(&mut self) { + let contents = self.contents_mut(); + contents.refcount -= 1; + if contents.refcount == 0 { + let mmap = mem::replace(&mut contents.mmap, Mmap::new()); + unsafe { ptr::drop_in_place(contents) }; + mem::drop(mmap); + } } } @@ -907,6 +927,7 @@ fn lookup_by_declaration( } else { imported_global(vmctx, offsets, *index).from }, + vmctx, global: module.globals[*index], }, } diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 95787051ef..c7e19a6016 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -46,7 +46,7 @@ pub mod libcalls; pub use crate::export::Export; pub use crate::imports::Imports; -pub use crate::instance::{Instance, InstantiationError, LinkError}; +pub use crate::instance::{Instance, InstanceContents, InstantiationError, LinkError}; pub use crate::mmap::Mmap; pub use crate::sig_registry::SignatureRegistry; pub use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish}; diff --git a/lib/wast/src/wast.rs b/lib/wast/src/wast.rs index 187330f1c8..5e47b5d546 100644 --- a/lib/wast/src/wast.rs +++ b/lib/wast/src/wast.rs @@ -4,7 +4,7 @@ use std::path::Path; use std::{fmt, fs, io, str}; use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value}; use wasmtime_jit::{ - ActionError, ActionOutcome, Compiler, Context, InstanceIndex, InstantiationError, RuntimeValue, + ActionError, ActionOutcome, Compiler, Context, Instance, InstantiationError, RuntimeValue, UnknownInstance, }; @@ -71,7 +71,7 @@ pub struct WastFileError { pub struct WastContext { /// Wast files have a concept of a "current" module, which is the most /// recently defined. - current: Option, + current: Option, context: Context, } @@ -85,28 +85,24 @@ impl WastContext { } } - fn get_instance_index( - &mut self, - instance_name: Option<&str>, - ) -> Result { - let index = if let Some(instance_name) = instance_name { + fn get_instance(&mut self, instance_name: Option<&str>) -> Result<&mut Instance, WastError> { + let instance = if let Some(instance_name) = instance_name { self.context - .get_instance_index(instance_name) + .get_instance(instance_name) .map_err(WastError::Instance) } else { self.current .as_mut() - .cloned() .ok_or_else(|| WastError::NoDefaultInstance) }?; - Ok(index) + Ok(instance) } /// Register "spectest" which is used by the spec testsuite. pub fn register_spectest(&mut self) -> Result<(), InstantiationError> { let instance = instantiate_spectest()?; - self.context.instance(Some("spectest".to_owned()), instance); + self.context.name_instance("spectest".to_owned(), instance); Ok(()) } @@ -140,8 +136,8 @@ impl WastContext { /// Register an instance to make it available for performing actions. fn register(&mut self, name: Option, as_name: String) -> Result<(), WastError> { - let index = self.get_instance_index(name.as_ref().map(|x| &**x))?; - self.context.alias_for_indexed(index, as_name); + let instance = self.get_instance(name.as_ref().map(|x| &**x))?.clone(); + self.context.name_instance(as_name, instance); Ok(()) } @@ -156,9 +152,11 @@ impl WastContext { .iter() .map(|arg| runtime_value(*arg)) .collect::>(); - let index = self.get_instance_index(instance_name.as_ref().map(|x| &**x))?; + let mut instance = self + .get_instance(instance_name.as_ref().map(|x| &**x))? + .clone(); self.context - .invoke_indexed(index, field, &value_args) + .invoke(&mut instance, field, &value_args) .map_err(WastError::Action) } @@ -168,9 +166,11 @@ impl WastContext { instance_name: Option, field: &str, ) -> Result { - let index = self.get_instance_index(instance_name.as_ref().map(|x| &**x))?; + let instance = self + .get_instance(instance_name.as_ref().map(|x| &**x))? + .clone(); self.context - .get_indexed(index, field) + .get(&instance, field) .map_err(WastError::Action) } diff --git a/src/wasmtime.rs b/src/wasmtime.rs index 2698db84ca..b687e91c5a 100644 --- a/src/wasmtime.rs +++ b/src/wasmtime.rs @@ -132,8 +132,8 @@ fn main() { let mut context = Context::with_isa(isa); // Make spectest available by default. - context.instance( - Some("spectest".to_owned()), + context.name_instance( + "spectest".to_owned(), instantiate_spectest().expect("instantiating spectest"), ); @@ -155,14 +155,14 @@ fn handle_module(context: &mut Context, args: &Args, path: &Path) -> Result<(), let data = read_wasm(path.to_path_buf())?; // Create a new `Instance` by compiling and instantiating a wasm module. - let index = context + let mut instance = context .instantiate_module(None, &data) .map_err(|e| e.to_string())?; // If a function to invoke was given, invoke it. if let Some(ref f) = args.flag_invoke { match context - .invoke_indexed(index, f, &[]) + .invoke(&mut instance, f, &[]) .map_err(|e| e.to_string())? { ActionOutcome::Returned { .. } => {}