start moving marine-runtime to generic wasm backend

This commit is contained in:
Valery Antopol 2022-02-25 22:28:28 +03:00
parent 614a4cb078
commit 5e7dae9dcd
22 changed files with 281 additions and 80 deletions

24
Cargo.lock generated
View File

@ -1610,6 +1610,7 @@ dependencies = [
"itertools 0.10.3", "itertools 0.10.3",
"marine-it-interfaces 0.5.0", "marine-it-interfaces 0.5.0",
"marine-module-interface 0.2.0", "marine-module-interface 0.2.0",
"marine-wasm-backend-traits",
"nom", "nom",
"semver 0.11.0", "semver 0.11.0",
"serde", "serde",
@ -1658,6 +1659,7 @@ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
"marine-rs-sdk-main", "marine-rs-sdk-main",
"marine-wasm-backend-traits",
"semver 0.11.0", "semver 0.11.0",
"serde", "serde",
"thiserror", "thiserror",
@ -1799,6 +1801,8 @@ dependencies = [
"marine-module-info-parser 0.2.2", "marine-module-info-parser 0.2.2",
"marine-module-interface 0.2.0", "marine-module-interface 0.2.0",
"marine-utils 0.4.0", "marine-utils 0.4.0",
"marine-wasm-backend-traits",
"marine-wasmer-backend",
"multimap", "multimap",
"once_cell", "once_cell",
"parity-wasm 0.42.2", "parity-wasm 0.42.2",
@ -1875,6 +1879,26 @@ checksum = "8dc5838acba84ce4d802d672afd0814fae0ae7098021ae5b06d975e70d09f812"
name = "marine-utils" name = "marine-utils"
version = "0.4.0" version = "0.4.0"
[[package]]
name = "marine-wasm-backend-traits"
version = "0.1.0"
dependencies = [
"thiserror",
"wasmer-interface-types-fl 0.21.1",
"wasmer-runtime-core-fl",
"wasmer-runtime-fl",
]
[[package]]
name = "marine-wasmer-backend"
version = "0.1.0"
dependencies = [
"marine-wasm-backend-traits",
"wasmer-interface-types-fl 0.21.1",
"wasmer-runtime-core-fl",
"wasmer-runtime-fl",
]
[[package]] [[package]]
name = "marine-web-runtime" name = "marine-web-runtime"
version = "0.1.0" version = "0.1.0"

View File

@ -7,6 +7,8 @@ members = [
"crates/min-it-version", "crates/min-it-version",
"crates/module-info-parser", "crates/module-info-parser",
"crates/module-interface", "crates/module-interface",
"crates/wasm-backend-traits",
"crates/wasmer-backend",
"crates/utils", "crates/utils",
"examples/call_parameters", "examples/call_parameters",
"examples/greeting", "examples/greeting",

View File

@ -13,6 +13,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
marine-it-interfaces = { path = "../it-interfaces", version = "0.5.0" } marine-it-interfaces = { path = "../it-interfaces", version = "0.5.0" }
marine-module-interface = { path = "../module-interface", version = "0.2.0" } marine-module-interface = { path = "../module-interface", version = "0.2.0" }
marine-wasm-backend-traits = { path = "../wasm-backend-traits", version = "0.1.0"}
anyhow = "1.0.31" anyhow = "1.0.31"
walrus = "0.18.0" walrus = "0.18.0"

View File

@ -20,7 +20,8 @@ use crate::ParserResult;
use walrus::IdsToIndices; use walrus::IdsToIndices;
use wasmer_it::ast::Interfaces; use wasmer_it::ast::Interfaces;
use wasmer_core::Module as WasmerModule; //use wasmer_core::Module as WasmerModule;
use marine_wasm_backend_traits::Module as ModuleTrait;
use std::borrow::Cow; use std::borrow::Cow;
use std::path::Path; use std::path::Path;
@ -42,7 +43,7 @@ where
} }
/// Extracts IT section of provided Wasm binary and converts it to a MITInterfaces. /// Extracts IT section of provided Wasm binary and converts it to a MITInterfaces.
pub fn extract_it_from_module(wasmer_module: &WasmerModule) -> ParserResult<Interfaces<'_>> { pub fn extract_it_from_module<M: ModuleTrait>(wasmer_module: &M) -> ParserResult<Interfaces<'_>> {
let wit_sections = wasmer_module let wit_sections = wasmer_module
.custom_sections(IT_SECTION_NAME) .custom_sections(IT_SECTION_NAME)
.ok_or(ITParserError::NoITSection)?; .ok_or(ITParserError::NoITSection)?;

View File

@ -14,6 +14,7 @@ path = "src/lib.rs"
marine-rs-sdk-main = "0.6.13" marine-rs-sdk-main = "0.6.13"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1" } wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1" }
marine-wasm-backend-traits = { path = "../wasm-backend-traits", version = "0.1.0"}
anyhow = "1.0.31" anyhow = "1.0.31"
chrono = "0.4.19" chrono = "0.4.19"

View File

@ -20,7 +20,8 @@ use super::SDKVersionError;
use crate::extract_custom_sections_by_name; use crate::extract_custom_sections_by_name;
use crate::try_as_one_section; use crate::try_as_one_section;
use wasmer_core::Module as WasmerModule; //use wasmer_core::Module as WasmerModule;
use marine_wasm_backend_traits::Module as ModuleTrait;
use marine_rs_sdk_main::VERSION_SECTION_NAME; use marine_rs_sdk_main::VERSION_SECTION_NAME;
use walrus::ModuleConfig; use walrus::ModuleConfig;
use walrus::Module; use walrus::Module;
@ -56,8 +57,8 @@ pub fn extract_from_module(wasm_module: &Module) -> ModuleInfoResult<Option<semv
Ok(Some(version)) Ok(Some(version))
} }
pub fn extract_from_wasmer_module( pub fn extract_from_wasmer_module<M: ModuleTrait>(
wasmer_module: &WasmerModule, wasmer_module: &M,
) -> ModuleInfoResult<Option<semver::Version>> { ) -> ModuleInfoResult<Option<semver::Version>> {
let sections = wasmer_module.custom_sections(VERSION_SECTION_NAME); let sections = wasmer_module.custom_sections(VERSION_SECTION_NAME);

View File

@ -0,0 +1,14 @@
[package]
name = "marine-wasm-backend-traits"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
thiserror = "1.0.24"
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" }
wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] }

View File

@ -0,0 +1,35 @@
use thiserror::Error;
pub struct Value {}
#[derive(Debug, Error)]
pub enum WasmBackendError {
#[error("Some error")]
SomeError,
}
pub type WasmBackendResult<T> = Result<T, WasmBackendError>;
pub trait WasmBackend: Clone + 'static {
type M: Module;
fn compile(wasm: &[u8]) -> WasmBackendResult<Self::M>;
}
pub trait Module {
type I: Instance;
fn custom_sections(&self, key: &str) -> Option<&[Vec<u8>]>;
fn instantiate(&self, imports: &wasmer_runtime::ImportObject) -> WasmBackendResult<Self::I>;
}
pub trait Instance {
fn export_iter<'a>(&'a self) -> Box<dyn Iterator<Item = (String, wasmer_runtime::Export)> + 'a>;
fn exports(&self) -> &wasmer_core::instance::Exports;
fn import_object(&self) -> &wasmer_runtime::ImportObject;
// maybe hide them inside impl
fn context(&self) -> &wasmer_core::vm::Ctx;
fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx;
}

View File

@ -0,0 +1,13 @@
[package]
name = "marine-wasmer-backend"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
marine-wasm-backend-traits = {path = "../wasm-backend-traits", version = "0.1.0"}
wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] }
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" }

View File

@ -0,0 +1,75 @@
use marine_wasm_backend_traits::WasmBackend;
use marine_wasm_backend_traits::WasmBackendResult;
use marine_wasm_backend_traits::WasmBackendError;
use marine_wasm_backend_traits::Module;
use marine_wasm_backend_traits::Instance;
#[derive(Clone)]
pub struct WasmerBackend {}
impl WasmBackend for WasmerBackend {
type M = WasmerModule;
fn compile(wasm: &[u8]) -> WasmBackendResult<WasmerModule> {
wasmer_runtime::compile(wasm).map_err(|_| {
WasmBackendError::SomeError
}).map(|module| {
WasmerModule { module }
})
}
}
pub struct WasmerModule {
module: wasmer_core::Module,
}
impl Module for WasmerModule {
type I = WasmerInstance;
fn custom_sections(&self, name: &str) -> Option<&[Vec<u8>]> {
self.module.custom_sections(name)
}
fn instantiate(&self, imports: &wasmer_runtime::ImportObject) -> WasmBackendResult<Self::I> {
self.module
.instantiate(&imports)
.map_err(|_| {
WasmBackendError::SomeError
})
.map(|instance| {WasmerInstance{instance}})
}
}
pub struct WasmerInstance {
instance: wasmer_core::Instance,
}
impl Instance for WasmerInstance {
fn export_iter<'a>(&'a self) -> Box<dyn Iterator<Item = (String, wasmer_runtime::Export)> + 'a> {
let exports = self.instance.exports();
Box::new(exports)
}
fn exports(&self) -> &wasmer_core::instance::Exports {
&self.instance.exports
}
fn import_object(&self) -> &wasmer_runtime::ImportObject {
&self.instance.import_object
}
fn context(&self) -> &wasmer_core::vm::Ctx { self.instance.context() }
fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx { self.instance.context_mut()}
}
/*
pub struct WasmerExportIter {
export_iter: Box<dyn Iterator<Item = (String, wasmer_runtime::Export)> + 'a>
}
impl<'a> Iterator for WasmerExportIter<'a> {
type Item = (String, wasmer_runtime::Export);
fn next(&mut self) -> Option<Self::Item> {
self.export_iter.as_mut().next()
}
}*/

View File

@ -18,6 +18,7 @@ marine-it-generator = { path = "../crates/it-generator", version = "0.6.0" }
marine-module-interface = { path = "../crates/module-interface", version = "0.2.0" } marine-module-interface = { path = "../crates/module-interface", version = "0.2.0" }
marine-utils = { path = "../crates/utils", version = "0.4.0" } marine-utils = { path = "../crates/utils", version = "0.4.0" }
marine-min-it-version = { path = "../crates/min-it-version", version = "0.1.0"} marine-min-it-version = { path = "../crates/min-it-version", version = "0.1.0"}
marine-wasm-backend-traits = { path = "../crates/wasm-backend-traits", version = "0.1.0"}
wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" } wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc # dynamicfunc-fat-closures allows using state inside DynamicFunc
@ -47,3 +48,4 @@ reqwest = "0.10.4"
bytes = "0.5.4" bytes = "0.5.4"
tokio = { version = "0.2.20", features = ["blocking", "macros"] } tokio = { version = "0.2.20", features = ["blocking", "macros"] }
once_cell = "1.4.0" once_cell = "1.4.0"
marine-wasmer-backend = { path = "../crates/wasmer-backend", version = "0.1.0"}

View File

@ -18,6 +18,8 @@ use super::*;
use crate::module::MModule; use crate::module::MModule;
use crate::module::MRecordTypes; use crate::module::MRecordTypes;
use marine_wasm_backend_traits::WasmBackend;
use serde::Serialize; use serde::Serialize;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
@ -32,12 +34,12 @@ pub struct MModuleInterface<'a> {
} }
/// The base struct of Marine, the Fluence compute runtime. /// The base struct of Marine, the Fluence compute runtime.
pub struct Marine { pub struct Marine<WB: WasmBackend> {
// set of modules registered inside Marine // set of modules registered inside Marine
modules: HashMap<String, MModule>, modules: HashMap<String, MModule<WB>>,
} }
impl Marine { impl<WB: WasmBackend> Marine<WB> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
modules: HashMap::new(), modules: HashMap::new(),
@ -149,7 +151,7 @@ impl Marine {
records.into() records.into()
} }
fn get_module_interface(module: &MModule) -> MModuleInterface<'_> { fn get_module_interface(module: &MModule<WB>) -> MModuleInterface<'_> {
let record_types = module.export_record_types(); let record_types = module.export_record_types();
let function_signatures = module.get_exports_signatures().collect::<Vec<_>>(); let function_signatures = module.get_exports_signatures().collect::<Vec<_>>();
@ -161,7 +163,7 @@ impl Marine {
} }
} }
impl Default for Marine { impl<WB: WasmBackend> Default for Marine<WB> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }

View File

@ -20,7 +20,7 @@ use crate::misc::PrepareError;
use marine_it_interfaces::MITInterfacesError; use marine_it_interfaces::MITInterfacesError;
use marine_it_parser::ITParserError; use marine_it_parser::ITParserError;
use marine_module_interface::it_interface::ITInterfaceError; use marine_module_interface::it_interface::ITInterfaceError;
use marine_wasm_backend_traits::WasmBackendError;
use wasmer_runtime::error as wasmer_error; use wasmer_runtime::error as wasmer_error;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
@ -101,6 +101,9 @@ pub enum MError {
/// Incorrect IT section. /// Incorrect IT section.
#[error("{0}")] #[error("{0}")]
IncorrectWIT(String), IncorrectWIT(String),
#[error("WASM BACKEND ERROR: {0}")]
WasmBackendError(WasmBackendError)
} }
impl From<MITInterfacesError> for MError { impl From<MITInterfacesError> for MError {
@ -132,3 +135,9 @@ impl From<()> for MError {
MError::IncorrectWIT("failed to parse instructions for adapter type".to_string()) MError::IncorrectWIT("failed to parse instructions for adapter type".to_string())
} }
} }
impl From<WasmBackendError> for MError {
fn from(err: WasmBackendError) -> Self {
MError::WasmBackendError(err)
}
}

View File

@ -21,11 +21,13 @@ use marine_module_info_parser::sdk_version;
use marine_min_it_version::min_sdk_version; use marine_min_it_version::min_sdk_version;
use marine_min_it_version::min_it_version; use marine_min_it_version::min_it_version;
use wasmer_core::Module; use marine_wasm_backend_traits::Module;
pub(crate) fn check_sdk_version( //use wasmer_core::Module;
pub(crate) fn check_sdk_version<M: Module>(
name: impl Into<String>, name: impl Into<String>,
wasmer_module: &Module, wasmer_module: &M,
) -> PrepareResult<()> { ) -> PrepareResult<()> {
let module_version = sdk_version::extract_from_wasmer_module(wasmer_module)?; let module_version = sdk_version::extract_from_wasmer_module(wasmer_module)?;
let module_version = match module_version { let module_version = match module_version {

View File

@ -21,12 +21,16 @@ use super::{IType, IRecordType, IFunctionArg, IValue, WValue};
use crate::MResult; use crate::MResult;
use crate::MModuleConfig; use crate::MModuleConfig;
use marine_wasm_backend_traits::WasmBackend;
use marine_wasm_backend_traits::Module;
use marine_wasm_backend_traits::Instance;
use marine_it_interfaces::MITInterfaces; use marine_it_interfaces::MITInterfaces;
use marine_it_parser::extract_it_from_module; use marine_it_parser::extract_it_from_module;
use marine_utils::SharedString; use marine_utils::SharedString;
use wasmer_core::Instance as WasmerInstance; //use wasmer_core::Instance as WasmerInstance;
use wasmer_core::import::Namespace; use wasmer_core::import::Namespace;
use wasmer_runtime::compile; //use wasmer_runtime::compile;
use wasmer_runtime::ImportObject; use wasmer_runtime::ImportObject;
use wasmer_it::interpreter::Interpreter; use wasmer_it::interpreter::Interpreter;
@ -36,23 +40,23 @@ use std::mem::MaybeUninit;
use std::sync::Arc; use std::sync::Arc;
use std::rc::Rc; use std::rc::Rc;
type ITInterpreter = type ITInterpreter<WB> =
Interpreter<ITInstance, ITExport, WITFunction, WITMemory, WITMemoryView<'static>>; Interpreter<ITInstance<WB>, ITExport, WITFunction<WB>, WITMemory, WITMemoryView<'static>>;
#[derive(Clone)] #[derive(Clone)]
pub(super) struct ITModuleFunc { pub(super) struct ITModuleFunc<WB: WasmBackend> {
interpreter: Arc<ITInterpreter>, interpreter: Arc<ITInterpreter<WB>>,
pub(super) arguments: Rc<Vec<IFunctionArg>>, pub(super) arguments: Rc<Vec<IFunctionArg>>,
pub(super) output_types: Rc<Vec<IType>>, pub(super) output_types: Rc<Vec<IType>>,
} }
#[derive(Clone)] #[derive(Clone)]
pub(super) struct Callable { pub(super) struct Callable<WB: WasmBackend> {
pub(super) it_instance: Arc<ITInstance>, pub(super) it_instance: Arc<ITInstance<WB>>,
pub(super) it_module_func: ITModuleFunc, pub(super) it_module_func: ITModuleFunc<WB>,
} }
impl Callable { impl<WB: WasmBackend> Callable<WB> {
pub fn call(&mut self, args: &[IValue]) -> MResult<Vec<IValue>> { pub fn call(&mut self, args: &[IValue]) -> MResult<Vec<IValue>> {
use wasmer_it::interpreter::stack::Stackable; use wasmer_it::interpreter::stack::Stackable;
@ -67,13 +71,13 @@ impl Callable {
} }
} }
type ExportFunctions = HashMap<SharedString, Rc<Callable>>; type ExportFunctions<WB> = HashMap<SharedString, Rc<Callable<WB>>>;
pub(crate) struct MModule { pub(crate) struct MModule<WB: WasmBackend> {
// wasmer_instance is needed because WITInstance contains dynamic functions // wasmer_instance is needed because WITInstance contains dynamic functions
// that internally keep pointer to it. // that internally keep pointer to it.
#[allow(unused)] #[allow(unused)]
wasmer_instance: Box<WasmerInstance>, wasmer_instance: Box<<<WB as WasmBackend>::M as Module>::I>,
// import_object is needed because ImportObject::extend doesn't really deep copy // import_object is needed because ImportObject::extend doesn't really deep copy
// imports, so we need to store imports of this module to prevent their removing. // imports, so we need to store imports of this module to prevent their removing.
@ -91,21 +95,21 @@ pub(crate) struct MModule {
host_closures_import_object: ImportObject, host_closures_import_object: ImportObject,
// TODO: replace with dyn Trait // TODO: replace with dyn Trait
export_funcs: ExportFunctions, export_funcs: ExportFunctions<WB>,
// TODO: save refs instead copying of a record types HashMap. // TODO: save refs instead copying of a record types HashMap.
/// Record types used in exported functions as arguments or return values. /// Record types used in exported functions as arguments or return values.
export_record_types: MRecordTypes, export_record_types: MRecordTypes,
} }
impl MModule { impl<WB: WasmBackend> MModule<WB> {
pub(crate) fn new( pub(crate) fn new(
name: &str, name: &str,
wasm_bytes: &[u8], wasm_bytes: &[u8],
config: MModuleConfig, config: MModuleConfig,
modules: &HashMap<String, MModule>, modules: &HashMap<String, MModule<WB>>,
) -> MResult<Self> { ) -> MResult<Self> {
let wasmer_module = compile(wasm_bytes)?; let wasmer_module = WB::compile(wasm_bytes)?;
crate::misc::check_sdk_version(name, &wasmer_module)?; crate::misc::check_sdk_version(name, &wasmer_module)?;
let it = extract_it_from_module(&wasmer_module)?; let it = extract_it_from_module(&wasmer_module)?;
@ -125,14 +129,14 @@ impl MModule {
// it and the environment is single-threaded // it and the environment is single-threaded
*Arc::get_mut_unchecked(&mut wit_instance) = *Arc::get_mut_unchecked(&mut wit_instance) =
MaybeUninit::new(ITInstance::new(&wasmer_instance, name, &mit, modules)?); MaybeUninit::new(ITInstance::new(&wasmer_instance, name, &mit, modules)?);
std::mem::transmute::<_, Arc<ITInstance>>(wit_instance) std::mem::transmute::<_, Arc<ITInstance<WB>>>(wit_instance)
}; };
let (export_funcs, export_record_types) = Self::instantiate_exports(&it_instance, &mit)?; let (export_funcs, export_record_types) = Self::instantiate_exports(&it_instance, &mit)?;
// call _start to populate the WASI state of the module // call _start to populate the WASI state of the module
#[rustfmt::skip] #[rustfmt::skip]
if let Ok(start_func) = wasmer_instance.exports.get::<wasmer_runtime::Func<'_, (), ()>>("_start") { if let Ok(start_func) = wasmer_instance.exports().get::<wasmer_runtime::Func<'_, (), ()>>("_start") {
start_func.call()?; start_func.call()?;
} }
@ -199,7 +203,7 @@ impl MModule {
&self, &self,
module_name: &str, module_name: &str,
function_name: &str, function_name: &str,
) -> MResult<Rc<Callable>> { ) -> MResult<Rc<Callable<WB>>> {
match self.export_funcs.get(function_name) { match self.export_funcs.get(function_name) {
Some(func) => Ok(func.clone()), Some(func) => Ok(func.clone()),
None => Err(MError::NoSuchFunction( None => Err(MError::NoSuchFunction(
@ -259,9 +263,9 @@ impl MModule {
} }
fn instantiate_exports( fn instantiate_exports(
it_instance: &Arc<ITInstance>, it_instance: &Arc<ITInstance<WB>>,
mit: &MITInterfaces<'_>, mit: &MITInterfaces<'_>,
) -> MResult<(ExportFunctions, MRecordTypes)> { ) -> MResult<(ExportFunctions<WB>, MRecordTypes)> {
let module_interface = marine_module_interface::it_interface::get_interface(mit)?; let module_interface = marine_module_interface::it_interface::get_interface(mit)?;
let export_funcs = module_interface let export_funcs = module_interface
@ -270,7 +274,7 @@ impl MModule {
.map(|sign| { .map(|sign| {
let adapter_instructions = mit.adapter_by_type_r(sign.adapter_function_type)?; let adapter_instructions = mit.adapter_by_type_r(sign.adapter_function_type)?;
let interpreter: ITInterpreter = adapter_instructions.clone().try_into()?; let interpreter: ITInterpreter<WB> = adapter_instructions.clone().try_into()?;
let it_module_func = ITModuleFunc { let it_module_func = ITModuleFunc {
interpreter: Arc::new(interpreter), interpreter: Arc::new(interpreter),
arguments: sign.arguments.clone(), arguments: sign.arguments.clone(),
@ -285,7 +289,7 @@ impl MModule {
Ok((shared_string, callable)) Ok((shared_string, callable))
}) })
.collect::<MResult<ExportFunctions>>()?; .collect::<MResult<ExportFunctions<WB>>>()?;
Ok((export_funcs, module_interface.export_record_types)) Ok((export_funcs, module_interface.export_record_types))
} }
@ -293,7 +297,7 @@ impl MModule {
// this function deals only with import functions that have an adaptor implementation // this function deals only with import functions that have an adaptor implementation
fn adjust_wit_imports( fn adjust_wit_imports(
wit: &MITInterfaces<'_>, wit: &MITInterfaces<'_>,
wit_instance: Arc<MaybeUninit<ITInstance>>, wit_instance: Arc<MaybeUninit<ITInstance<WB>>>,
) -> MResult<ImportObject> { ) -> MResult<ImportObject> {
use marine_it_interfaces::ITAstType; use marine_it_interfaces::ITAstType;
use wasmer_core::typed_func::DynamicFunc; use wasmer_core::typed_func::DynamicFunc;
@ -317,9 +321,9 @@ impl MModule {
} }
// creates a closure that is represent a IT module import // creates a closure that is represent a IT module import
fn create_raw_import( fn create_raw_import<WB: WasmBackend + 'static>(
wit_instance: Arc<MaybeUninit<ITInstance>>, wit_instance: Arc<MaybeUninit<ITInstance<WB>>>,
interpreter: ITInterpreter, interpreter: ITInterpreter<WB>,
import_namespace: String, import_namespace: String,
import_name: String, import_name: String,
) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static { ) -> impl Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static {
@ -383,7 +387,7 @@ impl MModule {
arguments, arguments,
output_types, output_types,
} => { } => {
let interpreter: ITInterpreter = adapter_instructions.clone().try_into()?; let interpreter: ITInterpreter<WB> = adapter_instructions.clone().try_into()?;
let raw_import = create_raw_import( let raw_import = create_raw_import(
wit_instance.clone(), wit_instance.clone(),

View File

@ -19,6 +19,8 @@ use super::{IType, IFunctionArg, IValue, WValue};
use super::marine_module::Callable; use super::marine_module::Callable;
use crate::MResult; use crate::MResult;
use marine_wasm_backend_traits::WasmBackend;
use wasmer_it::interpreter::wasm; use wasmer_it::interpreter::wasm;
use wasmer_core::instance::DynFunc; use wasmer_core::instance::DynFunc;
@ -26,26 +28,26 @@ use wasmer_core::instance::DynFunc;
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone)] #[derive(Clone)]
enum WITFunctionInner { enum WITFunctionInner<WB: WasmBackend> {
Export { Export {
func: Rc<DynFunc<'static>>, func: Rc<DynFunc<'static>>,
}, },
Import { Import {
// TODO: use dyn Callable here // TODO: use dyn Callable here
callable: Rc<Callable>, callable: Rc<Callable<WB>>,
}, },
} }
/// Represents all import and export functions that could be called from IT context by call-core. /// Represents all import and export functions that could be called from IT context by call-core.
#[derive(Clone)] #[derive(Clone)]
pub(super) struct WITFunction { pub(super) struct WITFunction<WB: WasmBackend> {
name: String, name: String,
arguments: Rc<Vec<IFunctionArg>>, arguments: Rc<Vec<IFunctionArg>>,
outputs: Rc<Vec<IType>>, outputs: Rc<Vec<IType>>,
inner: WITFunctionInner, inner: WITFunctionInner<WB>,
} }
impl WITFunction { impl<WB: WasmBackend> WITFunction<WB> {
/// Creates functions from a "usual" (not IT) module export. /// Creates functions from a "usual" (not IT) module export.
pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult<Self> { pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult<Self> {
use super::type_converters::wtype_to_itype; use super::type_converters::wtype_to_itype;
@ -83,7 +85,7 @@ impl WITFunction {
/// Creates function from a module import. /// Creates function from a module import.
pub(super) fn from_import( pub(super) fn from_import(
wit_module: &MModule, wit_module: &MModule<WB>,
module_name: &str, module_name: &str,
function_name: &str, function_name: &str,
arguments: Rc<Vec<IFunctionArg>>, arguments: Rc<Vec<IFunctionArg>>,
@ -104,7 +106,7 @@ impl WITFunction {
} }
} }
impl wasm::structures::LocalImport for WITFunction { impl<WB: WasmBackend> wasm::structures::LocalImport for WITFunction<WB> {
fn name(&self) -> &str { fn name(&self) -> &str {
self.name.as_str() self.name.as_str()
} }

View File

@ -19,11 +19,16 @@ use super::marine_module::MModule;
use super::IRecordType; use super::IRecordType;
use crate::MResult; use crate::MResult;
use marine_wasm_backend_traits::WasmBackend;
use marine_wasm_backend_traits::Module;
use marine_wasm_backend_traits::Instance;
use marine_it_interfaces::MITInterfaces; use marine_it_interfaces::MITInterfaces;
use marine_it_interfaces::ITAstType; use marine_it_interfaces::ITAstType;
use wasmer_it::interpreter::wasm; use wasmer_it::interpreter::wasm;
use wasmer_it::interpreter::wasm::structures::{LocalImportIndex, Memory, TypedIndex}; use wasmer_it::interpreter::wasm::structures::{LocalImportIndex, Memory, TypedIndex};
use wasmer_core::Instance as WasmerInstance; //use wasmer_core::Instance as WasmerInstance;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@ -32,9 +37,9 @@ pub type MRecordTypes = HashMap<u64, Rc<IRecordType>>;
/// Contains all import and export functions that could be called from IT context by call-core. /// Contains all import and export functions that could be called from IT context by call-core.
#[derive(Clone)] #[derive(Clone)]
pub(super) struct ITInstance { pub(super) struct ITInstance<WB: WasmBackend> {
/// IT functions indexed by id. /// IT functions indexed by id.
funcs: HashMap<usize, WITFunction>, funcs: HashMap<usize, WITFunction<WB>>,
/// IT memories. /// IT memories.
memories: Vec<WITMemory>, memories: Vec<WITMemory>,
@ -43,12 +48,12 @@ pub(super) struct ITInstance {
record_types_by_id: MRecordTypes, record_types_by_id: MRecordTypes,
} }
impl ITInstance { impl<WB: WasmBackend> ITInstance<WB> {
pub(super) fn new( pub(super) fn new(
wasmer_instance: &WasmerInstance, wasmer_instance: &<<WB as WasmBackend>::M as Module>::I,
module_name: &str, module_name: &str,
wit: &MITInterfaces<'_>, wit: &MITInterfaces<'_>,
modules: &HashMap<String, MModule>, modules: &HashMap<String, MModule<WB>>,
) -> MResult<Self> { ) -> MResult<Self> {
let mut exports = Self::extract_raw_exports(wasmer_instance, wit)?; let mut exports = Self::extract_raw_exports(wasmer_instance, wit)?;
let imports = Self::extract_imports(module_name, modules, wit, exports.len())?; let imports = Self::extract_imports(module_name, modules, wit, exports.len())?;
@ -66,13 +71,13 @@ impl ITInstance {
}) })
} }
fn extract_raw_exports( fn extract_raw_exports<I: Instance>(
wasmer_instance: &WasmerInstance, wasmer_instance: &I,
it: &MITInterfaces<'_>, it: &MITInterfaces<'_>,
) -> MResult<HashMap<usize, WITFunction>> { ) -> MResult<HashMap<usize, WITFunction<WB>>> {
use wasmer_core::DynFunc; use wasmer_core::DynFunc;
let module_exports = &wasmer_instance.exports; let module_exports = &wasmer_instance.exports();
it.exports() it.exports()
.enumerate() .enumerate()
@ -95,10 +100,10 @@ impl ITInstance {
/// Extracts only those imports that don't have implementations. /// Extracts only those imports that don't have implementations.
fn extract_imports( fn extract_imports(
module_name: &str, module_name: &str,
modules: &HashMap<String, MModule>, modules: &HashMap<String, MModule<WB>>,
wit: &MITInterfaces<'_>, wit: &MITInterfaces<'_>,
start_index: usize, start_index: usize,
) -> MResult<HashMap<usize, WITFunction>> { ) -> MResult<HashMap<usize, WITFunction<WB>>> {
wit.imports() wit.imports()
.filter(|import| .filter(|import|
// filter out imports that have implementations // filter out imports that have implementations
@ -136,11 +141,11 @@ impl ITInstance {
.collect::<MResult<HashMap<_, _>>>() .collect::<MResult<HashMap<_, _>>>()
} }
fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec<WITMemory> { fn extract_memories<I: Instance>(wasmer_instance: &I) -> Vec<WITMemory> {
use wasmer_core::export::Export::Memory; use wasmer_core::export::Export::Memory;
let mut memories = wasmer_instance let mut memories = wasmer_instance
.exports() .export_iter()
.filter_map(|(_, export)| match export { .filter_map(|(_, export)| match export {
Memory(memory) => Some(WITMemory(memory)), Memory(memory) => Some(WITMemory(memory)),
_ => None, _ => None,
@ -148,7 +153,7 @@ impl ITInstance {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if let Some(Memory(memory)) = wasmer_instance if let Some(Memory(memory)) = wasmer_instance
.import_object .import_object()
.maybe_with_namespace("env", |env| env.get_export("memory")) .maybe_with_namespace("env", |env| env.get_export("memory"))
{ {
memories.push(WITMemory(memory)); memories.push(WITMemory(memory));
@ -175,15 +180,15 @@ impl ITInstance {
} }
} }
impl<'v> wasm::structures::Instance<ITExport, WITFunction, WITMemory, WITMemoryView<'v>> impl<'v, WB: WasmBackend> wasm::structures::Instance<ITExport, WITFunction<WB>, WITMemory, WITMemoryView<'v>>
for ITInstance for ITInstance<WB>
{ {
fn export(&self, _export_name: &str) -> Option<&ITExport> { fn export(&self, _export_name: &str) -> Option<&ITExport> {
// exports aren't used in this version of IT // exports aren't used in this version of IT
None None
} }
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction> { fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction<WB>> {
self.funcs.get(&index.index()) self.funcs.get(&index.index())
} }

View File

@ -24,9 +24,11 @@ static GREETING_WASM_BYTES: Lazy<Vec<u8>> = Lazy::new(|| {
.expect("../examples/greeting/artifacts/greeting.wasm should presence") .expect("../examples/greeting/artifacts/greeting.wasm should presence")
}); });
use marine_wasmer_backend::WasmerBackend;
#[test] #[test]
pub fn greeting_basic() { pub fn greeting_basic() {
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
marine marine
.load_module("greeting", &*GREETING_WASM_BYTES, <_>::default()) .load_module("greeting", &*GREETING_WASM_BYTES, <_>::default())
.unwrap_or_else(|e| panic!("can't load a module into Marine: {:?}", e)); .unwrap_or_else(|e| panic!("can't load a module into Marine: {:?}", e));
@ -50,7 +52,7 @@ pub fn greeting_basic() {
#[test] #[test]
// test loading module with the same name twice // test loading module with the same name twice
pub fn non_unique_module_name() { pub fn non_unique_module_name() {
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
let module_name = String::from("greeting"); let module_name = String::from("greeting");
marine marine
.load_module(&module_name, &*GREETING_WASM_BYTES, <_>::default()) .load_module(&module_name, &*GREETING_WASM_BYTES, <_>::default())
@ -68,7 +70,7 @@ pub fn non_unique_module_name() {
#[allow(unused_variables)] #[allow(unused_variables)]
// test calling Marine with non-exist module and function names // test calling Marine with non-exist module and function names
pub fn non_exist_module_func() { pub fn non_exist_module_func() {
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
marine marine
.load_module("greeting", &*GREETING_WASM_BYTES, <_>::default()) .load_module("greeting", &*GREETING_WASM_BYTES, <_>::default())
.unwrap_or_else(|e| panic!("can't load a module into Marine: {:?}", e)); .unwrap_or_else(|e| panic!("can't load a module into Marine: {:?}", e));

View File

@ -17,6 +17,8 @@
use marine::Marine; use marine::Marine;
use marine::IValue; use marine::IValue;
use marine_wasmer_backend::WasmerBackend;
#[test] #[test]
pub fn records() { pub fn records() {
let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/records_effector.wasm") let effector_wasm_bytes = std::fs::read("../examples/records/artifacts/records_effector.wasm")
@ -25,7 +27,7 @@ pub fn records() {
let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/records_pure.wasm") let pure_wasm_bytes = std::fs::read("../examples/records/artifacts/records_pure.wasm")
.expect("../examples/records/artifacts/records_pure.wasm should presence"); .expect("../examples/records/artifacts/records_pure.wasm should presence");
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
let load_result = marine.load_module("pure", &pure_wasm_bytes, <_>::default()); let load_result = marine.load_module("pure", &pure_wasm_bytes, <_>::default());
assert!(load_result.is_err()); assert!(load_result.is_err());

View File

@ -16,6 +16,7 @@
use marine::Marine; use marine::Marine;
use marine::IValue; use marine::IValue;
use marine_wasmer_backend::WasmerBackend;
const REDIS_DOWNLOAD_URL: &str = const REDIS_DOWNLOAD_URL: &str =
"https://github.com/fluencelabs/redis/releases/download/v0.14.0_w/redis.wasm"; "https://github.com/fluencelabs/redis/releases/download/v0.14.0_w/redis.wasm";
@ -35,7 +36,7 @@ pub async fn download(url: &str) -> bytes::Bytes {
async fn redis() { async fn redis() {
let wasm_bytes = download(REDIS_DOWNLOAD_URL).await; let wasm_bytes = download(REDIS_DOWNLOAD_URL).await;
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
let module_name = "redis"; let module_name = "redis";
let config = <_>::default(); let config = <_>::default();
@ -95,7 +96,7 @@ async fn redis() {
async fn sqlite() { async fn sqlite() {
let wasm_bytes = download(SQLITE_DOWNLOAD_URL).await; let wasm_bytes = download(SQLITE_DOWNLOAD_URL).await;
let mut marine = Marine::new(); let mut marine = Marine::<WasmerBackend>::new();
let module_name = "sqlite"; let module_name = "sqlite";
let config = <_>::default(); let config = <_>::default();

View File

@ -68,13 +68,13 @@ impl Marine {
pub fn load_module<S: Into<String>>( pub fn load_module<S: Into<String>>(
&mut self, &mut self,
name: S, name: S,
wit_section_bytes: &[u8], wasm_bytes: &[u8],
) -> MResult<()> { ) -> MResult<()> {
self.load_module_(name.into(), wit_section_bytes) self.load_module_(name.into(), wasm_bytes)
} }
fn load_module_(&mut self, name: String, wit_section_bytes: &[u8]) -> MResult<()> { fn load_module_(&mut self, name: String, wasm_bytes: &[u8]) -> MResult<()> {
let module = MModule::new(&name, wit_section_bytes)?; let module = MModule::new(&name, wasm_bytes)?;
match self.modules.entry(name) { match self.modules.entry(name) {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {

View File

@ -86,8 +86,11 @@ pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfac
#[allow(unused)] #[allow(unused)]
impl MModule { impl MModule {
pub(crate) fn new(name: &str, wit_section_bytes: &[u8]) -> MResult<Self> { pub(crate) fn new(name: &str, wasm_bytes: &[u8]) -> MResult<Self> {
let it = extract_it_from_bytes(wit_section_bytes)?; // TODO: compile module
// TODO: extract it section
// TODO: extract sdk version
let it = extract_it_from_bytes(wasm_bytes)?;
crate::misc::check_it_version(name, &it.version)?; crate::misc::check_it_version(name, &it.version)?;
let mit = MITInterfaces::new(it); let mit = MITInterfaces::new(it);