1
0
mirror of https://github.com/fluencelabs/marine.git synced 2025-03-16 06:20:49 +00:00
This commit is contained in:
Valery Antopol 2023-02-20 19:22:10 +03:00
parent aa698e25b6
commit 736927119b
3 changed files with 142 additions and 115 deletions
core/src/host_imports
crates/marine-wasmtime-backend/src
marine/src

@ -22,7 +22,7 @@ use super::lowering::LoHelper;
use super::utils::itypes_args_to_wtypes;
use super::utils::itypes_output_to_wtypes;
use crate::MRecordTypes;
use crate::{IType, IValue, MRecordTypes};
use crate::init_wasm_func;
use crate::call_wasm_func;
use crate::HostImportDescriptor;
@ -46,120 +46,12 @@ pub(crate) fn create_host_import_func<WB: WasmBackend>(
descriptor: HostImportDescriptor<WB>,
record_types: Arc<MRecordTypes>,
) -> <WB as WasmBackend>::Function {
let HostImportDescriptor {
host_exported_func,
argument_types,
output_type,
error_handler,
} = descriptor;
let output_type_to_types = |output_type| match output_type {
Some(ty) => vec![ty],
None => vec![],
};
let raw_args = itypes_args_to_wtypes(&descriptor.argument_types);
let raw_output = itypes_output_to_wtypes(&output_type_to_types(descriptor.output_type.as_ref()));
let raw_args = itypes_args_to_wtypes(&argument_types);
let raw_output = itypes_output_to_wtypes(&output_type_to_types(output_type));
let func = move |mut caller: <WB as WasmBackend>::Caller<'_>,
inputs: &[WValue]|
-> Vec<WValue> {
let result = {
let memory_index = 0;
let memory_view = caller.memory(memory_index).unwrap().view(); // todo handle error
let li_helper = LiHelper::new(record_types.clone());
let lifter = ILifter::new(memory_view, &li_helper);
let rets = wvalues_to_ivalues(
&mut caller.as_context_mut(),
&lifter,
inputs,
&argument_types,
);
match rets {
Ok(ivalues) => host_exported_func(&mut caller, ivalues),
Err(e) => {
log::error!("error occurred while lifting values in host import: {}", e);
error_handler
.as_ref()
.map_or_else(|| default_error_handler(&e), |h| h(&e))
}
}
};
init_wasm_func!(
allocate_func,
caller,
(i32, i32),
i32,
ALLOCATE_FUNC_NAME,
2
);
let memory_index = 0;
let memory_view = caller.memory(memory_index).unwrap().view(); // todo handle error
let mut lo_helper = LoHelper::new(&mut allocate_func, caller.memory(memory_index).unwrap()); // todo handle error
let lowering_result =
ILowerer::<'_, _, _, DelayedContextLifetime<WB>>::new(memory_view, &mut lo_helper)
.map_err(HostImportError::LowererError)
.and_then(|mut lowerer| {
ivalue_to_wvalues(&mut caller.as_context_mut(), &mut lowerer, result)
});
let wvalues = match lowering_result {
Ok(wvalues) => wvalues,
Err(e) => {
log::error!("host closure failed: {}", e);
// returns 0 to a Wasm module in case of errors
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 4);
init_wasm_func!(set_result_size_func, caller, i32, (), SET_SIZE_FUNC_NAME, 4);
call_wasm_func!(set_result_ptr_func, &mut caller.as_context_mut(), 0);
call_wasm_func!(set_result_size_func, &mut caller.as_context_mut(), 0);
return vec![WValue::I32(0)];
}
};
// TODO: refactor this when multi-value is supported
match wvalues.len() {
// strings and arrays are passed back to the Wasm module by pointer and size
2 => {
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 4);
init_wasm_func!(set_result_size_func, caller, i32, (), SET_SIZE_FUNC_NAME, 4);
call_wasm_func!(
set_result_ptr_func,
&mut caller.as_context_mut(),
wvalues[0].to_u128() as _
);
call_wasm_func!(
set_result_size_func,
&mut caller.as_context_mut(),
wvalues[1].to_u128() as _
);
vec![]
}
// records and primitive types are passed to the Wasm module by pointer
// and value on the stack
1 => {
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 3);
call_wasm_func!(
set_result_ptr_func,
&mut caller.as_context_mut(),
wvalues[0].to_u128() as _
);
vec![wvalues[0].clone()]
}
// when None is passed
0 => vec![],
// at now while multi-values aren't supported ivalue_to_wvalues returns only Vec with
// 0, 1, 2 values
_ => unimplemented!(),
}
let func = move |caller: <WB as WasmBackend>::Caller<'_>, inputs: &[WValue]| -> Vec<WValue> {
call_host_import(caller, inputs, &descriptor, record_types.clone())
};
<WB as WasmBackend>::Function::new_with_ctx(
@ -169,6 +61,141 @@ pub(crate) fn create_host_import_func<WB: WasmBackend>(
)
}
fn call_host_import<WB: WasmBackend>(
mut caller: <WB as WasmBackend>::Caller<'_>,
inputs: &[WValue],
descriptor: &HostImportDescriptor<WB>,
record_types: Arc<MRecordTypes>,
) -> Vec<WValue> {
let HostImportDescriptor {
host_exported_func,
argument_types,
error_handler,
..
} = descriptor;
let memory_index = 0;
let memory = caller
.memory(memory_index)
.unwrap_or_else(|| panic!("Host import called directly, not from wasm"));
let inputs = lift_inputs::<WB>(&mut caller, memory.clone(), record_types, inputs, &argument_types);
let output = match inputs {
Ok(ivalues) => host_exported_func(&mut caller, ivalues),
Err(e) => {
log::error!("error occurred while lifting values in host import: {}", e);
error_handler
.as_ref()
.map_or_else(|| default_error_handler(&e), |h| h(&e))
}
};
lower_outputs::<WB>(&mut caller, memory, output)
}
fn lift_inputs<WB: WasmBackend>(
caller: &mut <WB as WasmBackend>::Caller<'_>,
memory: <WB as WasmBackend>::Memory,
record_types: Arc<MRecordTypes>,
inputs: &[WValue],
argument_types: &[IType]
) -> HostImportResult<Vec<IValue>> {
let memory_view = memory.view();
let li_helper = LiHelper::new(record_types.clone());
let lifter = ILifter::new(memory_view, &li_helper);
wvalues_to_ivalues(
&mut caller.as_context_mut(),
&lifter,
inputs,
&argument_types,
)
}
fn lower_outputs<WB: WasmBackend>(caller: &mut <WB as WasmBackend>::Caller<'_>,
memory: <WB as WasmBackend>::Memory,
output: Option<IValue>, ) -> Vec<WValue> {
init_wasm_func!(
allocate_func,
caller,
(i32, i32),
i32,
ALLOCATE_FUNC_NAME,
2
);
let memory_view = memory.view();
let mut lo_helper = LoHelper::new(&mut allocate_func, memory.clone());
let lowering_result =
ILowerer::<'_, _, _, DelayedContextLifetime<WB>>::new(memory_view, &mut lo_helper)
.map_err(HostImportError::LowererError)
.and_then(|mut lowerer| {
ivalue_to_wvalues(&mut caller.as_context_mut(), &mut lowerer, output)
});
let wvalues = match lowering_result {
Ok(wvalues) => wvalues,
Err(e) => {
log::error!("host closure failed: {}", e);
// returns 0 to a Wasm module in case of errors
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 4);
init_wasm_func!(set_result_size_func, caller, i32, (), SET_SIZE_FUNC_NAME, 4);
call_wasm_func!(set_result_ptr_func, &mut caller.as_context_mut(), 0);
call_wasm_func!(set_result_size_func, &mut caller.as_context_mut(), 0);
return vec![WValue::I32(0)];
}
};
// TODO: refactor this when multi-value is supported
match wvalues.len() {
// strings and arrays are passed back to the Wasm module by pointer and size
2 => {
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 4);
init_wasm_func!(set_result_size_func, caller, i32, (), SET_SIZE_FUNC_NAME, 4);
call_wasm_func!(
set_result_ptr_func,
&mut caller.as_context_mut(),
wvalues[0].to_u128() as _
);
call_wasm_func!(
set_result_size_func,
&mut caller.as_context_mut(),
wvalues[1].to_u128() as _
);
vec![]
}
// records and primitive types are passed to the Wasm module by pointer
// and value on the stack
1 => {
init_wasm_func!(set_result_ptr_func, caller, i32, (), SET_PTR_FUNC_NAME, 3);
call_wasm_func!(
set_result_ptr_func,
&mut caller.as_context_mut(),
wvalues[0].to_u128() as _
);
vec![wvalues[0].clone()]
}
// when None is passed
0 => vec![],
// at now while multi-values aren't supported ivalue_to_wvalues returns only Vec with
// 0, 1, 2 values
_ => unimplemented!(),
}
}
fn output_type_to_types(output_type: Option<&IType>) -> Vec<IType>{
match output_type {
Some(ty) => vec![ty.clone()],
None => vec![],
}
}
fn default_error_handler(err: &HostImportError) -> Option<crate::IValue> {
panic!(
"an error is occurred while lifting values to interface values: {}",

@ -169,4 +169,4 @@ macro_rules! impl_func_construction {
impl FuncConstructor<WasmtimeWasmBackend> for WasmtimeFunction {
impl_for_each_function_signature!(impl_func_construction);
}
}

@ -26,7 +26,7 @@ use crate::host_imports::logger::LoggerFilter;
use crate::host_imports::logger::WASM_LOG_ENV_NAME;
use crate::json_to_marine_err;
use marine_wasm_backend_traits::WasmB ackend;
use marine_wasm_backend_traits::WasmBackend;
use marine_core::MarineCore;
use marine_core::IFunctionArg;