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:
@@ -31,7 +31,7 @@ use wasmtime_environ::wasm::{
|
||||
DataIndex, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
|
||||
ElemIndex, FuncIndex, GlobalIndex, GlobalInit, MemoryIndex, SignatureIndex, TableIndex,
|
||||
};
|
||||
use wasmtime_environ::{ir, DataInitializer, Module, TableElements, VMOffsets};
|
||||
use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, VMOffsets};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
@@ -296,9 +296,9 @@ impl Instance {
|
||||
}
|
||||
|
||||
/// Lookup an export with the given export declaration.
|
||||
pub fn lookup_by_declaration(&self, export: &wasmtime_environ::Export) -> Export {
|
||||
pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export {
|
||||
match export {
|
||||
wasmtime_environ::Export::Function(index) => {
|
||||
EntityIndex::Function(index) => {
|
||||
let signature = self.signature_id(self.module.local.functions[*index]);
|
||||
let (address, vmctx) =
|
||||
if let Some(def_index) = self.module.local.defined_func_index(*index) {
|
||||
@@ -317,7 +317,7 @@ impl Instance {
|
||||
}
|
||||
.into()
|
||||
}
|
||||
wasmtime_environ::Export::Table(index) => {
|
||||
EntityIndex::Table(index) => {
|
||||
let (definition, vmctx) =
|
||||
if let Some(def_index) = self.module.local.defined_table_index(*index) {
|
||||
(self.table_ptr(def_index), self.vmctx_ptr())
|
||||
@@ -332,7 +332,7 @@ impl Instance {
|
||||
}
|
||||
.into()
|
||||
}
|
||||
wasmtime_environ::Export::Memory(index) => {
|
||||
EntityIndex::Memory(index) => {
|
||||
let (definition, vmctx) =
|
||||
if let Some(def_index) = self.module.local.defined_memory_index(*index) {
|
||||
(self.memory_ptr(def_index), self.vmctx_ptr())
|
||||
@@ -347,7 +347,7 @@ impl Instance {
|
||||
}
|
||||
.into()
|
||||
}
|
||||
wasmtime_environ::Export::Global(index) => ExportGlobal {
|
||||
EntityIndex::Global(index) => ExportGlobal {
|
||||
definition: if let Some(def_index) = self.module.local.defined_global_index(*index)
|
||||
{
|
||||
self.global_ptr(def_index)
|
||||
@@ -363,10 +363,10 @@ impl Instance {
|
||||
|
||||
/// Return an iterator over the exports of this instance.
|
||||
///
|
||||
/// Specifically, it provides access to the key-value pairs, where they keys
|
||||
/// Specifically, it provides access to the key-value pairs, where the keys
|
||||
/// are export names, and the values are export declarations which can be
|
||||
/// resolved `lookup_by_declaration`.
|
||||
pub fn exports(&self) -> indexmap::map::Iter<String, wasmtime_environ::Export> {
|
||||
pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
|
||||
self.module.exports.iter()
|
||||
}
|
||||
|
||||
@@ -383,22 +383,35 @@ impl Instance {
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let (callee_address, callee_vmctx) = match self.module.local.defined_func_index(start_index)
|
||||
{
|
||||
Some(defined_index) => {
|
||||
let body = *self
|
||||
.finished_functions
|
||||
.get(defined_index)
|
||||
.expect("function index is out of bounds");
|
||||
(body as *const _, self.vmctx_ptr())
|
||||
}
|
||||
None => {
|
||||
assert_lt!(start_index.index(), self.module.imported_funcs.len());
|
||||
let import = self.imported_function(start_index);
|
||||
(import.body, import.vmctx)
|
||||
}
|
||||
};
|
||||
self.invoke_function_index(start_index)
|
||||
.map_err(InstantiationError::StartTrap)
|
||||
}
|
||||
|
||||
fn invoke_function_index(&self, callee_index: FuncIndex) -> Result<(), Trap> {
|
||||
let (callee_address, callee_vmctx) =
|
||||
match self.module.local.defined_func_index(callee_index) {
|
||||
Some(defined_index) => {
|
||||
let body = *self
|
||||
.finished_functions
|
||||
.get(defined_index)
|
||||
.expect("function index is out of bounds");
|
||||
(body as *const _, self.vmctx_ptr())
|
||||
}
|
||||
None => {
|
||||
assert_lt!(callee_index.index(), self.module.local.num_imported_funcs);
|
||||
let import = self.imported_function(callee_index);
|
||||
(import.body, import.vmctx)
|
||||
}
|
||||
};
|
||||
|
||||
self.invoke_function(callee_vmctx, callee_address)
|
||||
}
|
||||
|
||||
fn invoke_function(
|
||||
&self,
|
||||
callee_vmctx: *mut VMContext,
|
||||
callee_address: *const VMFunctionBody,
|
||||
) -> Result<(), Trap> {
|
||||
// Make the call.
|
||||
unsafe {
|
||||
catch_traps(callee_vmctx, || {
|
||||
@@ -407,7 +420,6 @@ impl Instance {
|
||||
unsafe extern "C" fn(*mut VMContext, *mut VMContext),
|
||||
>(callee_address)(callee_vmctx, self.vmctx_ptr())
|
||||
})
|
||||
.map_err(InstantiationError::StartTrap)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,7 +1031,7 @@ impl InstanceHandle {
|
||||
}
|
||||
|
||||
/// Lookup an export with the given export declaration.
|
||||
pub fn lookup_by_declaration(&self, export: &wasmtime_environ::Export) -> Export {
|
||||
pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export {
|
||||
self.instance().lookup_by_declaration(export)
|
||||
}
|
||||
|
||||
@@ -1028,7 +1040,7 @@ impl InstanceHandle {
|
||||
/// Specifically, it provides access to the key-value pairs, where the keys
|
||||
/// are export names, and the values are export declarations which can be
|
||||
/// resolved `lookup_by_declaration`.
|
||||
pub fn exports(&self) -> indexmap::map::Iter<String, wasmtime_environ::Export> {
|
||||
pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
|
||||
self.instance().exports()
|
||||
}
|
||||
|
||||
@@ -1204,7 +1216,7 @@ fn check_memory_init_bounds(
|
||||
|
||||
/// Allocate memory for just the tables of the current module.
|
||||
fn create_tables(module: &Module) -> BoxedSlice<DefinedTableIndex, Table> {
|
||||
let num_imports = module.imported_tables.len();
|
||||
let num_imports = module.local.num_imported_tables;
|
||||
let mut tables: PrimaryMap<DefinedTableIndex, _> =
|
||||
PrimaryMap::with_capacity(module.local.table_plans.len() - num_imports);
|
||||
for table in &module.local.table_plans.values().as_slice()[num_imports..] {
|
||||
@@ -1291,7 +1303,7 @@ fn create_memories(
|
||||
module: &Module,
|
||||
mem_creator: &dyn RuntimeMemoryCreator,
|
||||
) -> Result<BoxedSlice<DefinedMemoryIndex, Box<dyn RuntimeLinearMemory>>, InstantiationError> {
|
||||
let num_imports = module.imported_memories.len();
|
||||
let num_imports = module.local.num_imported_memories;
|
||||
let mut memories: PrimaryMap<DefinedMemoryIndex, _> =
|
||||
PrimaryMap::with_capacity(module.local.memory_plans.len() - num_imports);
|
||||
for plan in &module.local.memory_plans.values().as_slice()[num_imports..] {
|
||||
@@ -1336,7 +1348,7 @@ fn initialize_memories(
|
||||
/// Allocate memory for just the globals of the current module,
|
||||
/// with initializers applied.
|
||||
fn create_globals(module: &Module) -> BoxedSlice<DefinedGlobalIndex, VMGlobalDefinition> {
|
||||
let num_imports = module.imported_globals.len();
|
||||
let num_imports = module.local.num_imported_globals;
|
||||
let mut vmctx_globals = PrimaryMap::with_capacity(module.local.globals.len() - num_imports);
|
||||
|
||||
for _ in &module.local.globals.values().as_slice()[num_imports..] {
|
||||
@@ -1348,7 +1360,7 @@ fn create_globals(module: &Module) -> BoxedSlice<DefinedGlobalIndex, VMGlobalDef
|
||||
|
||||
fn initialize_globals(instance: &Instance) {
|
||||
let module = Arc::clone(&instance.module);
|
||||
let num_imports = module.imported_globals.len();
|
||||
let num_imports = module.local.num_imported_globals;
|
||||
for (index, global) in module.local.globals.iter().skip(num_imports) {
|
||||
let def_index = module.local.defined_global_index(index).unwrap();
|
||||
unsafe {
|
||||
@@ -1394,7 +1406,7 @@ pub enum InstantiationError {
|
||||
#[error("Trap occurred during instantiation")]
|
||||
Trap(Trap),
|
||||
|
||||
/// A compilation error occured.
|
||||
/// A trap occurred while running the wasm start function.
|
||||
#[error("Trap occurred while invoking start function")]
|
||||
StartTrap(Trap),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user