diff --git a/lib/runtime/examples/simple/main.rs b/lib/runtime/examples/simple/main.rs index b8f6a6a3d..69be508a0 100644 --- a/lib/runtime/examples/simple/main.rs +++ b/lib/runtime/examples/simple/main.rs @@ -1,3 +1,4 @@ +use hashbrown::HashMap; use std::rc::Rc; use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; @@ -15,9 +16,8 @@ fn main() -> Result<(), String> { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); let inner_module = runtime::compile(&wasm_binary, &CraneliftCompiler::new())?; - let mut imports = Imports::new(); - imports.register_export( - "env", + let mut env_namespace = HashMap::new(); + env_namespace.insert( "print_i32", Export::Function { func: unsafe { FuncRef::new(print_num as _) }, @@ -28,13 +28,15 @@ fn main() -> Result<(), String> { }, }, ); + let mut imports = Imports::new(); + imports.register("env", env_namespace); let imports = Rc::new(imports); let inner_instance = inner_module.instantiate(imports)?; let mut outer_imports = Imports::new(); - outer_imports.register_instance("env", inner_instance); + outer_imports.register("env", inner_instance); let outer_imports = Rc::new(outer_imports); let outer_module = runtime::compile(EXAMPLE_WASM, &CraneliftCompiler::new())?; let mut outer_instance = outer_module.instantiate(outer_imports)?; @@ -57,15 +59,3 @@ static IMPORT_MODULE: &str = r#" get_local $p0 call $print_i32)) "#; - -fn generate_imports() -> Rc { - let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()) - .expect("WASM can't be compiled"); - let instance = module - .instantiate(Rc::new(Imports::new())) - .expect("WASM can't be instantiated"); - let mut imports = Imports::new(); - imports.register_instance("env", instance); - Rc::new(imports) -} diff --git a/lib/runtime/examples/test.rs b/lib/runtime/examples/test.rs index 68d82fb5d..b04a3391f 100644 --- a/lib/runtime/examples/test.rs +++ b/lib/runtime/examples/test.rs @@ -21,7 +21,7 @@ fn generate_imports() -> Rc { // let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled"); // let instance = module.instantiate(Rc::new(Imports::new())).expect("WASM can't be instantiated"); let imports = Imports::new(); - // imports.register_instance("spectest", instance); + // imports.register("spectest", instance); Rc::new(imports) } diff --git a/lib/runtime/src/export.rs b/lib/runtime/src/export.rs index a99327e8c..f9af52eea 100644 --- a/lib/runtime/src/export.rs +++ b/lib/runtime/src/export.rs @@ -4,7 +4,7 @@ use crate::{ vm, }; -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] pub enum Context { External(*mut vm::Ctx), Internal, diff --git a/lib/runtime/src/import.rs b/lib/runtime/src/import.rs index 75c1ef764..90a26e874 100644 --- a/lib/runtime/src/import.rs +++ b/lib/runtime/src/import.rs @@ -1,17 +1,27 @@ -use crate::{export::Export, Instance}; +use crate::export::Export; use hashbrown::{hash_map::Entry, HashMap}; pub trait ImportResolver { fn get(&self, namespace: &str, name: &str) -> Option; } -enum Namespace { - Instance(Box), - UserSupplied(HashMap), +pub trait Namespace { + fn get_export(&self, name: &str) -> Option; +} + +impl Namespace for HashMap { + fn get_export(&self, name: &str) -> Option { + self.get(name).cloned() + } +} +impl<'a> Namespace for HashMap<&'a str, Export> { + fn get_export(&self, name: &str) -> Option { + self.get(name).cloned() + } } pub struct Imports { - map: HashMap, + map: HashMap>, } impl Imports { @@ -21,38 +31,50 @@ impl Imports { } } - pub fn register_instance(&mut self, namespace: impl Into, instance: Box) { - match self.map.entry(namespace.into()) { - Entry::Vacant(empty) => empty.insert(Namespace::Instance(instance)), - Entry::Occupied(_) => { - panic!("cannot register an instance in a namespace that already exists") - } - }; - } - - pub fn register_export( + pub fn register( &mut self, - namespace: impl Into, name: impl Into, - export: Export, - ) { - let namespace_item = self - .map - .entry(namespace.into()) - .or_insert_with(|| Namespace::UserSupplied(HashMap::new())); - - match namespace_item { - Namespace::UserSupplied(ref mut map) => map.insert(name.into(), export), - Namespace::Instance(_) => panic!("cannot register an export in a namespace that has already been used to register an instance"), - }; + namespace: impl Namespace + 'static, + ) -> Option> { + match self.map.entry(name.into()) { + Entry::Vacant(empty) => { + empty.insert(Box::new(namespace)); + None + } + Entry::Occupied(mut occupied) => Some(occupied.insert(Box::new(namespace))), + } } + + // pub fn register_instance(&mut self, namespace: impl Into, instance: Box) { + // match self.map.entry(namespace.into()) { + // Entry::Vacant(empty) => empty.insert(Namespace::Instance(instance)), + // Entry::Occupied(_) => { + // panic!("cannot register an instance in a namespace that already exists") + // } + // }; + // } + + // pub fn register_export( + // &mut self, + // namespace: impl Into, + // name: impl Into, + // export: Export, + // ) { + // let namespace_item = self + // .map + // .entry(namespace.into()) + // .or_insert_with(|| Namespace::UserSupplied(HashMap::new())); + + // match namespace_item { + // Namespace::UserSupplied(ref mut map) => map.insert(name.into(), export), + // Namespace::Instance(_) => panic!("cannot register an export in a namespace that has already been used to register an instance"), + // }; + // } } impl ImportResolver for Imports { - fn get(&self, namespace: &str, name: &str) -> Option { - match self.map.get(namespace)? { - Namespace::UserSupplied(map) => map.get(name).cloned(), - Namespace::Instance(instance) => instance.get_export(name).ok(), - } + fn get(&self, namespace_name: &str, name: &str) -> Option { + let namespace = self.map.get(namespace_name)?; + namespace.get_export(name) } } diff --git a/lib/runtime/src/instance.rs b/lib/runtime/src/instance.rs index c47578fda..74116cb4a 100644 --- a/lib/runtime/src/instance.rs +++ b/lib/runtime/src/instance.rs @@ -2,7 +2,7 @@ use crate::recovery::call_protected; use crate::{ backing::{ImportBacking, LocalBacking}, export::{Context, Export}, - import::ImportResolver, + import::{ImportResolver, Namespace}, module::{ExportIndex, Module}, types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Type, Value}, vm, @@ -130,16 +130,6 @@ impl Instance { }) } - pub fn get_export(&self, name: &str) -> Result { - let export_index = self - .module - .exports - .get(name) - .ok_or_else(|| format!("there is no export with that name: {}", name))?; - - Ok(self.get_export_from_index(export_index)) - } - pub fn exports(&self) -> ExportIter { ExportIter::new(self) } @@ -238,6 +228,14 @@ impl Instance { } } +impl Namespace for Box { + fn get_export(&self, name: &str) -> Option { + let export_index = self.module.exports.get(name)?; + + Some(self.get_export_from_index(export_index)) + } +} + #[derive(Debug, Clone)] pub struct FuncRef(*const vm::Func); diff --git a/lib/runtime/tests/spectests/_common.rs b/lib/runtime/tests/spectests/_common.rs index 138aa0728..9ecb528d9 100644 --- a/lib/runtime/tests/spectests/_common.rs +++ b/lib/runtime/tests/spectests/_common.rs @@ -22,7 +22,7 @@ pub fn generate_imports() -> Rc { .instantiate(Rc::new(Imports::new())) .expect("WASM can't be instantiated"); let mut imports = Imports::new(); - imports.register_instance("spectest", instance); + imports.register("spectest", instance); Rc::new(imports) }