mirror of
https://github.com/fluencelabs/marine.git
synced 2025-03-16 06:20:49 +00:00
move to new dispatcher scheme
This commit is contained in:
parent
8f57458aa2
commit
4ffef90cd6
src/vm
123
src/vm/frank.rs
123
src/vm/frank.rs
@ -14,38 +14,58 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::vm::module::{FrankModule, ModuleAPI};
|
|
||||||
use crate::vm::{config::Config, errors::FrankError, service::FrankService};
|
|
||||||
use crate::vm::module::frank_result::FrankResult;
|
use crate::vm::module::frank_result::FrankResult;
|
||||||
|
use crate::vm::module::{FrankModule, ModuleABI, ModuleAPI};
|
||||||
|
use crate::vm::{config::Config, errors::FrankError, service::FrankService};
|
||||||
|
|
||||||
use wasmer_runtime_core::import::ImportObject;
|
|
||||||
use sha2::{digest::generic_array::GenericArray, digest::FixedOutput};
|
use sha2::{digest::generic_array::GenericArray, digest::FixedOutput};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use wasmer_runtime::{func, Ctx};
|
||||||
|
use wasmer_runtime_core::import::ImportObject;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Dispatcher {
|
pub struct Dispatcher {
|
||||||
api: HashMap<String, FrankModule>,
|
api: HashMap<String, ModuleABI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatcher {
|
impl Dispatcher {
|
||||||
pub fn new(api: HashMap<String, FrankModule>) -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
api
|
api: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Frank {
|
pub struct Frank {
|
||||||
modules: HashMap<String, FrankModule>,
|
modules: HashMap<String, FrankModule>,
|
||||||
|
dispatcher: Arc<Mutex<Dispatcher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frank {
|
impl Frank {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
|
dispatcher: Arc::new(Mutex::new(Dispatcher::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn out_invoke(ctx: &mut Ctx, offset: i32, size: i32) -> i32 {
|
||||||
|
let data = ctx.data as *mut Mutex<Dispatcher>;
|
||||||
|
let dispatcher: Arc<Mutex<Dispatcher>> = unsafe { Arc::from_raw(data) };
|
||||||
|
|
||||||
|
let wasm_ptr = WasmPtr::<u8, Array>::new(offset as _);
|
||||||
|
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
|
||||||
|
Some(msg) => print!("{}", msg),
|
||||||
|
None => print!("frank logger: incorrect UTF8 string's been supplied to logger"),
|
||||||
|
}
|
||||||
|
1
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrankService for Frank {
|
impl FrankService for Frank {
|
||||||
@ -65,28 +85,91 @@ impl FrankService for Frank {
|
|||||||
let prepared_wasm_bytes =
|
let prepared_wasm_bytes =
|
||||||
crate::vm::prepare::prepare_module(wasm_bytes, config.mem_pages_count)?;
|
crate::vm::prepare::prepare_module(wasm_bytes, config.mem_pages_count)?;
|
||||||
|
|
||||||
let modules_copy = self.modules.clone();
|
let dispatcher = self.dispatcher.clone();
|
||||||
let dispatcher = move || {
|
let dispatcher1 = move || {
|
||||||
let dispatcher = Dispatcher::new(modules_copy);
|
let dtor = (|_: *mut c_void| {}) as fn(*mut c_void);
|
||||||
let dispatcher = Box::new(dispatcher);
|
// TODO: try with Box
|
||||||
let dtor = (|data: *mut c_void| unsafe {
|
let dispatcher2: Arc<Mutex<Dispatcher>> = dispatcher.clone();
|
||||||
drop(Box::from_raw(data as *mut Dispatcher));
|
let raw_dispatcher =
|
||||||
}) as fn(*mut c_void);
|
Arc::into_raw(dispatcher2) as *mut Mutex<Dispatcher> as *mut c_void;
|
||||||
|
(raw_dispatcher, dtor)
|
||||||
// and then release corresponding Box object obtaining the raw pointer
|
|
||||||
(Box::leak(dispatcher) as *mut Dispatcher as *mut c_void, dtor)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut import_object = ImportObject::new_with_data(dispatcher);
|
let mut import_object = ImportObject::new_with_data(dispatcher1);
|
||||||
//import_object.register();
|
let dispatcher = self.dispatcher.lock().unwrap();
|
||||||
|
for (module, abi) in dispatcher.api.iter() {
|
||||||
|
use wasmer_runtime_core::import::Namespace;
|
||||||
|
|
||||||
let module = FrankModule::new(&prepared_wasm_bytes, config, import_object)?;
|
// TODO: introduce a macro for such things
|
||||||
match self.modules.entry(module_name) {
|
let mut namespace = Namespace::new();
|
||||||
|
let allocate = abi.allocate.clone();
|
||||||
|
namespace.insert(
|
||||||
|
config.allocate_fn_name.clone(),
|
||||||
|
func!(move |_ctx: &mut Ctx, size: i32| -> i32 {
|
||||||
|
allocate
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.call(size)
|
||||||
|
.expect("allocate failed")
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let invoke = abi.invoke.clone();
|
||||||
|
namespace.insert(
|
||||||
|
config.invoke_fn_name.clone(),
|
||||||
|
func!(move |_ctx: &mut Ctx, offset: i32, size: i32| -> i32 {
|
||||||
|
invoke
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.call(offset, size)
|
||||||
|
.expect("invoke failed")
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let deallocate = abi.deallocate.clone();
|
||||||
|
namespace.insert(
|
||||||
|
config.deallocate_fn_name.clone(),
|
||||||
|
func!(move |_ctx: &mut Ctx, ptr: i32, size: i32| {
|
||||||
|
deallocate
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.call(ptr, size)
|
||||||
|
.expect("deallocate failed");
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let store = abi.store.clone();
|
||||||
|
namespace.insert(
|
||||||
|
config.store_fn_name.clone(),
|
||||||
|
func!(move |_ctx: &mut Ctx, offset: i32, value: i32| {
|
||||||
|
store
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.call(offset, value)
|
||||||
|
.expect("store failed")
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let load = abi.load.clone();
|
||||||
|
namespace.insert(
|
||||||
|
config.load_fn_name.clone(),
|
||||||
|
func!(move |_ctx: &mut Ctx, offset: i32| -> i32 {
|
||||||
|
load.as_ref().unwrap().call(offset).expect("load failed")
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
import_object.register(module, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (module, module_abi) = FrankModule::new(&prepared_wasm_bytes, config, import_object)?;
|
||||||
|
match self.modules.entry(module_name.clone()) {
|
||||||
Entry::Vacant(entry) => entry.insert(module),
|
Entry::Vacant(entry) => entry.insert(module),
|
||||||
Entry::Occupied(_) => return Err(FrankError::NonUniqueModuleName),
|
Entry::Occupied(_) => return Err(FrankError::NonUniqueModuleName),
|
||||||
};
|
};
|
||||||
|
|
||||||
// registers new abi in a dispatcher
|
// registers new abi in a dispatcher
|
||||||
|
let mut dispatcher = self.dispatcher.lock().unwrap();
|
||||||
|
dispatcher.api.insert(module_name, module_abi);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use wasmer_runtime::Func;
|
||||||
|
|
||||||
/// Application binary interface of a Frank module. Different module could use such scheme for
|
/// Application binary interface of a Frank module. Different module could use such scheme for
|
||||||
/// communicate with each other.
|
/// communicate with each other.
|
||||||
///
|
///
|
||||||
@ -26,30 +28,44 @@
|
|||||||
/// 4. read a result from the res by reading 4 bytes as little-endian result_size
|
/// 4. read a result from the res by reading 4 bytes as little-endian result_size
|
||||||
/// and the read result_size bytes as the final result.
|
/// and the read result_size bytes as the final result.
|
||||||
/// 5. deallocate(res, strlen(sql)) to clean memory.
|
/// 5. deallocate(res, strlen(sql)) to clean memory.
|
||||||
pub trait ModuleABI {
|
// TODO: make pub(crate)
|
||||||
|
pub struct ModuleABI {
|
||||||
|
// It is safe to use unwrap() while calling these functions because Option is used here
|
||||||
|
// just to allow partially initialization. And all Option fields will contain Some if
|
||||||
|
// invoking Frank::new has been succeed.
|
||||||
/// Allocates a region of memory inside a module. Used for passing argument inside the module.
|
/// Allocates a region of memory inside a module. Used for passing argument inside the module.
|
||||||
/// size a size of allocated memory region
|
pub(crate) allocate: Option<Func<'static, i32, i32>>,
|
||||||
/// return a pointer to the allocated memory region
|
|
||||||
fn allocate(&mut self, size: i32) -> i32;
|
|
||||||
|
|
||||||
/// Deallocates previously allocated memory region.
|
/// Deallocates previously allocated memory region.
|
||||||
/// ptr a pointer to the previously allocated memory region
|
pub(crate) deallocate: Option<Func<'static, (i32, i32), ()>>,
|
||||||
// size a size of the previously allocated memory region
|
|
||||||
fn deallocate(&mut self, ptr: i32, size: i32);
|
|
||||||
|
|
||||||
/// Calls the main entry point of a module called invoke.
|
/// Calls the main entry point of a module called invoke.
|
||||||
/// ptr a pointer to the supplied request
|
pub(crate) invoke: Option<Func<'static, (i32, i32), i32>>,
|
||||||
/// size a size of the supplied request
|
|
||||||
/// return a pointer to the struct contains result_size and result
|
|
||||||
fn invoke(&mut self, ptr: i32, size: i32) -> i32;
|
|
||||||
|
|
||||||
/// Stores one given byte on provided address.
|
/// Stores one given byte on provided address.
|
||||||
/// ptr a address at which the needed byte is located
|
pub(crate) store: Option<Func<'static, (i32, i32)>>,
|
||||||
/// return the byte at the given address
|
|
||||||
fn load(&self, ptr: i32) -> i32;
|
|
||||||
|
|
||||||
/// Loads one bytes from provided address.
|
/// Loads one bytes from provided address.
|
||||||
/// ptr a address where byte should be stored
|
pub(crate) load: Option<Func<'static, i32, i32>>,
|
||||||
// value a byte to be stored
|
}
|
||||||
fn store(&mut self, ptr: i32, value: i32);
|
|
||||||
|
impl Drop for ModuleABI {
|
||||||
|
// The manually drop is needed because at first we need to delete functions
|
||||||
|
// and only then instance.
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[allow(clippy::drop_copy)]
|
||||||
|
drop(self.allocate.as_ref());
|
||||||
|
|
||||||
|
#[allow(clippy::drop_copy)]
|
||||||
|
drop(self.deallocate.as_ref());
|
||||||
|
|
||||||
|
#[allow(clippy::drop_copy)]
|
||||||
|
drop(self.invoke.as_ref());
|
||||||
|
|
||||||
|
#[allow(clippy::drop_copy)]
|
||||||
|
drop(self.store.as_ref());
|
||||||
|
|
||||||
|
#[allow(clippy::drop_copy)]
|
||||||
|
drop(self.load.as_ref());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
use crate::vm::config::Config;
|
use crate::vm::config::Config;
|
||||||
use crate::vm::errors::FrankError;
|
use crate::vm::errors::FrankError;
|
||||||
use crate::vm::module::abi::ModuleABI;
|
|
||||||
use crate::vm::module::frank_result::FrankResult;
|
use crate::vm::module::frank_result::FrankResult;
|
||||||
use crate::vm::module::ModuleAPI;
|
use crate::vm::module::{ModuleABI, ModuleAPI};
|
||||||
|
|
||||||
use sha2::digest::generic_array::GenericArray;
|
use sha2::digest::generic_array::GenericArray;
|
||||||
use sha2::digest::FixedOutput;
|
use sha2::digest::FixedOutput;
|
||||||
@ -41,12 +40,6 @@ pub struct FrankModule {
|
|||||||
|
|
||||||
/// Calls the main entry point of a module called invoke.
|
/// Calls the main entry point of a module called invoke.
|
||||||
invoke: Option<Func<'static, (i32, i32), i32>>,
|
invoke: Option<Func<'static, (i32, i32), i32>>,
|
||||||
|
|
||||||
/// Stores one given byte on provided address.
|
|
||||||
store: Option<Func<'static, (i32, i32)>>,
|
|
||||||
|
|
||||||
/// Loads one bytes from provided address.
|
|
||||||
load: Option<Func<'static, i32, i32>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrankModule {
|
impl FrankModule {
|
||||||
@ -55,7 +48,7 @@ impl FrankModule {
|
|||||||
wasm_bytes: &[u8],
|
wasm_bytes: &[u8],
|
||||||
config: Config,
|
config: Config,
|
||||||
imports: ImportObject,
|
imports: ImportObject,
|
||||||
) -> Result<Self, FrankError> {
|
) -> Result<(Self, ModuleABI), FrankError> {
|
||||||
let logger_imports = imports! {
|
let logger_imports = imports! {
|
||||||
"logger" => {
|
"logger" => {
|
||||||
"log_utf8_string" => func!(FrankModule::logger_log_utf8_string),
|
"log_utf8_string" => func!(FrankModule::logger_log_utf8_string),
|
||||||
@ -76,14 +69,21 @@ impl FrankModule {
|
|||||||
let instance = compile(&wasm_bytes)?.instantiate(&import_object)?;
|
let instance = compile(&wasm_bytes)?.instantiate(&import_object)?;
|
||||||
let instance: &'static mut Instance = Box::leak(Box::new(instance));
|
let instance: &'static mut Instance = Box::leak(Box::new(instance));
|
||||||
|
|
||||||
Ok(Self {
|
Ok((
|
||||||
instance,
|
Self {
|
||||||
allocate: Some(instance.exports.get(&config.allocate_fn_name)?),
|
instance,
|
||||||
deallocate: Some(instance.exports.get(&config.deallocate_fn_name)?),
|
allocate: Some(instance.exports.get(&config.allocate_fn_name)?),
|
||||||
invoke: Some(instance.exports.get(&config.invoke_fn_name)?),
|
deallocate: Some(instance.exports.get(&config.deallocate_fn_name)?),
|
||||||
store: Some(instance.exports.get(&config.store_fn_name)?),
|
invoke: Some(instance.exports.get(&config.invoke_fn_name)?),
|
||||||
load: Some(instance.exports.get(&config.load_fn_name)?),
|
},
|
||||||
})
|
ModuleABI {
|
||||||
|
allocate: Some(instance.exports.get(&config.allocate_fn_name)?),
|
||||||
|
deallocate: Some(instance.exports.get(&config.deallocate_fn_name)?),
|
||||||
|
invoke: Some(instance.exports.get(&config.invoke_fn_name)?),
|
||||||
|
store: Some(instance.exports.get(&config.store_fn_name)?),
|
||||||
|
load: Some(instance.exports.get(&config.load_fn_name)?),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints utf8 string of the given size from the given offset. Called from the wasm.
|
/// Prints utf8 string of the given size from the given offset. Called from the wasm.
|
||||||
@ -128,44 +128,6 @@ impl FrankModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleABI for FrankModule {
|
|
||||||
fn allocate(&mut self, size: i32) -> i32 {
|
|
||||||
self.allocate
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.call(size)
|
|
||||||
.expect("allocate failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deallocate(&mut self, ptr: i32, size: i32) {
|
|
||||||
self.deallocate
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.call(ptr, size)
|
|
||||||
.expect("allocate failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn invoke(&mut self, ptr: i32, size: i32) -> i32 {
|
|
||||||
self.invoke
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.call(ptr, size)
|
|
||||||
.expect("invoke failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load(&self, ptr: i32) -> i32 {
|
|
||||||
self.load.as_ref().unwrap().call(ptr).expect("load failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn store(&mut self, ptr: i32, value: i32) {
|
|
||||||
self.store
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.call(ptr, value)
|
|
||||||
.expect("store failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleAPI for FrankModule {
|
impl ModuleAPI for FrankModule {
|
||||||
fn invoke(&mut self, argument: &[u8]) -> Result<FrankResult, FrankError> {
|
fn invoke(&mut self, argument: &[u8]) -> Result<FrankResult, FrankError> {
|
||||||
// allocate memory for the given argument and write it to memory
|
// allocate memory for the given argument and write it to memory
|
||||||
@ -214,27 +176,5 @@ impl ModuleAPI for FrankModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for FrankModule {
|
impl Drop for FrankModule {
|
||||||
// The manually drop is needed because at first we need to delete functions
|
fn drop(&mut self) {}
|
||||||
// and only then instance.
|
|
||||||
fn drop(&mut self) {
|
|
||||||
#[allow(clippy::drop_copy)]
|
|
||||||
drop(self.allocate.as_ref());
|
|
||||||
|
|
||||||
#[allow(clippy::drop_copy)]
|
|
||||||
drop(self.deallocate.as_ref());
|
|
||||||
|
|
||||||
#[allow(clippy::drop_copy)]
|
|
||||||
drop(self.invoke.as_ref());
|
|
||||||
|
|
||||||
#[allow(clippy::drop_copy)]
|
|
||||||
drop(self.store.as_ref());
|
|
||||||
|
|
||||||
#[allow(clippy::drop_copy)]
|
|
||||||
drop(self.load.as_ref());
|
|
||||||
|
|
||||||
// delete instance
|
|
||||||
unsafe {
|
|
||||||
// let _ = Box::from_raw(self.instance as *mut FrankModule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ pub trait FrankService {
|
|||||||
/// Invokes a module supplying byte array and expecting byte array with some outcome back.
|
/// Invokes a module supplying byte array and expecting byte array with some outcome back.
|
||||||
fn invoke(&mut self, module_name: String, argument: &[u8]) -> Result<FrankResult, FrankError>;
|
fn invoke(&mut self, module_name: String, argument: &[u8]) -> Result<FrankResult, FrankError>;
|
||||||
|
|
||||||
/// Registers new module inside in Frank Service.
|
/// Registers new module in the Frank Service.
|
||||||
fn register_module(
|
fn register_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_name: String,
|
module_name: String,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user