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:
@@ -166,7 +166,7 @@ impl Linker {
|
||||
if !item.comes_from_same_store(&self.store) {
|
||||
bail!("all linker items must be from the same store");
|
||||
}
|
||||
self.insert(module, name, &item.ty(), item)?;
|
||||
self.insert(module, name, item)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
@@ -264,8 +264,8 @@ impl Linker {
|
||||
if !Store::same(&self.store, instance.store()) {
|
||||
bail!("all linker items must be from the same store");
|
||||
}
|
||||
for (export, item) in instance.module().exports().iter().zip(instance.exports()) {
|
||||
self.insert(module_name, export.name(), export.ty(), item.clone())?;
|
||||
for export in instance.exports() {
|
||||
self.insert(module_name, export.name(), export.into_extern())?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
@@ -283,7 +283,7 @@ impl Linker {
|
||||
let items = self
|
||||
.iter()
|
||||
.filter(|(m, _, _)| *m == module)
|
||||
.map(|(_, name, item)| (name.to_string(), item.clone()))
|
||||
.map(|(_, name, item)| (name.to_string(), item))
|
||||
.collect::<Vec<_>>();
|
||||
for (name, item) in items {
|
||||
self.define(as_module, &name, item)?;
|
||||
@@ -291,8 +291,8 @@ impl Linker {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert(&mut self, module: &str, name: &str, ty: &ExternType, item: Extern) -> Result<()> {
|
||||
let key = self.import_key(module, name, ty);
|
||||
fn insert(&mut self, module: &str, name: &str, item: Extern) -> Result<()> {
|
||||
let key = self.import_key(module, name, item.ty());
|
||||
match self.map.entry(key) {
|
||||
Entry::Occupied(o) if !self.allow_shadowing => bail!(
|
||||
"import of `{}::{}` with kind {:?} defined twice",
|
||||
@@ -310,7 +310,7 @@ impl Linker {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn import_key(&mut self, module: &str, name: &str, ty: &ExternType) -> ImportKey {
|
||||
fn import_key(&mut self, module: &str, name: &str, ty: ExternType) -> ImportKey {
|
||||
ImportKey {
|
||||
module: self.intern_str(module),
|
||||
name: self.intern_str(name),
|
||||
@@ -318,10 +318,10 @@ impl Linker {
|
||||
}
|
||||
}
|
||||
|
||||
fn import_kind(&self, ty: &ExternType) -> ImportKind {
|
||||
fn import_kind(&self, ty: ExternType) -> ImportKind {
|
||||
match ty {
|
||||
ExternType::Func(f) => ImportKind::Func(f.clone()),
|
||||
ExternType::Global(f) => ImportKind::Global(f.clone()),
|
||||
ExternType::Func(f) => ImportKind::Func(f),
|
||||
ExternType::Global(f) => ImportKind::Global(f),
|
||||
ExternType::Memory(_) => ImportKind::Memory,
|
||||
ExternType::Table(_) => ImportKind::Table,
|
||||
}
|
||||
@@ -378,8 +378,8 @@ impl Linker {
|
||||
pub fn instantiate(&self, module: &Module) -> Result<Instance> {
|
||||
let mut imports = Vec::new();
|
||||
for import in module.imports() {
|
||||
if let Some(item) = self.get(import) {
|
||||
imports.push(item.clone());
|
||||
if let Some(item) = self.get(&import) {
|
||||
imports.push(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -429,23 +429,27 @@ impl Linker {
|
||||
///
|
||||
/// Note that multiple `Extern` items may be defined for the same
|
||||
/// module/name pair.
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &str, &Extern)> {
|
||||
self.map
|
||||
.iter()
|
||||
.map(move |(key, item)| (&*self.strings[key.module], &*self.strings[key.name], item))
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &str, Extern)> {
|
||||
self.map.iter().map(move |(key, item)| {
|
||||
(
|
||||
&*self.strings[key.module],
|
||||
&*self.strings[key.name],
|
||||
item.clone(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Looks up a value in this `Linker` which matches the `import` type
|
||||
/// provided.
|
||||
///
|
||||
/// Returns `None` if no match was found.
|
||||
pub fn get(&self, import: &ImportType) -> Option<&Extern> {
|
||||
pub fn get(&self, import: &ImportType) -> Option<Extern> {
|
||||
let key = ImportKey {
|
||||
module: *self.string2idx.get(import.module())?,
|
||||
name: *self.string2idx.get(import.name())?,
|
||||
kind: self.import_kind(import.ty()),
|
||||
};
|
||||
self.map.get(&key)
|
||||
self.map.get(&key).cloned()
|
||||
}
|
||||
|
||||
/// Returns all items defined for the `module` and `name` pair.
|
||||
@@ -468,10 +472,10 @@ impl Linker {
|
||||
/// Returns the single item defined for the `module` and `name` pair.
|
||||
///
|
||||
/// Unlike the similar [`Linker::get_by_name`] method this function returns
|
||||
/// a single `&Extern` item. If the `module` and `name` pair isn't defined
|
||||
/// a single `Extern` item. If the `module` and `name` pair isn't defined
|
||||
/// in this linker then an error is returned. If more than one value exists
|
||||
/// for the `module` and `name` pairs, then an error is returned as well.
|
||||
pub fn get_one_by_name(&self, module: &str, name: &str) -> Result<&Extern> {
|
||||
pub fn get_one_by_name(&self, module: &str, name: &str) -> Result<Extern> {
|
||||
let mut items = self.get_by_name(module, name);
|
||||
let ret = items
|
||||
.next()
|
||||
@@ -479,6 +483,6 @@ impl Linker {
|
||||
if items.next().is_some() {
|
||||
bail!("too many items named `{}` in `{}`", name, module);
|
||||
}
|
||||
Ok(ret)
|
||||
Ok(ret.clone())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user