Refactor (#1524)
* Compute instance exports on demand. Instead having instances eagerly compute a Vec of Externs, and bumping the refcount for each Extern, compute Externs on demand. This also enables `Instance::get_export` to avoid doing a linear search. This also means that the closure returned by `get0` and friends now holds an `InstanceHandle` to dynamically hold the instance live rather than being scoped to a lifetime. * Compute module imports and exports on demand too. And compute Extern::ty on demand too. * Add a utility function for computing an ExternType. * Add a utility function for looking up a function's signature. * Add a utility function for computing the ValType of a Global. * Rename wasmtime_environ::Export to EntityIndex. This helps differentiate it from other Export types in the tree, and describes what it is. * Fix a typo in a comment. * Simplify module imports and exports. * Make `Instance::exports` return the export names. This significantly simplifies the public API, as it's relatively common to need the names, and this avoids the need to do a zip with `Module::exports`. This also changes `ImportType` and `ExportType` to have public members instead of private members and accessors, as I find that simplifies the usage particularly in cases where there are temporary instances. * Remove `Instance::module`. This doesn't quite remove `Instance`'s `module` member, it gets a step closer. * Use a InstanceHandle utility function. * Don't consume self in the `Func::get*` methods. Instead, just create a closure containing the instance handle and the export for them to call. * Use `ExactSizeIterator` to avoid needing separate `num_*` methods. * Rename `Extern::func()` etc. to `into_func()` etc. * Revise examples to avoid using `nth`. * Add convenience methods to instance for getting specific extern types. * Use the convenience functions in more tests and examples. * Avoid cloning strings for `ImportType` and `ExportType`. * Remove more obviated clone() calls. * Simplify `Func`'s closure state. * Make wasmtime::Export's fields private. This makes them more consistent with ExportType. * Fix compilation error. * Make a lifetime parameter explicit, and use better lifetime names. Instead of 'me, use 'instance and 'module to make it clear what the lifetime is. * More lifetime cleanups.
This commit is contained in:
@@ -1,18 +1,19 @@
|
||||
use crate::externals::Extern;
|
||||
use crate::externals::{Export, Extern, Global, Memory, Table};
|
||||
use crate::func::Func;
|
||||
use crate::module::Module;
|
||||
use crate::runtime::{Config, Store};
|
||||
use crate::trap::Trap;
|
||||
use anyhow::{bail, Error, Result};
|
||||
use std::any::Any;
|
||||
use wasmtime_jit::{CompiledModule, Resolver};
|
||||
use wasmtime_runtime::{Export, InstanceHandle, InstantiationError, SignatureRegistry};
|
||||
use wasmtime_runtime::{InstanceHandle, InstantiationError, SignatureRegistry};
|
||||
|
||||
struct SimpleResolver<'a> {
|
||||
imports: &'a [Extern],
|
||||
}
|
||||
|
||||
impl Resolver for SimpleResolver<'_> {
|
||||
fn resolve(&mut self, idx: u32, _name: &str, _field: &str) -> Option<Export> {
|
||||
fn resolve(&mut self, idx: u32, _name: &str, _field: &str) -> Option<wasmtime_runtime::Export> {
|
||||
self.imports
|
||||
.get(idx as usize)
|
||||
.map(|i| i.get_wasmtime_export())
|
||||
@@ -68,7 +69,6 @@ fn instantiate(
|
||||
pub struct Instance {
|
||||
pub(crate) instance_handle: InstanceHandle,
|
||||
module: Module,
|
||||
exports: Box<[Extern]>,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
@@ -145,20 +145,9 @@ impl Instance {
|
||||
Box::new(info),
|
||||
)?;
|
||||
|
||||
let mut exports = Vec::with_capacity(module.exports().len());
|
||||
for export in module.exports() {
|
||||
let name = export.name().to_string();
|
||||
let export = instance_handle.lookup(&name).expect("export");
|
||||
exports.push(Extern::from_wasmtime_export(
|
||||
store,
|
||||
instance_handle.clone(),
|
||||
export,
|
||||
));
|
||||
}
|
||||
Ok(Instance {
|
||||
instance_handle,
|
||||
module: module.clone(),
|
||||
exports: exports.into_boxed_slice(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -170,24 +159,19 @@ impl Instance {
|
||||
self.module.store()
|
||||
}
|
||||
|
||||
/// Returns the associated [`Module`] that this `Instance` instantiated.
|
||||
///
|
||||
/// The corresponding [`Module`] here is a static version of this `Instance`
|
||||
/// which can be used to learn information such as naming information about
|
||||
/// various functions.
|
||||
pub fn module(&self) -> &Module {
|
||||
&self.module
|
||||
}
|
||||
|
||||
/// Returns the list of exported items from this [`Instance`].
|
||||
///
|
||||
/// Note that the exports here do not have names associated with them,
|
||||
/// they're simply the values that are exported. To learn the value of each
|
||||
/// export you'll need to consult [`Module::exports`]. The list returned
|
||||
/// here maps 1:1 with the list that [`Module::exports`] returns, and
|
||||
/// [`ExportType`](crate::ExportType) contains the name of each export.
|
||||
pub fn exports(&self) -> &[Extern] {
|
||||
&self.exports
|
||||
pub fn exports<'instance>(
|
||||
&'instance self,
|
||||
) -> impl ExactSizeIterator<Item = Export<'instance>> + 'instance {
|
||||
let instance_handle = &self.instance_handle;
|
||||
let store = self.module.store();
|
||||
self.instance_handle
|
||||
.exports()
|
||||
.map(move |(name, entity_index)| {
|
||||
let export = instance_handle.lookup_by_declaration(entity_index);
|
||||
let extern_ = Extern::from_wasmtime_export(export, store, instance_handle.clone());
|
||||
Export::new(name, extern_)
|
||||
})
|
||||
}
|
||||
|
||||
/// Looks up an exported [`Extern`] value by name.
|
||||
@@ -196,14 +180,45 @@ impl Instance {
|
||||
/// the value, if found.
|
||||
///
|
||||
/// Returns `None` if there was no export named `name`.
|
||||
pub fn get_export(&self, name: &str) -> Option<&Extern> {
|
||||
let (i, _) = self
|
||||
.module
|
||||
.exports()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, e)| e.name() == name)?;
|
||||
Some(&self.exports()[i])
|
||||
pub fn get_export(&self, name: &str) -> Option<Extern> {
|
||||
let export = self.instance_handle.lookup(&name)?;
|
||||
Some(Extern::from_wasmtime_export(
|
||||
export,
|
||||
self.module.store(),
|
||||
self.instance_handle.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Looks up an exported [`Func`] value by name.
|
||||
///
|
||||
/// Returns `None` if there was no export named `name`, or if there was but
|
||||
/// it wasn't a function.
|
||||
pub fn get_func(&self, name: &str) -> Option<Func> {
|
||||
self.get_export(name)?.into_func()
|
||||
}
|
||||
|
||||
/// Looks up an exported [`Table`] value by name.
|
||||
///
|
||||
/// Returns `None` if there was no export named `name`, or if there was but
|
||||
/// it wasn't a table.
|
||||
pub fn get_table(&self, name: &str) -> Option<Table> {
|
||||
self.get_export(name)?.into_table()
|
||||
}
|
||||
|
||||
/// Looks up an exported [`Memory`] value by name.
|
||||
///
|
||||
/// Returns `None` if there was no export named `name`, or if there was but
|
||||
/// it wasn't a memory.
|
||||
pub fn get_memory(&self, name: &str) -> Option<Memory> {
|
||||
self.get_export(name)?.into_memory()
|
||||
}
|
||||
|
||||
/// Looks up an exported [`Global`] value by name.
|
||||
///
|
||||
/// Returns `None` if there was no export named `name`, or if there was but
|
||||
/// it wasn't a global.
|
||||
pub fn get_global(&self, name: &str) -> Option<Global> {
|
||||
self.get_export(name)?.into_global()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
||||
Reference in New Issue
Block a user