refactor abi

This commit is contained in:
vms 2020-05-08 22:41:29 +03:00
parent 39c9aaa703
commit d94a20f0ed
3 changed files with 68 additions and 41 deletions

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use wasmer_runtime::Func; use crate::vm::errors::FCEError;
/// Application binary interface of a FCE module. Different module could use such scheme for /// Application binary interface of a FCE module. Different module could use such scheme for
/// communicate with each other. /// communicate with each other.
@ -28,26 +28,19 @@ use wasmer_runtime::Func;
/// 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(crate) trait ModuleABI {
pub(crate) trait ModuleABI<'a> {}
#[derive(Clone)]
pub(crate) struct ABI<'a> {
// 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 FCE::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.
pub(crate) allocate: Option<Func<'a, i32, i32>>, fn allocate(&self, size: i32) -> Result<i32, FCEError>;
/// Deallocates previously allocated memory region. /// Deallocates previously allocated memory region.
pub(crate) deallocate: Option<Func<'a, (i32, i32), ()>>, fn deallocate(&self, ptr: i32, size: i32) -> Result<(), FCEError>;
/// Calls the main entry point of a module called invoke. /// Calls the main entry point of a module called invoke.
pub(crate) invoke: Option<Func<'a, (i32, i32), i32>>, fn invoke(&self, arg_address: i32, arg_size: i32) -> Result<i32, FCEError>;
/// Stores one given byte on provided address. /// Stores one byte on given address.
pub(crate) store: Option<Func<'a, (i32, i32)>>, fn store(&self, address: i32, value: i32) -> Result<(), FCEError>;
/// Loads one bytes from provided address. /// Loads one byte from given address.
pub(crate) load: Option<Func<'a, i32, i32>>, fn load(&self, address: i32) -> Result<i32, FCEError>;
} }

View File

@ -17,7 +17,7 @@
use crate::vm::config::Config; use crate::vm::config::Config;
use crate::vm::errors::FCEError; use crate::vm::errors::FCEError;
use crate::vm::module::fce_result::FCEResult; use crate::vm::module::fce_result::FCEResult;
use crate::vm::module::{ModuleAPI, ABI}; 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;
@ -26,6 +26,22 @@ use wasmer_runtime_core::import::ImportObject;
use wasmer_runtime_core::memory::ptr::{Array, WasmPtr}; use wasmer_runtime_core::memory::ptr::{Array, WasmPtr};
use wasmer_wasi::generate_import_object_for_version; use wasmer_wasi::generate_import_object_for_version;
/// Desribes Application Binary Interface of a module.
/// For more details see comment in abi.rs.
#[derive(Clone)]
pub(crate) struct ABI<'a> {
// 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 FCE::new has been succeed.
pub(crate) allocate: Option<Func<'a, i32, i32>>,
pub(crate) deallocate: Option<Func<'a, (i32, i32), ()>>,
pub(crate) invoke: Option<Func<'a, (i32, i32), i32>>,
pub(crate) store: Option<Func<'a, (i32, i32)>>,
pub(crate) load: Option<Func<'a, i32, i32>>,
}
/// A building block of multi-modules scheme of FCE, represents one module that corresponds
/// to a one Wasm file.
pub(crate) struct FCEModule { pub(crate) struct FCEModule {
instance: Instance, instance: Instance,
abi: ABI<'static>, abi: ABI<'static>,
@ -39,6 +55,7 @@ impl FCEModule {
"log_utf8_string" => func!(FCEModule::logger_log_utf8_string), "log_utf8_string" => func!(FCEModule::logger_log_utf8_string),
}, },
}; };
let config_copy = config.clone();
let mut import_object = generate_import_object_for_version( let mut import_object = generate_import_object_for_version(
config.wasi_config.version, config.wasi_config.version,
@ -52,42 +69,41 @@ impl FCEModule {
import_object.allow_missing_functions = false; import_object.allow_missing_functions = false;
let instance = compile(&wasm_bytes)?.instantiate(&import_object)?; let instance = compile(&wasm_bytes)?.instantiate(&import_object)?;
let abi = FCEModule::create_abi(&instance, &config_copy)?;
Ok(Self { instance, abi })
}
#[rustfmt::skip]
fn create_abi(instance: &Instance, config: &Config) -> Result<ABI<'static>, FCEError> {
unsafe { unsafe {
#[rustfmt::skip]
let allocate = std::mem::transmute::<Func<'_, i32, i32>, Func<'static, i32, i32>>( let allocate = std::mem::transmute::<Func<'_, i32, i32>, Func<'static, i32, i32>>(
instance.exports.get(&config.allocate_fn_name)? instance.exports.get(&config.allocate_fn_name)?
); );
#[rustfmt::skip]
let deallocate = std::mem::transmute::<Func<'_, (i32, i32)>, Func<'static, (i32, i32)>>( let deallocate = std::mem::transmute::<Func<'_, (i32, i32)>, Func<'static, (i32, i32)>>(
instance.exports.get(&config.deallocate_fn_name)? instance.exports.get(&config.deallocate_fn_name)?
); );
#[rustfmt::skip]
let invoke = std::mem::transmute::<Func<'_, (i32, i32), i32>, Func<'static, (i32, i32), i32>, >( let invoke = std::mem::transmute::<Func<'_, (i32, i32), i32>, Func<'static, (i32, i32), i32>, >(
instance.exports.get(&config.invoke_fn_name)? instance.exports.get(&config.invoke_fn_name)?
); );
#[rustfmt::skip]
let store = std::mem::transmute::<Func<'_, (i32, i32)>, Func<'static, _, _>>( let store = std::mem::transmute::<Func<'_, (i32, i32)>, Func<'static, _, _>>(
instance.exports.get(&config.store_fn_name)?, instance.exports.get(&config.store_fn_name)?,
); );
#[rustfmt::skip]
let load = std::mem::transmute::<Func<'_, i32, i32>, Func<'static, _, _>>( let load = std::mem::transmute::<Func<'_, i32, i32>, Func<'static, _, _>>(
instance.exports.get(&config.load_fn_name)?, instance.exports.get(&config.load_fn_name)?,
); );
let abi = ABI { Ok(ABI {
allocate: Some(allocate), allocate: Some(allocate),
deallocate: Some(deallocate), deallocate: Some(deallocate),
invoke: Some(invoke), invoke: Some(invoke),
store: Some(store), store: Some(store),
load: Some(load), load: Some(load),
}; })
Ok(Self { instance, abi })
} }
} }
@ -139,10 +155,11 @@ impl FCEModule {
impl ModuleAPI for FCEModule { impl ModuleAPI for FCEModule {
fn invoke(&mut self, argument: &[u8]) -> Result<FCEResult, FCEError> { fn invoke(&mut self, argument: &[u8]) -> Result<FCEResult, FCEError> {
// allocate memory for the given argument and write it to memory
let argument_len = argument.len() as i32; let argument_len = argument.len() as i32;
// allocate memory for the given argument and write it to memory
let argument_address = if argument_len != 0 { let argument_address = if argument_len != 0 {
let address = self.abi.allocate.as_ref().unwrap().call(argument_len)?; let address = self.allocate(argument_len)?;
self.write_to_mem(address as usize, argument)?; self.write_to_mem(address as usize, argument)?;
address address
} else { } else {
@ -150,19 +167,9 @@ impl ModuleAPI for FCEModule {
}; };
// invoke a main module, read a result and deallocate it // invoke a main module, read a result and deallocate it
let result_address = self let result_address = <Self as ModuleABI>::invoke(self, argument_address, argument_len)?;
.abi
.invoke
.as_ref()
.unwrap()
.call(argument_address, argument_len)?;
let result = self.read_result_from_mem(result_address as _)?; let result = self.read_result_from_mem(result_address as _)?;
self.deallocate(result_address, result.len() as i32)?;
self.abi
.deallocate
.as_ref()
.unwrap()
.call(result_address, result.len() as i32)?;
Ok(FCEResult::new(result)) Ok(FCEResult::new(result))
} }
@ -186,6 +193,33 @@ impl ModuleAPI for FCEModule {
} }
} }
impl ModuleABI for FCEModule {
fn allocate(&self, size: i32) -> Result<i32, FCEError> {
Ok(self.abi.allocate.as_ref().unwrap().call(size)?)
}
fn deallocate(&self, ptr: i32, size: i32) -> Result<(), FCEError> {
Ok(self.abi.deallocate.as_ref().unwrap().call(ptr, size)?)
}
fn invoke(&self, arg_address: i32, arg_size: i32) -> Result<i32, FCEError> {
Ok(self
.abi
.invoke
.as_ref()
.unwrap()
.call(arg_address, arg_size)?)
}
fn store(&self, address: i32, value: i32) -> Result<(), FCEError> {
Ok(self.abi.store.as_ref().unwrap().call(address, value)?)
}
fn load(&self, address: i32) -> Result<i32, FCEError> {
Ok(self.abi.load.as_ref().unwrap().call(address)?)
}
}
impl Drop for FCEModule { impl Drop for FCEModule {
fn drop(&mut self) {} fn drop(&mut self) {}
} }

View File

@ -19,6 +19,6 @@ mod api;
mod fce_module; mod fce_module;
pub mod fce_result; pub mod fce_result;
pub(crate) use abi::ABI; pub(crate) use abi::ModuleABI;
pub(crate) use api::ModuleAPI; pub(crate) use api::ModuleAPI;
pub(crate) use fce_module::FCEModule; pub(crate) use fce_module::FCEModule;