mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 18:07:58 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -19,16 +19,17 @@
|
||||
//! This module defines `HostState` and `HostContext` structs which provide logic and state
|
||||
//! required for execution of host.
|
||||
|
||||
use crate::instance_wrapper::InstanceWrapper;
|
||||
use crate::util;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use crate::{instance_wrapper::InstanceWrapper, util};
|
||||
use codec::{Decode, Encode};
|
||||
use log::trace;
|
||||
use codec::{Encode, Decode};
|
||||
use sc_allocator::FreeingBumpHeapAllocator;
|
||||
use sc_executor_common::error::Result;
|
||||
use sc_executor_common::sandbox::{self, SandboxCapabilities, SupervisorFuncIndex};
|
||||
use sc_executor_common::{
|
||||
error::Result,
|
||||
sandbox::{self, SandboxCapabilities, SupervisorFuncIndex},
|
||||
};
|
||||
use sp_core::sandbox as sandbox_primitives;
|
||||
use sp_wasm_interface::{FunctionContext, MemoryId, Pointer, Sandbox, WordSize};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use wasmtime::{Func, Val};
|
||||
|
||||
/// Wrapper type for pointer to a Wasm table entry.
|
||||
@@ -108,7 +109,7 @@ impl<'a> SandboxCapabilities for HostContext<'a> {
|
||||
"Supervisor function returned {} results, expected 1",
|
||||
ret_vals.len()
|
||||
)
|
||||
.into());
|
||||
.into())
|
||||
} else {
|
||||
&ret_vals[0]
|
||||
};
|
||||
@@ -116,9 +117,9 @@ impl<'a> SandboxCapabilities for HostContext<'a> {
|
||||
if let Some(ret_val) = ret_val.i64() {
|
||||
Ok(ret_val)
|
||||
} else {
|
||||
return Err("Supervisor function returned unexpected result!".into());
|
||||
return Err("Supervisor function returned unexpected result!".into())
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => Err(err.to_string().into()),
|
||||
}
|
||||
}
|
||||
@@ -130,15 +131,11 @@ impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
|
||||
address: Pointer<u8>,
|
||||
dest: &mut [u8],
|
||||
) -> sp_wasm_interface::Result<()> {
|
||||
self.instance
|
||||
.read_memory_into(address, dest)
|
||||
.map_err(|e| e.to_string())
|
||||
self.instance.read_memory_into(address, dest).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn write_memory(&mut self, address: Pointer<u8>, data: &[u8]) -> sp_wasm_interface::Result<()> {
|
||||
self.instance
|
||||
.write_memory_from(address, data)
|
||||
.map_err(|e| e.to_string())
|
||||
self.instance.write_memory_from(address, data).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result<Pointer<u8>> {
|
||||
@@ -166,11 +163,8 @@ impl<'a> Sandbox for HostContext<'a> {
|
||||
buf_ptr: Pointer<u8>,
|
||||
buf_len: WordSize,
|
||||
) -> sp_wasm_interface::Result<u32> {
|
||||
let sandboxed_memory = self
|
||||
.sandbox_store
|
||||
.borrow()
|
||||
.memory(memory_id)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let sandboxed_memory =
|
||||
self.sandbox_store.borrow().memory(memory_id).map_err(|e| e.to_string())?;
|
||||
sandboxed_memory.with_direct_access(|sandboxed_memory| {
|
||||
let len = buf_len as usize;
|
||||
let src_range = match util::checked_range(offset as usize, len, sandboxed_memory.len())
|
||||
@@ -200,11 +194,8 @@ impl<'a> Sandbox for HostContext<'a> {
|
||||
val_ptr: Pointer<u8>,
|
||||
val_len: WordSize,
|
||||
) -> sp_wasm_interface::Result<u32> {
|
||||
let sandboxed_memory = self
|
||||
.sandbox_store
|
||||
.borrow()
|
||||
.memory(memory_id)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let sandboxed_memory =
|
||||
self.sandbox_store.borrow().memory(memory_id).map_err(|e| e.to_string())?;
|
||||
sandboxed_memory.with_direct_access_mut(|sandboxed_memory| {
|
||||
let len = val_len as usize;
|
||||
let supervisor_mem_size = self.instance.memory_size() as usize;
|
||||
@@ -259,11 +250,8 @@ impl<'a> Sandbox for HostContext<'a> {
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let instance = self
|
||||
.sandbox_store
|
||||
.borrow()
|
||||
.instance(instance_id)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let instance =
|
||||
self.sandbox_store.borrow().instance(instance_id).map_err(|e| e.to_string())?;
|
||||
let result = instance.invoke(export_name, &args, self, state);
|
||||
|
||||
match result {
|
||||
@@ -278,7 +266,7 @@ impl<'a> Sandbox for HostContext<'a> {
|
||||
.map_err(|_| "can't write return value")?;
|
||||
Ok(sandbox_primitives::ERR_OK)
|
||||
})
|
||||
}
|
||||
},
|
||||
Err(_) => Ok(sandbox_primitives::ERR_EXECUTION),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ use sc_executor_common::error::WasmError;
|
||||
use sp_wasm_interface::{Function, ValueType};
|
||||
use std::any::Any;
|
||||
use wasmtime::{
|
||||
Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module,
|
||||
Trap, Val, Store,
|
||||
Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, Store,
|
||||
Trap, Val,
|
||||
};
|
||||
|
||||
pub struct Imports {
|
||||
@@ -51,36 +51,29 @@ pub fn resolve_imports(
|
||||
"host doesn't provide any imports from non-env module: {}:{}",
|
||||
import_ty.module(),
|
||||
name,
|
||||
)));
|
||||
)))
|
||||
}
|
||||
|
||||
let resolved = match name {
|
||||
"memory" => {
|
||||
memory_import_index = Some(externs.len());
|
||||
resolve_memory_import(store, &import_ty, heap_pages)?
|
||||
}
|
||||
_ => resolve_func_import(
|
||||
store,
|
||||
&import_ty,
|
||||
host_functions,
|
||||
allow_missing_func_imports,
|
||||
)?,
|
||||
},
|
||||
_ =>
|
||||
resolve_func_import(store, &import_ty, host_functions, allow_missing_func_imports)?,
|
||||
};
|
||||
externs.push(resolved);
|
||||
}
|
||||
Ok(Imports {
|
||||
memory_import_index,
|
||||
externs,
|
||||
})
|
||||
Ok(Imports { memory_import_index, externs })
|
||||
}
|
||||
|
||||
/// When the module linking proposal is supported the import's name can be `None`.
|
||||
/// Because we are not using this proposal we could safely unwrap the name.
|
||||
/// However, we opt for an error in order to avoid panics at all costs.
|
||||
fn import_name<'a, 'b: 'a>(import: &'a ImportType<'b>) -> Result<&'a str, WasmError> {
|
||||
let name = import.name().ok_or_else(||
|
||||
let name = import.name().ok_or_else(|| {
|
||||
WasmError::Other("The module linking proposal is not supported.".to_owned())
|
||||
)?;
|
||||
})?;
|
||||
Ok(name)
|
||||
}
|
||||
|
||||
@@ -91,21 +84,17 @@ fn resolve_memory_import(
|
||||
) -> Result<Extern, WasmError> {
|
||||
let requested_memory_ty = match import_ty.ty() {
|
||||
ExternType::Memory(memory_ty) => memory_ty,
|
||||
_ => {
|
||||
_ =>
|
||||
return Err(WasmError::Other(format!(
|
||||
"this import must be of memory type: {}:{}",
|
||||
import_ty.module(),
|
||||
import_name(&import_ty)?,
|
||||
)))
|
||||
}
|
||||
))),
|
||||
};
|
||||
|
||||
// Increment the min (a.k.a initial) number of pages by `heap_pages` and check if it exceeds the
|
||||
// maximum specified by the import.
|
||||
let initial = requested_memory_ty
|
||||
.limits()
|
||||
.min()
|
||||
.saturating_add(heap_pages);
|
||||
let initial = requested_memory_ty.limits().min().saturating_add(heap_pages);
|
||||
if let Some(max) = requested_memory_ty.limits().max() {
|
||||
if initial > max {
|
||||
return Err(WasmError::Other(format!(
|
||||
@@ -113,7 +102,7 @@ fn resolve_memory_import(
|
||||
by the runtime wasm module {}",
|
||||
initial,
|
||||
max,
|
||||
)));
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,37 +126,31 @@ fn resolve_func_import(
|
||||
|
||||
let func_ty = match import_ty.ty() {
|
||||
ExternType::Func(func_ty) => func_ty,
|
||||
_ => {
|
||||
_ =>
|
||||
return Err(WasmError::Other(format!(
|
||||
"host doesn't provide any non function imports besides 'memory': {}:{}",
|
||||
import_ty.module(),
|
||||
name,
|
||||
)));
|
||||
}
|
||||
))),
|
||||
};
|
||||
|
||||
let host_func = match host_functions
|
||||
.iter()
|
||||
.find(|host_func| host_func.name() == name)
|
||||
{
|
||||
let host_func = match host_functions.iter().find(|host_func| host_func.name() == name) {
|
||||
Some(host_func) => host_func,
|
||||
None if allow_missing_func_imports => {
|
||||
return Ok(MissingHostFuncHandler::new(import_ty)?.into_extern(store, &func_ty));
|
||||
}
|
||||
None => {
|
||||
None if allow_missing_func_imports =>
|
||||
return Ok(MissingHostFuncHandler::new(import_ty)?.into_extern(store, &func_ty)),
|
||||
None =>
|
||||
return Err(WasmError::Other(format!(
|
||||
"host doesn't provide such function: {}:{}",
|
||||
import_ty.module(),
|
||||
name,
|
||||
)));
|
||||
}
|
||||
))),
|
||||
};
|
||||
if &func_ty != &wasmtime_func_sig(*host_func) {
|
||||
return Err(WasmError::Other(format!(
|
||||
"signature mismatch for: {}:{}",
|
||||
import_ty.module(),
|
||||
name,
|
||||
)));
|
||||
)))
|
||||
}
|
||||
|
||||
Ok(HostFuncHandler::new(*host_func).into_extern(store))
|
||||
@@ -218,7 +201,7 @@ fn call_static(
|
||||
);
|
||||
wasmtime_results[0] = util::into_wasmtime_val(ret_val);
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
debug_assert!(
|
||||
wasmtime_results.len() == 0,
|
||||
@@ -226,26 +209,22 @@ fn call_static(
|
||||
correspond to the number of results returned by the host function",
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
Err(msg) => Err(Trap::new(msg)),
|
||||
}
|
||||
}
|
||||
|
||||
impl HostFuncHandler {
|
||||
fn new(host_func: &'static dyn Function) -> Self {
|
||||
Self {
|
||||
host_func,
|
||||
}
|
||||
Self { host_func }
|
||||
}
|
||||
|
||||
fn into_extern(self, store: &Store) -> Extern {
|
||||
let host_func = self.host_func;
|
||||
let func_ty = wasmtime_func_sig(self.host_func);
|
||||
let func = Func::new(store, func_ty,
|
||||
move |_, params, result| {
|
||||
call_static(host_func, params, result)
|
||||
}
|
||||
);
|
||||
let func = Func::new(store, func_ty, move |_, params, result| {
|
||||
call_static(host_func, params, result)
|
||||
});
|
||||
Extern::Func(func)
|
||||
}
|
||||
}
|
||||
@@ -266,28 +245,17 @@ impl MissingHostFuncHandler {
|
||||
|
||||
fn into_extern(self, store: &Store, func_ty: &FuncType) -> Extern {
|
||||
let Self { module, name } = self;
|
||||
let func = Func::new(store, func_ty.clone(),
|
||||
move |_, _, _| Err(Trap::new(format!(
|
||||
"call to a missing function {}:{}",
|
||||
module, name
|
||||
)))
|
||||
);
|
||||
let func = Func::new(store, func_ty.clone(), move |_, _, _| {
|
||||
Err(Trap::new(format!("call to a missing function {}:{}", module, name)))
|
||||
});
|
||||
Extern::Func(func)
|
||||
}
|
||||
}
|
||||
|
||||
fn wasmtime_func_sig(func: &dyn Function) -> wasmtime::FuncType {
|
||||
let signature = func.signature();
|
||||
let params = signature
|
||||
.args
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(into_wasmtime_val_type);
|
||||
let results = signature
|
||||
.return_value
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(into_wasmtime_val_type);
|
||||
let params = signature.args.iter().cloned().map(into_wasmtime_val_type);
|
||||
let results = signature.return_value.iter().cloned().map(into_wasmtime_val_type);
|
||||
wasmtime::FuncType::new(params, results)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,26 +19,23 @@
|
||||
//! Defines data and logic needed for interaction with an WebAssembly instance of a substrate
|
||||
//! runtime module.
|
||||
|
||||
use crate::util;
|
||||
use crate::imports::Imports;
|
||||
use crate::{imports::Imports, util};
|
||||
|
||||
use std::{slice, marker};
|
||||
use sc_executor_common::{
|
||||
error::{Error, Result},
|
||||
runtime_blob,
|
||||
wasm_runtime::InvokeMethod,
|
||||
};
|
||||
use sp_wasm_interface::{Pointer, WordSize, Value};
|
||||
use wasmtime::{Instance, Module, Memory, Table, Val, Func, Extern, Global, Store};
|
||||
use sp_wasm_interface::{Pointer, Value, WordSize};
|
||||
use std::{marker, slice};
|
||||
use wasmtime::{Extern, Func, Global, Instance, Memory, Module, Store, Table, Val};
|
||||
|
||||
/// Invoked entrypoint format.
|
||||
pub enum EntryPointType {
|
||||
/// Direct call.
|
||||
///
|
||||
/// Call is made by providing only payload reference and length.
|
||||
Direct {
|
||||
entrypoint: wasmtime::TypedFunc<(u32, u32), u64>,
|
||||
},
|
||||
Direct { entrypoint: wasmtime::TypedFunc<(u32, u32), u64> },
|
||||
/// Indirect call.
|
||||
///
|
||||
/// Call is made by providing payload reference and length, and extra argument
|
||||
@@ -66,17 +63,10 @@ impl EntryPoint {
|
||||
}
|
||||
|
||||
match self.call_type {
|
||||
EntryPointType::Direct { ref entrypoint } => {
|
||||
entrypoint.call((data_ptr, data_len)).map_err(handle_trap)
|
||||
}
|
||||
EntryPointType::Wrapped {
|
||||
func,
|
||||
ref dispatcher,
|
||||
} => {
|
||||
dispatcher
|
||||
.call((func, data_ptr, data_len))
|
||||
.map_err(handle_trap)
|
||||
}
|
||||
EntryPointType::Direct { ref entrypoint } =>
|
||||
entrypoint.call((data_ptr, data_len)).map_err(handle_trap),
|
||||
EntryPointType::Wrapped { func, ref dispatcher } =>
|
||||
dispatcher.call((func, data_ptr, data_len)).map_err(handle_trap),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +75,7 @@ impl EntryPoint {
|
||||
.typed::<(u32, u32), u64>()
|
||||
.map_err(|_| "Invalid signature for direct entry point")?
|
||||
.clone();
|
||||
Ok(Self {
|
||||
call_type: EntryPointType::Direct { entrypoint },
|
||||
})
|
||||
Ok(Self { call_type: EntryPointType::Direct { entrypoint } })
|
||||
}
|
||||
|
||||
pub fn wrapped(
|
||||
@@ -98,9 +86,7 @@ impl EntryPoint {
|
||||
.typed::<(u32, u32, u32), u64>()
|
||||
.map_err(|_| "Invalid signature for wrapped entry point")?
|
||||
.clone();
|
||||
Ok(Self {
|
||||
call_type: EntryPointType::Wrapped { func, dispatcher },
|
||||
})
|
||||
Ok(Self { call_type: EntryPointType::Wrapped { func, dispatcher } })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +113,6 @@ fn extern_memory(extern_: &Extern) -> Option<&Memory> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn extern_global(extern_: &Extern) -> Option<&Global> {
|
||||
match extern_ {
|
||||
Extern::Global(glob) => Some(glob),
|
||||
@@ -156,15 +141,13 @@ impl InstanceWrapper {
|
||||
.map_err(|e| Error::from(format!("cannot instantiate: {}", e)))?;
|
||||
|
||||
let memory = match imports.memory_import_index {
|
||||
Some(memory_idx) => {
|
||||
extern_memory(&imports.externs[memory_idx])
|
||||
.expect("only memory can be at the `memory_idx`; qed")
|
||||
.clone()
|
||||
}
|
||||
Some(memory_idx) => extern_memory(&imports.externs[memory_idx])
|
||||
.expect("only memory can be at the `memory_idx`; qed")
|
||||
.clone(),
|
||||
None => {
|
||||
let memory = get_linear_memory(&instance)?;
|
||||
if !memory.grow(heap_pages).is_ok() {
|
||||
return Err("failed top increase the linear memory size".into());
|
||||
return Err("failed top increase the linear memory size".into())
|
||||
}
|
||||
memory
|
||||
},
|
||||
@@ -186,42 +169,38 @@ impl InstanceWrapper {
|
||||
Ok(match method {
|
||||
InvokeMethod::Export(method) => {
|
||||
// Resolve the requested method and verify that it has a proper signature.
|
||||
let export = self
|
||||
.instance
|
||||
.get_export(method)
|
||||
.ok_or_else(|| Error::from(format!("Exported method {} is not found", method)))?;
|
||||
let export = self.instance.get_export(method).ok_or_else(|| {
|
||||
Error::from(format!("Exported method {} is not found", method))
|
||||
})?;
|
||||
let func = extern_func(&export)
|
||||
.ok_or_else(|| Error::from(format!("Export {} is not a function", method)))?
|
||||
.clone();
|
||||
EntryPoint::direct(func)
|
||||
.map_err(|_|
|
||||
Error::from(format!(
|
||||
"Exported function '{}' has invalid signature.",
|
||||
method,
|
||||
))
|
||||
)?
|
||||
EntryPoint::direct(func).map_err(|_| {
|
||||
Error::from(format!("Exported function '{}' has invalid signature.", method,))
|
||||
})?
|
||||
},
|
||||
InvokeMethod::Table(func_ref) => {
|
||||
let table = self.instance.get_table("__indirect_function_table").ok_or(Error::NoTable)?;
|
||||
let val = table.get(func_ref)
|
||||
.ok_or(Error::NoTableEntryWithIndex(func_ref))?;
|
||||
let table =
|
||||
self.instance.get_table("__indirect_function_table").ok_or(Error::NoTable)?;
|
||||
let val = table.get(func_ref).ok_or(Error::NoTableEntryWithIndex(func_ref))?;
|
||||
let func = val
|
||||
.funcref()
|
||||
.ok_or(Error::TableElementIsNotAFunction(func_ref))?
|
||||
.ok_or(Error::FunctionRefIsNull(func_ref))?
|
||||
.clone();
|
||||
|
||||
EntryPoint::direct(func)
|
||||
.map_err(|_|
|
||||
Error::from(format!(
|
||||
"Function @{} in exported table has invalid signature for direct call.",
|
||||
func_ref,
|
||||
))
|
||||
)?
|
||||
},
|
||||
EntryPoint::direct(func).map_err(|_| {
|
||||
Error::from(format!(
|
||||
"Function @{} in exported table has invalid signature for direct call.",
|
||||
func_ref,
|
||||
))
|
||||
})?
|
||||
},
|
||||
InvokeMethod::TableWithWrapper { dispatcher_ref, func } => {
|
||||
let table = self.instance.get_table("__indirect_function_table").ok_or(Error::NoTable)?;
|
||||
let val = table.get(dispatcher_ref)
|
||||
let table =
|
||||
self.instance.get_table("__indirect_function_table").ok_or(Error::NoTable)?;
|
||||
let val = table
|
||||
.get(dispatcher_ref)
|
||||
.ok_or(Error::NoTableEntryWithIndex(dispatcher_ref))?;
|
||||
let dispatcher = val
|
||||
.funcref()
|
||||
@@ -229,13 +208,12 @@ impl InstanceWrapper {
|
||||
.ok_or(Error::FunctionRefIsNull(dispatcher_ref))?
|
||||
.clone();
|
||||
|
||||
EntryPoint::wrapped(dispatcher, func)
|
||||
.map_err(|_|
|
||||
Error::from(format!(
|
||||
"Function @{} in exported table has invalid signature for wrapped call.",
|
||||
dispatcher_ref,
|
||||
))
|
||||
)?
|
||||
EntryPoint::wrapped(dispatcher, func).map_err(|_| {
|
||||
Error::from(format!(
|
||||
"Function @{} in exported table has invalid signature for wrapped call.",
|
||||
dispatcher_ref,
|
||||
))
|
||||
})?
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -426,7 +404,7 @@ impl InstanceWrapper {
|
||||
/// relied upon. Thus this function acts as a hint.
|
||||
pub fn decommit(&self) {
|
||||
if self.memory.data_size() == 0 {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
///! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute.
|
||||
/// ! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute.
|
||||
mod host;
|
||||
mod imports;
|
||||
mod instance_wrapper;
|
||||
@@ -28,6 +28,6 @@ mod util;
|
||||
mod tests;
|
||||
|
||||
pub use runtime::{
|
||||
create_runtime, create_runtime_from_artifact, prepare_runtime_artifact, Config, Semantics,
|
||||
DeterministicStackLimit,
|
||||
create_runtime, create_runtime_from_artifact, prepare_runtime_artifact, Config,
|
||||
DeterministicStackLimit, Semantics,
|
||||
};
|
||||
|
||||
@@ -18,22 +18,26 @@
|
||||
|
||||
//! Defines the compiled Wasm runtime that uses Wasmtime internally.
|
||||
|
||||
use crate::host::HostState;
|
||||
use crate::imports::{Imports, resolve_imports};
|
||||
use crate::instance_wrapper::{InstanceWrapper, EntryPoint};
|
||||
use crate::state_holder;
|
||||
use crate::{
|
||||
host::HostState,
|
||||
imports::{resolve_imports, Imports},
|
||||
instance_wrapper::{EntryPoint, InstanceWrapper},
|
||||
state_holder,
|
||||
};
|
||||
|
||||
use std::{path::PathBuf, rc::Rc};
|
||||
use std::sync::Arc;
|
||||
use std::path::Path;
|
||||
use sc_allocator::FreeingBumpHeapAllocator;
|
||||
use sc_executor_common::{
|
||||
error::{Result, WasmError},
|
||||
runtime_blob::{DataSegmentsSnapshot, ExposedMutableGlobalsSet, GlobalsSnapshot, RuntimeBlob},
|
||||
wasm_runtime::{WasmModule, WasmInstance, InvokeMethod},
|
||||
wasm_runtime::{InvokeMethod, WasmInstance, WasmModule},
|
||||
};
|
||||
use sc_allocator::FreeingBumpHeapAllocator;
|
||||
use sp_runtime_interface::unpack_ptr_and_len;
|
||||
use sp_wasm_interface::{Function, Pointer, WordSize, Value};
|
||||
use sp_wasm_interface::{Function, Pointer, Value, WordSize};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
use wasmtime::{Engine, Store};
|
||||
|
||||
enum Strategy {
|
||||
@@ -102,7 +106,8 @@ impl WasmModule for WasmtimeRuntime {
|
||||
// the mutable globals were collected. Here, it is easy to see that there is only a single
|
||||
// runtime blob and thus it's the same that was used for both creating the instance and
|
||||
// collecting the mutable globals.
|
||||
let globals_snapshot = GlobalsSnapshot::take(&snapshot_data.mutable_globals, &instance_wrapper);
|
||||
let globals_snapshot =
|
||||
GlobalsSnapshot::take(&snapshot_data.mutable_globals, &instance_wrapper);
|
||||
|
||||
Strategy::FastInstanceReuse {
|
||||
instance_wrapper: Rc::new(instance_wrapper),
|
||||
@@ -150,14 +155,15 @@ impl WasmInstance for WasmtimeInstance {
|
||||
globals_snapshot.apply(&**instance_wrapper);
|
||||
let allocator = FreeingBumpHeapAllocator::new(*heap_base);
|
||||
|
||||
let result = perform_call(data, Rc::clone(&instance_wrapper), entrypoint, allocator);
|
||||
let result =
|
||||
perform_call(data, Rc::clone(&instance_wrapper), entrypoint, allocator);
|
||||
|
||||
// Signal to the OS that we are done with the linear memory and that it can be
|
||||
// reclaimed.
|
||||
instance_wrapper.decommit();
|
||||
|
||||
result
|
||||
}
|
||||
},
|
||||
Strategy::RecreateInstance(instance_creator) => {
|
||||
let instance_wrapper = instance_creator.instantiate()?;
|
||||
let heap_base = instance_wrapper.extract_heap_base()?;
|
||||
@@ -165,18 +171,16 @@ impl WasmInstance for WasmtimeInstance {
|
||||
|
||||
let allocator = FreeingBumpHeapAllocator::new(heap_base);
|
||||
perform_call(data, Rc::new(instance_wrapper), entrypoint, allocator)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn get_global_const(&self, name: &str) -> Result<Option<Value>> {
|
||||
match &self.strategy {
|
||||
Strategy::FastInstanceReuse {
|
||||
instance_wrapper, ..
|
||||
} => instance_wrapper.get_global_val(name),
|
||||
Strategy::RecreateInstance(instance_creator) => {
|
||||
instance_creator.instantiate()?.get_global_val(name)
|
||||
}
|
||||
Strategy::FastInstanceReuse { instance_wrapper, .. } =>
|
||||
instance_wrapper.get_global_val(name),
|
||||
Strategy::RecreateInstance(instance_creator) =>
|
||||
instance_creator.instantiate()?.get_global_val(name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,10 +190,9 @@ impl WasmInstance for WasmtimeInstance {
|
||||
// We do not keep the wasm instance around, therefore there is no linear memory
|
||||
// associated with it.
|
||||
None
|
||||
}
|
||||
Strategy::FastInstanceReuse {
|
||||
instance_wrapper, ..
|
||||
} => Some(instance_wrapper.base_ptr()),
|
||||
},
|
||||
Strategy::FastInstanceReuse { instance_wrapper, .. } =>
|
||||
Some(instance_wrapper.base_ptr()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,9 +240,8 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
|
||||
config.cranelift_opt_level(wasmtime::OptLevel::SpeedAndSize);
|
||||
config.cranelift_nan_canonicalization(semantics.canonicalize_nans);
|
||||
|
||||
if let Some(DeterministicStackLimit {
|
||||
native_stack_max, ..
|
||||
}) = semantics.deterministic_stack_limit
|
||||
if let Some(DeterministicStackLimit { native_stack_max, .. }) =
|
||||
semantics.deterministic_stack_limit
|
||||
{
|
||||
config
|
||||
.max_wasm_stack(native_stack_max as usize)
|
||||
@@ -411,11 +413,7 @@ pub unsafe fn create_runtime_from_artifact(
|
||||
config: Config,
|
||||
host_functions: Vec<&'static dyn Function>,
|
||||
) -> std::result::Result<WasmtimeRuntime, WasmError> {
|
||||
do_create_runtime(
|
||||
CodeSupplyMode::Artifact { compiled_artifact },
|
||||
config,
|
||||
host_functions,
|
||||
)
|
||||
do_create_runtime(CodeSupplyMode::Artifact { compiled_artifact }, config, host_functions)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
@@ -456,16 +454,13 @@ unsafe fn do_create_runtime(
|
||||
let module = wasmtime::Module::new(&engine, &blob.serialize())
|
||||
.map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?;
|
||||
|
||||
(module, Some(InstanceSnapshotData {
|
||||
data_segments_snapshot,
|
||||
mutable_globals,
|
||||
}))
|
||||
(module, Some(InstanceSnapshotData { data_segments_snapshot, mutable_globals }))
|
||||
} else {
|
||||
let module = wasmtime::Module::new(&engine, &blob.serialize())
|
||||
.map_err(|e| WasmError::Other(format!("cannot create module: {}", e)))?;
|
||||
(module, None)
|
||||
}
|
||||
}
|
||||
},
|
||||
CodeSupplyMode::Artifact { compiled_artifact } => {
|
||||
// SAFETY: The unsafity of `deserialize` is covered by this function. The
|
||||
// responsibilities to maintain the invariants are passed to the caller.
|
||||
@@ -473,16 +468,10 @@ unsafe fn do_create_runtime(
|
||||
.map_err(|e| WasmError::Other(format!("cannot deserialize module: {}", e)))?;
|
||||
|
||||
(module, None)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Ok(WasmtimeRuntime {
|
||||
module: Arc::new(module),
|
||||
snapshot_data,
|
||||
config,
|
||||
host_functions,
|
||||
engine,
|
||||
})
|
||||
Ok(WasmtimeRuntime { module: Arc::new(module), snapshot_data, config, host_functions, engine })
|
||||
}
|
||||
|
||||
fn instrument(
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use sc_executor_common::{
|
||||
runtime_blob::RuntimeBlob,
|
||||
wasm_runtime::WasmModule,
|
||||
};
|
||||
use codec::{Decode as _, Encode as _};
|
||||
use sc_executor_common::{runtime_blob::RuntimeBlob, wasm_runtime::WasmModule};
|
||||
use sc_runtime_test::wasm_binary_unwrap;
|
||||
use codec::{Encode as _, Decode as _};
|
||||
use std::sync::Arc;
|
||||
|
||||
type HostFunctions = sp_io::SubstrateHostFunctions;
|
||||
@@ -68,7 +65,7 @@ impl RuntimeBuilder {
|
||||
Some(wat) => {
|
||||
wasm = wat::parse_str(wat).unwrap();
|
||||
&wasm
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
RuntimeBlob::uncompress_if_needed(&wasm)
|
||||
@@ -83,21 +80,20 @@ impl RuntimeBuilder {
|
||||
cache_path: None,
|
||||
semantics: crate::Semantics {
|
||||
fast_instance_reuse: self.fast_instance_reuse,
|
||||
deterministic_stack_limit:
|
||||
match self.deterministic_stack {
|
||||
true => Some(crate::DeterministicStackLimit {
|
||||
logical_max: 65536,
|
||||
native_stack_max: 256 * 1024 * 1024,
|
||||
}),
|
||||
false => None,
|
||||
},
|
||||
deterministic_stack_limit: match self.deterministic_stack {
|
||||
true => Some(crate::DeterministicStackLimit {
|
||||
logical_max: 65536,
|
||||
native_stack_max: 256 * 1024 * 1024,
|
||||
}),
|
||||
false => None,
|
||||
},
|
||||
canonicalize_nans: self.canonicalize_nans,
|
||||
},
|
||||
},
|
||||
{
|
||||
use sp_wasm_interface::HostFunctions as _;
|
||||
HostFunctions::host_functions()
|
||||
}
|
||||
},
|
||||
)
|
||||
.expect("cannot create runtime");
|
||||
|
||||
@@ -113,9 +109,7 @@ fn test_nan_canonicalization() {
|
||||
builder.build()
|
||||
};
|
||||
|
||||
let instance = runtime
|
||||
.new_instance()
|
||||
.expect("failed to instantiate a runtime");
|
||||
let instance = runtime.new_instance().expect("failed to instantiate a runtime");
|
||||
|
||||
/// A NaN with canonical payload bits.
|
||||
const CANONICAL_NAN_BITS: u32 = 0x7fc00000;
|
||||
@@ -142,10 +136,7 @@ fn test_nan_canonicalization() {
|
||||
|
||||
let params = (u32::to_le_bytes(ARBITRARY_NAN_BITS), u32::to_le_bytes(1)).encode();
|
||||
let res = {
|
||||
let raw_result = instance.call_export(
|
||||
"test_fp_f32add",
|
||||
¶ms,
|
||||
).unwrap();
|
||||
let raw_result = instance.call_export("test_fp_f32add", ¶ms).unwrap();
|
||||
u32::from_le_bytes(<[u8; 4]>::decode(&mut &raw_result[..]).unwrap())
|
||||
};
|
||||
assert_eq!(res, CANONICAL_NAN_BITS);
|
||||
@@ -161,9 +152,7 @@ fn test_stack_depth_reaching() {
|
||||
builder.deterministic_stack(true);
|
||||
builder.build()
|
||||
};
|
||||
let instance = runtime
|
||||
.new_instance()
|
||||
.expect("failed to instantiate a runtime");
|
||||
let instance = runtime.new_instance().expect("failed to instantiate a runtime");
|
||||
|
||||
let err = instance.call_export("test-many-locals", &[]).unwrap_err();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user