Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft : optimise PassByCodec usage in runtime interfaces. #36

Open
wants to merge 1 commit into
base: gear-polkadot-v0.9.41-canary
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/executor/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! A set of common definitions that are needed for defining execution engines.

#![warn(missing_docs)]
#![deny(unused_crate_dependencies)]
// #![deny(unused_crate_dependencies)]

pub mod error;
pub mod runtime_blob;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ fn generate_extern_host_function(
},
};

// Generate nested using_ffi_value calls and a call to the extern function
let mut nested_calls = quote! { unsafe { #ext_function( #( #arg_names3 ),* ) } };
for (arg_name, arg_type) in arg_names2.zip(arg_types2) {
nested_calls = quote! { <#arg_type as #crate_::wasm::IntoFFIValue>::using_ffi_value(&#arg_name, |#arg_name| { #nested_calls }) };
}

Ok(quote! {
#[doc = #doc_string]
pub fn #function ( #( #args ),* ) #return_value {
Expand All @@ -121,14 +127,7 @@ fn generate_extern_host_function(
) #ffi_return_value;
}

// Generate all wrapped ffi values.
#(
let #arg_names2 = <#arg_types2 as #crate_::wasm::IntoFFIValue>::into_ffi_value(
&#arg_names2,
);
)*

let result = unsafe { #ext_function( #( #arg_names3.get() ),* ) };
let result = #nested_calls;

#convert_return_value
}
Expand Down
19 changes: 19 additions & 0 deletions primitives/runtime-interface/src/pass_by.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ pub trait PassByImpl<T>: RIType {
/// For more information see: [`crate::wasm::IntoFFIValue::into_ffi_value`]
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned>;

/// Run `f` with provided ffi value and `_owned` living on stack.
fn using_ffi_value<R, F: FnOnce(Self::FFIType) -> R>(instance: &T, f: F) -> R {
match Self::into_ffi_value(instance) {
WrappedFFIValue::Wrapped(x) => f(x),
WrappedFFIValue::WrappedAndOwned(ffi, _owned) => f(ffi),
}
}

/// Create `T` from the given ffi value.
///
/// For more information see: [`crate::wasm::FromFFIValue::from_ffi_value`]
Expand Down Expand Up @@ -186,6 +194,10 @@ impl<T: PassBy> IntoFFIValue for T {
fn into_ffi_value(&self) -> WrappedFFIValue<<T::PassBy as RIType>::FFIType, Self::Owned> {
T::PassBy::into_ffi_value(self)
}

fn using_ffi_value<R, F: FnOnce(Self::FFIType) -> R>(&self, f: F) -> R {
T::PassBy::using_ffi_value(self, f)
}
}

#[cfg(not(feature = "std"))]
Expand Down Expand Up @@ -243,6 +255,13 @@ impl<T: codec::Codec> PassByImpl<T> for Codec<T> {
(ffi_value, data).into()
}

fn using_ffi_value<R, F: FnOnce(Self::FFIType) -> R>(instance: &T, f: F) -> R {
instance.using_encoded(|data| {
let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
f(ffi_value)
})
}

fn from_ffi_value(arg: Self::FFIType) -> T {
let (ptr, len) = unpack_ptr_and_len(arg);
let len = len as usize;
Expand Down
8 changes: 8 additions & 0 deletions primitives/runtime-interface/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ pub trait IntoFFIValue: RIType {

/// Convert `self` into a [`WrappedFFIValue`].
fn into_ffi_value(&self) -> WrappedFFIValue<Self::FFIType, Self::Owned>;

/// Run `f` with provided ffi value and `_owned` living on stack.
fn using_ffi_value<R, F: FnOnce(Self::FFIType) -> R>(&self, f: F) -> R {
match Self::into_ffi_value(self) {
WrappedFFIValue::Wrapped(x) => f(x),
WrappedFFIValue::WrappedAndOwned(ffi, _owned) => f(ffi),
}
}
}

/// Represents a wrapped ffi value.
Expand Down
54 changes: 53 additions & 1 deletion primitives/wasm-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl TryFrom<u8> for ValueType {
}

/// Values supported by Substrate on the boundary between host/Wasm.
#[derive(PartialEq, Debug, Clone, Copy, codec::Encode, codec::Decode)]
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Value {
/// A 32-bit integer.
I32(i32),
Expand All @@ -107,6 +107,58 @@ pub enum Value {
F64(u64),
}

impl codec::Encode for Value {
fn size_hint(&self) -> usize {
match self {
Value::I32(_) => 5,
Value::I64(_) => 9,
Value::F32(_) => 5,
Value::F64(_) => 9,
}
}

fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
match self {
Value::I32(x) => {
let mut data = [0u8, 0, 0, 0, 0];
data[1..].copy_from_slice(&x.to_le_bytes());
f(&data)
},
Value::I64(x) => {
let mut data = [1u8, 0, 0, 0, 0, 0, 0, 0, 0];
data[1..].copy_from_slice(&x.to_le_bytes());
f(&data)
},
Value::F32(x) => {
let mut data = [2u8, 0, 0, 0, 0];
data[1..].copy_from_slice(&x.to_le_bytes());
f(&data)
},
Value::F64(x) => {
let mut data = [3u8, 0, 0, 0, 0, 0, 0, 0, 0];
data[1..].copy_from_slice(&x.to_le_bytes());
f(&data)
},
}
}

fn encoded_size(&self) -> usize {
self.size_hint()
}
}

impl codec::Decode for Value {
fn decode<I: codec::Input>(input: &mut I) -> result::Result<Self, codec::Error> {
match input.read_byte()? {
0 => Ok(Value::I32(<i32>::decode(input)?)),
1 => Ok(Value::I64(<i64>::decode(input)?)),
2 => Ok(Value::F32(<u32>::decode(input)?)),
3 => Ok(Value::F64(<u64>::decode(input)?)),
_ => Err("Could not decode `Value`, variant doesn't exist".into()),
}
}
}

impl Value {
/// Returns the type of this value.
pub fn value_type(&self) -> ValueType {
Expand Down