Files
marine/fce/src/vm/module/fce_module.rs

348 lines
13 KiB
Rust
Raw Normal View History

2020-05-30 01:55:39 +03:00
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2020-06-02 17:20:00 +03:00
use super::wit_prelude::*;
use super::{IType, IValue, WValue};
2020-06-04 19:06:23 +03:00
use fce_wit_interfaces::FCEWITInterfaces;
2020-06-02 17:20:00 +03:00
use wasmer_wit::interpreter::Interpreter;
2020-05-30 01:55:39 +03:00
use wasmer_runtime::{compile, ImportObject};
2020-06-02 17:20:00 +03:00
use wasmer_core::Instance as WasmerInstance;
use wasmer_core::import::Namespace;
2020-06-06 01:03:49 +03:00
use wit_parser::extract_wit;
2020-05-30 01:55:39 +03:00
use std::collections::HashMap;
use std::convert::TryInto;
2020-06-01 02:45:04 +03:00
use std::mem::MaybeUninit;
use std::sync::Arc;
2020-06-07 22:57:30 +03:00
use std::borrow::BorrowMut;
2020-05-30 01:55:39 +03:00
2020-06-01 02:45:04 +03:00
type WITInterpreter =
Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
2020-06-04 19:06:23 +03:00
2020-06-07 22:57:30 +03:00
#[derive(Clone)]
pub(super) struct WITModuleFunc {
interpreter: Arc<WITInterpreter>,
pub(super) inputs: Vec<IType>,
pub(super) outputs: Vec<IType>,
}
#[derive(Clone)]
pub(super) struct Callable {
pub(super) wit_instance: Arc<WITInstance>,
pub(super) wit_module_func: WITModuleFunc,
}
impl Callable {
pub fn call(&mut self, args: &[IValue]) -> Result<Vec<IValue>, FCEError> {
use wasmer_wit::interpreter::stack::Stackable;
let result = self.wit_module_func
.interpreter
.run(args, Arc::make_mut(&mut self.wit_instance))?
.as_slice()
.to_owned();
Ok(result)
}
2020-06-04 19:06:23 +03:00
}
2020-05-30 01:55:39 +03:00
2020-06-02 17:20:00 +03:00
pub struct FCEModule {
// it is needed because of WITInstance contains dynamic functions
// that internally keep pointer to Wasmer instance.
2020-06-02 00:12:23 +03:00
#[allow(unused)]
2020-06-02 17:20:00 +03:00
wamser_instance: WasmerInstance,
2020-06-07 22:57:30 +03:00
import_object: ImportObject,
// TODO: replace with dyn Trait
pub(super) exports_funcs: HashMap<String, Arc<Callable>>,
2020-05-30 01:55:39 +03:00
}
2020-06-07 12:33:26 +03:00
impl Drop for FCEModule {
fn drop(&mut self) {
2020-06-07 22:57:30 +03:00
println!("FCEModule dropped: {:?}", self.exports_funcs.keys());
2020-06-07 12:33:26 +03:00
}
}
2020-06-02 17:20:00 +03:00
impl FCEModule {
2020-06-01 02:45:04 +03:00
pub fn new(
wasm_bytes: &[u8],
2020-06-07 22:57:30 +03:00
fce_imports: ImportObject,
modules: &HashMap<String, FCEModule>,
2020-06-02 19:16:15 +03:00
) -> Result<Self, FCEError> {
2020-06-02 17:20:00 +03:00
let wasmer_module = compile(&wasm_bytes)?;
2020-06-06 01:03:49 +03:00
let wit = extract_wit(&wasmer_module)?;
let fce_wit = FCEWITInterfaces::new(wit);
2020-05-30 01:55:39 +03:00
2020-06-01 02:45:04 +03:00
let mut wit_instance = Arc::new_uninit();
2020-06-06 01:03:49 +03:00
let mut import_object = Self::adjust_wit_imports(&fce_wit, wit_instance.clone())?;
2020-06-07 22:57:30 +03:00
let mut fce_imports = fce_imports;
fce_imports.extend(import_object.clone());
2020-05-30 01:55:39 +03:00
2020-06-07 22:57:30 +03:00
let wasmer_instance = wasmer_module.instantiate(&fce_imports)?;
2020-05-30 01:55:39 +03:00
2020-06-01 02:45:04 +03:00
let wit_instance = unsafe {
2020-06-02 00:12:23 +03:00
// get_mut_unchecked here is safe because currently only this modules have reference to
// it and the environment is single-threaded
2020-06-01 02:45:04 +03:00
*Arc::get_mut_unchecked(&mut wit_instance) =
2020-06-06 01:03:49 +03:00
MaybeUninit::new(WITInstance::new(&wasmer_instance, &fce_wit, modules)?);
2020-06-01 02:45:04 +03:00
std::mem::transmute::<_, Arc<WITInstance>>(wit_instance)
};
2020-05-30 01:55:39 +03:00
2020-06-07 22:57:30 +03:00
let exports_funcs = Self::instantiate_wit_exports(wit_instance.clone(), &fce_wit)?;
2020-05-30 01:55:39 +03:00
Ok(Self {
2020-06-02 17:20:00 +03:00
wamser_instance: wasmer_instance,
2020-06-07 22:57:30 +03:00
import_object,
exports_funcs,
2020-05-30 01:55:39 +03:00
})
}
2020-06-03 23:08:18 +03:00
pub fn call(&mut self, function_name: &str, args: &[IValue]) -> Result<Vec<IValue>, FCEError> {
2020-06-02 17:20:00 +03:00
use wasmer_wit::interpreter::stack::Stackable;
2020-06-07 22:57:30 +03:00
match self.exports_funcs.get_mut(function_name) {
2020-05-30 01:55:39 +03:00
Some(func) => {
2020-06-07 22:57:30 +03:00
Arc::make_mut(func).call(args)
2020-05-30 01:55:39 +03:00
}
2020-06-02 19:16:15 +03:00
None => Err(FCEError::NoSuchFunction(format!(
2020-06-02 00:12:23 +03:00
"{} hasn't been found while calling",
function_name
))),
2020-06-01 02:45:04 +03:00
}
}
pub fn get_func_signature(
&self,
function_name: &str,
2020-06-02 19:16:15 +03:00
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
2020-06-02 17:20:00 +03:00
match self.exports_funcs.get(function_name) {
2020-06-07 22:57:30 +03:00
Some(func) => Ok((&func.wit_module_func.inputs, &func.wit_module_func.outputs)),
2020-06-06 21:34:13 +03:00
None => {
for func in self.exports_funcs.iter() {
println!("{}", func.0);
}
Err(FCEError::NoSuchFunction(format!(
"{} has't been found during its signature looking up",
function_name
)))
}
2020-05-30 01:55:39 +03:00
}
}
2020-06-01 02:45:04 +03:00
2020-06-05 23:12:02 +03:00
pub fn get_exports_signatures(
&self,
) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> {
2020-06-07 22:57:30 +03:00
self.exports_funcs.iter().map(|(func_name, func)| {
(
func_name,
&func.wit_module_func.inputs,
&func.wit_module_func.outputs,
)
})
2020-06-05 23:12:02 +03:00
}
2020-06-02 17:20:00 +03:00
fn instantiate_wit_exports(
2020-06-07 22:57:30 +03:00
wit_instance: Arc<WITInstance>,
2020-06-04 19:06:23 +03:00
wit: &FCEWITInterfaces<'_>,
2020-06-07 22:57:30 +03:00
) -> Result<HashMap<String, Arc<Callable>>, FCEError> {
2020-06-04 19:06:23 +03:00
use fce_wit_interfaces::WITAstType;
2020-06-04 19:54:23 +03:00
wit.implementations()
.filter_map(|(adapter_function_type, core_function_type)| {
2020-06-06 21:34:13 +03:00
match wit.exports_by_type(*core_function_type) {
2020-06-04 19:54:23 +03:00
Some(export_function_name) => {
2020-06-06 21:34:13 +03:00
Some((adapter_function_type, export_function_name))
2020-06-04 19:54:23 +03:00
}
2020-06-04 19:06:23 +03:00
// pass functions that aren't export
2020-06-04 19:54:23 +03:00
None => None,
2020-06-04 19:06:23 +03:00
}
2020-06-04 19:54:23 +03:00
})
2020-06-06 21:34:13 +03:00
.map(|(adapter_function_type, export_function_names)| {
export_function_names
.iter()
.map(move |export_function_name| (*adapter_function_type, export_function_name))
})
.flatten()
2020-06-04 19:06:23 +03:00
.map(|(adapter_function_type, export_function_name)| {
2020-06-06 21:34:13 +03:00
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
2020-06-04 19:06:23 +03:00
match wit_type {
2020-06-04 19:54:23 +03:00
WITAstType::Function {
inputs, outputs, ..
} => {
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
2020-06-07 22:57:30 +03:00
let wit_module_func = WITModuleFunc {
interpreter: Arc::new(interpreter),
inputs: inputs.clone(),
outputs: outputs.clone(),
};
2020-06-04 19:06:23 +03:00
Ok((
export_function_name.to_string(),
2020-06-07 22:57:30 +03:00
Arc::new(Callable {
wit_instance: wit_instance.clone(),
wit_module_func,
}),
2020-06-04 19:06:23 +03:00
))
2020-06-04 19:54:23 +03:00
}
2020-06-04 19:06:23 +03:00
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
2020-06-04 19:54:23 +03:00
))),
2020-06-01 12:14:12 +03:00
}
2020-06-04 19:06:23 +03:00
})
2020-06-07 22:57:30 +03:00
.collect::<Result<HashMap<String, Arc<Callable>>, FCEError>>()
2020-06-01 02:45:04 +03:00
}
// this function deals only with import functions that have an adaptor implementation
2020-06-04 19:06:23 +03:00
fn adjust_wit_imports(
wit: &FCEWITInterfaces<'_>,
2020-06-01 02:45:04 +03:00
wit_instance: Arc<MaybeUninit<WITInstance>>,
2020-06-02 19:16:15 +03:00
) -> Result<ImportObject, FCEError> {
2020-06-04 19:06:23 +03:00
use fce_wit_interfaces::WITAstType;
2020-06-02 17:20:00 +03:00
use wasmer_core::typed_func::DynamicFunc;
use wasmer_core::vm::Ctx;
2020-06-01 02:45:04 +03:00
2020-06-07 12:33:26 +03:00
#[derive(Clone)]
struct T {}
impl Drop for T {
fn drop(&mut self) {
2020-06-07 22:57:30 +03:00
println!("fce_module imports: drop T");
2020-06-07 12:33:26 +03:00
}
}
2020-06-01 02:45:04 +03:00
// returns function that will be called from imports of Wasmer module
2020-06-04 19:54:23 +03:00
fn dyn_func_from_raw_import(
2020-06-04 19:06:23 +03:00
inputs: Vec<IType>,
2020-06-07 12:33:26 +03:00
wit_instance: Arc<MaybeUninit<WITInstance>>,
interpreter: WITInterpreter,
2020-06-04 19:06:23 +03:00
) -> DynamicFunc<'static> {
2020-06-04 19:54:23 +03:00
use wasmer_core::types::FuncSig;
use super::type_converters::itype_to_wtype;
2020-06-07 12:33:26 +03:00
let t = T {};
2020-06-04 19:54:23 +03:00
2020-06-01 02:45:04 +03:00
let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
2020-06-07 12:33:26 +03:00
DynamicFunc::new(
Arc::new(FuncSig::new(signature, vec![])),
move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
use super::type_converters::wval_to_ival;
let t_copied = t.clone();
2020-06-07 22:57:30 +03:00
println!("dyn_func_from_raw_import: {:?}", inputs);
2020-06-07 12:33:26 +03:00
// copy here because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
unsafe {
// error here will be propagated by the special error instruction
let _ = interpreter.run(
&converted_inputs,
Arc::make_mut(&mut wit_instance_callable.assume_init()),
);
}
// wit import functions should only change the stack state -
// the result will be returned by an export function
vec![]
},
)
2020-06-01 02:45:04 +03:00
}
2020-06-04 19:54:23 +03:00
// creates a closure that is represent a WIT module import
2020-06-04 19:06:23 +03:00
fn create_raw_import(
wit_instance: Arc<MaybeUninit<WITInstance>>,
interpreter: WITInterpreter,
) -> Box<dyn for<'a, 'b> Fn(&'a mut Ctx, &'b [WValue]) -> Vec<WValue> + 'static> {
Box::new(move |_: &mut Ctx, inputs: &[WValue]| -> Vec<WValue> {
2020-06-04 19:54:23 +03:00
use super::type_converters::wval_to_ival;
2020-06-04 19:06:23 +03:00
// copy here because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();
unsafe {
// error here will be propagated by the special error instruction
let _ = interpreter.run(
&converted_inputs,
Arc::make_mut(&mut wit_instance_callable.assume_init()),
);
}
2020-06-01 02:45:04 +03:00
2020-06-04 19:06:23 +03:00
// wit import functions should only change the stack state -
// the result will be returned by an export function
vec![]
2020-06-01 02:45:04 +03:00
})
}
2020-06-07 12:33:26 +03:00
let wit_import_funcs = wit
2020-06-04 19:06:23 +03:00
.implementations()
2020-06-04 19:54:23 +03:00
.filter_map(|(adapter_function_type, core_function_type)| {
2020-06-06 21:34:13 +03:00
match wit.imports_by_type(*core_function_type) {
Some(import) => Some((adapter_function_type, import)),
// skip functions that aren't import
2020-06-04 19:54:23 +03:00
None => None,
2020-06-04 19:06:23 +03:00
}
2020-06-04 19:54:23 +03:00
})
2020-06-06 21:34:13 +03:00
.map(|(adapter_function_type, import_function_names)| {
import_function_names
.iter()
.map(move |import_function_name| (*adapter_function_type, import_function_name))
})
.flatten()
2020-06-04 19:06:23 +03:00
.map(|(adapter_function_type, (import_namespace, import_name))| {
2020-06-06 21:34:13 +03:00
let adapter_instructions = wit.adapter_by_type_r(adapter_function_type)?;
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
2020-06-04 19:06:23 +03:00
match wit_type {
WITAstType::Function { inputs, .. } => {
2020-06-04 19:54:23 +03:00
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
2020-06-07 12:33:26 +03:00
let wit_import = dyn_func_from_raw_import(
inputs.clone(),
wit_instance.clone(),
interpreter,
);
2020-06-04 19:06:23 +03:00
2020-06-07 12:33:26 +03:00
Ok((import_namespace.to_string(), (*import_name, wit_import)))
2020-06-04 19:54:23 +03:00
}
2020-06-04 19:06:23 +03:00
_ => Err(FCEError::IncorrectWIT(format!(
"type with idx = {} isn't a function type",
adapter_function_type
2020-06-04 19:54:23 +03:00
))),
2020-06-04 19:06:23 +03:00
}
2020-06-04 19:54:23 +03:00
})
2020-06-07 12:33:26 +03:00
.collect::<Result<multimap::MultiMap<_, _>, FCEError>>()?;
2020-06-04 19:06:23 +03:00
2020-06-01 02:45:04 +03:00
let mut import_object = ImportObject::new();
2020-06-06 21:34:13 +03:00
// TODO: refactor it
2020-06-07 12:33:26 +03:00
for (namespace_name, funcs) in wit_import_funcs.into_iter() {
let mut namespace = Namespace::new();
for (import_name, import_func) in funcs.into_iter() {
namespace.insert(import_name.to_string(), import_func);
2020-06-06 21:34:13 +03:00
}
2020-06-07 12:33:26 +03:00
import_object.register(namespace_name, namespace);
2020-06-01 02:45:04 +03:00
}
Ok(import_object)
}
2020-05-30 01:55:39 +03:00
}