Files
wasmtime/crates/api/src/instance.rs
Alex Crichton e134505b90 Refactor the types.rs types and structures (#681)
* Refactor the `types.rs` types and structures

A few changes applied along the way:

* Documentation added to most methods and types.
* Limits are now stored with the maximum as optional rather than a
  sentinel u32 value for `None`.
* The `Name` type was removed in favor of just using a bare `String`.
* The `Extern` prefix in the varaints of `ExternType` has been removed
  since it was redundant.
* Accessors of `ExternType` variants no longer panic, and unwrapping
  versions were added with "unwrap" in the name.
* Fields and methods named `r#type` were renamed to `ty` to avoid
  requiring a raw identifier to use them.

* Remove `fail-fast: false`

This was left around since the development of GitHub Actions for
wasmtime, but they're no longer needed!

* Fix compilation of the test-programs code

* Fix compilation of wasmtime-py package

* Run rustfmt
2019-12-06 16:19:55 -06:00

174 lines
5.1 KiB
Rust

use crate::context::Context;
use crate::externals::Extern;
use crate::module::Module;
use crate::r#ref::HostRef;
use crate::runtime::Store;
use crate::trampoline::take_api_trap;
use crate::types::{ExportType, ExternType};
use anyhow::Result;
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use wasmtime_jit::{instantiate, Resolver};
use wasmtime_runtime::{Export, InstanceHandle};
struct SimpleResolver {
imports: Vec<(String, String, Extern)>,
}
impl Resolver for SimpleResolver {
fn resolve(&mut self, name: &str, field: &str) -> Option<Export> {
// TODO speedup lookup
self.imports
.iter_mut()
.find(|(n, f, _)| name == n && field == f)
.map(|(_, _, e)| e.get_wasmtime_export())
}
}
pub fn instantiate_in_context(
data: &[u8],
imports: Vec<(String, String, Extern)>,
mut context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>)> {
let mut contexts = HashSet::new();
let debug_info = context.debug_info();
let mut resolver = SimpleResolver { imports };
let instance = instantiate(
&mut context.compiler(),
data,
&mut resolver,
exports,
debug_info,
)
.map_err(|e| {
// TODO wrap HostRef<Trap> into Error
drop(take_api_trap());
e
})?;
contexts.insert(context);
Ok((instance, contexts))
}
#[derive(Clone)]
pub struct Instance {
instance_handle: InstanceHandle,
module: HostRef<Module>,
// We need to keep CodeMemory alive.
contexts: HashSet<Context>,
exports: Box<[Extern]>,
}
impl Instance {
pub fn new(
store: &HostRef<Store>,
module: &HostRef<Module>,
externs: &[Extern],
) -> Result<Instance> {
let context = store.borrow_mut().context().clone();
let exports = store.borrow_mut().global_exports().clone();
let imports = module
.borrow()
.imports()
.iter()
.zip(externs.iter())
.map(|(i, e)| (i.module().to_string(), i.name().to_string(), e.clone()))
.collect::<Vec<_>>();
let (mut instance_handle, contexts) = instantiate_in_context(
module.borrow().binary().expect("binary"),
imports,
context,
exports,
)?;
let exports = {
let module = module.borrow();
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,
));
}
exports.into_boxed_slice()
};
Ok(Instance {
instance_handle,
module: module.clone(),
contexts,
exports,
})
}
pub fn exports(&self) -> &[Extern] {
&self.exports
}
pub fn module(&self) -> &HostRef<Module> {
&self.module
}
pub fn find_export_by_name(&self, name: &str) -> Option<&Extern> {
let (i, _) = self
.module
.borrow()
.exports()
.iter()
.enumerate()
.find(|(_, e)| e.name() == name)?;
Some(&self.exports()[i])
}
pub fn from_handle(store: &HostRef<Store>, instance_handle: InstanceHandle) -> Instance {
let contexts = HashSet::new();
let mut exports = Vec::new();
let mut exports_types = Vec::new();
let mut mutable = instance_handle.clone();
for (name, _) in instance_handle.clone().exports() {
let export = mutable.lookup(name).expect("export");
if let wasmtime_runtime::Export::Function { signature, .. } = &export {
// HACK ensure all handles, instantiated outside Store, present in
// the store's SignatureRegistry, e.g. WASI instances that are
// imported into this store using the from_handle() method.
let _ = store.borrow_mut().register_wasmtime_signature(signature);
}
let extern_type = ExternType::from_wasmtime_export(&export);
exports_types.push(ExportType::new(name, extern_type));
exports.push(Extern::from_wasmtime_export(
store,
instance_handle.clone(),
export.clone(),
));
}
let module = HostRef::new(Module::from_exports(
store,
exports_types.into_boxed_slice(),
));
Instance {
instance_handle,
module,
contexts,
exports: exports.into_boxed_slice(),
}
}
pub fn handle(&self) -> &InstanceHandle {
&self.instance_handle
}
pub fn get_wasmtime_memory(&self) -> Option<wasmtime_runtime::Export> {
let mut instance_handle = self.instance_handle.clone();
instance_handle.lookup("memory")
}
}