mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 08:47:57 +00:00
Executor: Remove LegacyInstanceReuse strategy (#1486)
It seems the old strategy have been depracted more than one year. So maybe it's time to clean up old strategy for wasm executor. --- polkadot address: 15ouFh2SHpGbHtDPsJ6cXQfes9Cx1gEFnJJsJVqPGzBSTudr --------- Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Koute <koute@users.noreply.github.com>
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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 super::RuntimeBlob;
|
||||
use crate::error::{self, Error};
|
||||
use std::mem;
|
||||
use wasm_instrument::parity_wasm::elements::Instruction;
|
||||
|
||||
/// This is a snapshot of data segments specialzied for a particular instantiation.
|
||||
///
|
||||
/// Note that this assumes that no mutable globals are used.
|
||||
#[derive(Clone)]
|
||||
pub struct DataSegmentsSnapshot {
|
||||
/// The list of data segments represented by (offset, contents).
|
||||
data_segments: Vec<(u32, Vec<u8>)>,
|
||||
}
|
||||
|
||||
impl DataSegmentsSnapshot {
|
||||
/// Create a snapshot from the data segments from the module.
|
||||
pub fn take(module: &RuntimeBlob) -> error::Result<Self> {
|
||||
let data_segments = module
|
||||
.data_segments()
|
||||
.into_iter()
|
||||
.map(|mut segment| {
|
||||
// Just replace contents of the segment since the segments will be discarded later
|
||||
// anyway.
|
||||
let contents = mem::take(segment.value_mut());
|
||||
|
||||
let init_expr = match segment.offset() {
|
||||
Some(offset) => offset.code(),
|
||||
// Return if the segment is passive
|
||||
None => return Err(Error::SharedMemUnsupported),
|
||||
};
|
||||
|
||||
// [op, End]
|
||||
if init_expr.len() != 2 {
|
||||
return Err(Error::InitializerHasTooManyExpressions)
|
||||
}
|
||||
let offset = match &init_expr[0] {
|
||||
Instruction::I32Const(v) => *v as u32,
|
||||
Instruction::GetGlobal(_) => {
|
||||
// In a valid wasm file, initializer expressions can only refer imported
|
||||
// globals.
|
||||
//
|
||||
// At the moment of writing the Substrate Runtime Interface does not provide
|
||||
// any globals. There is nothing that prevents us from supporting this
|
||||
// if/when we gain those.
|
||||
return Err(Error::ImportedGlobalsUnsupported)
|
||||
},
|
||||
insn => return Err(Error::InvalidInitializerExpression(format!("{:?}", insn))),
|
||||
};
|
||||
|
||||
Ok((offset, contents))
|
||||
})
|
||||
.collect::<error::Result<Vec<_>>>()?;
|
||||
|
||||
Ok(Self { data_segments })
|
||||
}
|
||||
|
||||
/// Apply the given snapshot to a linear memory.
|
||||
///
|
||||
/// Linear memory interface is represented by a closure `memory_set`.
|
||||
pub fn apply<E>(
|
||||
&self,
|
||||
mut memory_set: impl FnMut(u32, &[u8]) -> Result<(), E>,
|
||||
) -> Result<(), E> {
|
||||
for (offset, contents) in &self.data_segments {
|
||||
memory_set(*offset, contents)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// 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 super::RuntimeBlob;
|
||||
|
||||
/// Saved value of particular exported global.
|
||||
struct SavedValue<Global> {
|
||||
/// The handle of this global which can be used to refer to this global.
|
||||
handle: Global,
|
||||
/// The global value that was observed during the snapshot creation.
|
||||
value: sp_wasm_interface::Value,
|
||||
}
|
||||
|
||||
/// An adapter for a wasm module instance that is focused on getting and setting globals.
|
||||
pub trait InstanceGlobals {
|
||||
/// A handle to a global which can be used to get or set a global variable. This is supposed to
|
||||
/// be a lightweight handle, like an index or an Rc-like smart-pointer, which is cheap to clone.
|
||||
type Global: Clone;
|
||||
/// Get a handle to a global by it's export name.
|
||||
///
|
||||
/// The requested export is must exist in the exported list, and it should be a mutable global.
|
||||
fn get_global(&mut self, export_name: &str) -> Self::Global;
|
||||
/// Get the current value of the global.
|
||||
fn get_global_value(&mut self, global: &Self::Global) -> sp_wasm_interface::Value;
|
||||
/// Update the current value of the global.
|
||||
///
|
||||
/// The global behind the handle is guaranteed to be mutable and the value to be the same type
|
||||
/// as the global.
|
||||
fn set_global_value(&mut self, global: &Self::Global, value: sp_wasm_interface::Value);
|
||||
}
|
||||
|
||||
/// A set of exposed mutable globals.
|
||||
///
|
||||
/// This is set of globals required to create a [`GlobalsSnapshot`] and that are collected from
|
||||
/// a runtime blob that was instrumented by
|
||||
/// [`RuntimeBlob::expose_mutable_globals`](super::RuntimeBlob::expose_mutable_globals`).
|
||||
|
||||
/// If the code wasn't instrumented then it would be empty and snapshot would do nothing.
|
||||
pub struct ExposedMutableGlobalsSet(Vec<String>);
|
||||
|
||||
impl ExposedMutableGlobalsSet {
|
||||
/// Collect the set from the given runtime blob. See the struct documentation for details.
|
||||
pub fn collect(runtime_blob: &RuntimeBlob) -> Self {
|
||||
let global_names =
|
||||
runtime_blob.exported_internal_global_names().map(ToOwned::to_owned).collect();
|
||||
Self(global_names)
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshot of a global variables values. This snapshot can be later used for restoring the
|
||||
/// values to the preserved state.
|
||||
///
|
||||
/// Technically, a snapshot stores only values of mutable global variables. This is because
|
||||
/// immutable global variables always have the same values.
|
||||
///
|
||||
/// We take it from an instance rather from a module because the start function could potentially
|
||||
/// change any of the mutable global values.
|
||||
pub struct GlobalsSnapshot<Global>(Vec<SavedValue<Global>>);
|
||||
|
||||
impl<Global> GlobalsSnapshot<Global> {
|
||||
/// Take a snapshot of global variables for a given instance.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the instance doesn't correspond to the module from which the
|
||||
/// [`ExposedMutableGlobalsSet`] was collected.
|
||||
pub fn take<Instance>(
|
||||
mutable_globals: &ExposedMutableGlobalsSet,
|
||||
instance: &mut Instance,
|
||||
) -> Self
|
||||
where
|
||||
Instance: InstanceGlobals<Global = Global>,
|
||||
{
|
||||
let global_names = &mutable_globals.0;
|
||||
let mut saved_values = Vec::with_capacity(global_names.len());
|
||||
|
||||
for global_name in global_names {
|
||||
let handle = instance.get_global(global_name);
|
||||
let value = instance.get_global_value(&handle);
|
||||
saved_values.push(SavedValue { handle, value });
|
||||
}
|
||||
|
||||
Self(saved_values)
|
||||
}
|
||||
|
||||
/// Apply the snapshot to the given instance.
|
||||
///
|
||||
/// This instance must be the same that was used for creation of this snapshot.
|
||||
pub fn apply<Instance>(&self, instance: &mut Instance)
|
||||
where
|
||||
Instance: InstanceGlobals<Global = Global>,
|
||||
{
|
||||
for saved_value in &self.0 {
|
||||
instance.set_global_value(&saved_value.handle, saved_value.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,10 +46,6 @@
|
||||
//! is free of any floating point operations, which is a useful step towards making instances
|
||||
//! produced from such a module deterministic.
|
||||
|
||||
mod data_segments_snapshot;
|
||||
mod globals_snapshot;
|
||||
mod runtime_blob;
|
||||
|
||||
pub use data_segments_snapshot::DataSegmentsSnapshot;
|
||||
pub use globals_snapshot::{ExposedMutableGlobalsSet, GlobalsSnapshot, InstanceGlobals};
|
||||
pub use runtime_blob::RuntimeBlob;
|
||||
|
||||
@@ -20,8 +20,8 @@ use crate::{error::WasmError, wasm_runtime::HeapAllocStrategy};
|
||||
use wasm_instrument::{
|
||||
export_mutable_globals,
|
||||
parity_wasm::elements::{
|
||||
deserialize_buffer, serialize, DataSegment, ExportEntry, External, Internal, MemorySection,
|
||||
MemoryType, Module, Section,
|
||||
deserialize_buffer, serialize, ExportEntry, External, Internal, MemorySection, MemoryType,
|
||||
Module, Section,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -52,11 +52,6 @@ impl RuntimeBlob {
|
||||
Ok(Self { raw_module })
|
||||
}
|
||||
|
||||
/// Extract the data segments from the given wasm code.
|
||||
pub(super) fn data_segments(&self) -> Vec<DataSegment> {
|
||||
self.raw_module.data_section().map(|ds| ds.entries()).unwrap_or(&[]).to_vec()
|
||||
}
|
||||
|
||||
/// The number of globals defined in locally in this module.
|
||||
pub fn declared_globals_count(&self) -> u32 {
|
||||
self.raw_module
|
||||
@@ -190,16 +185,6 @@ impl RuntimeBlob {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns an iterator of all globals which were exported by [`expose_mutable_globals`].
|
||||
pub(super) fn exported_internal_global_names(&self) -> impl Iterator<Item = &str> {
|
||||
let exports = self.raw_module.export_section().map(|es| es.entries()).unwrap_or(&[]);
|
||||
exports.iter().filter_map(|export| match export.internal() {
|
||||
Internal::Global(_) if export.field().starts_with("exported_internal_global") =>
|
||||
Some(export.field()),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Scans the wasm blob for the first section with the name that matches the given. Returns the
|
||||
/// contents of the custom section if found or `None` otherwise.
|
||||
pub fn custom_section_contents(&self, section_name: &str) -> Option<&[u8]> {
|
||||
|
||||
@@ -115,16 +115,6 @@ pub trait WasmInstance: Send {
|
||||
///
|
||||
/// This method is only suitable for getting immutable globals.
|
||||
fn get_global_const(&mut self, name: &str) -> Result<Option<Value>, Error>;
|
||||
|
||||
/// **Testing Only**. This function returns the base address of the linear memory.
|
||||
///
|
||||
/// This is meant to be the starting address of the memory mapped area for the linear memory.
|
||||
///
|
||||
/// This function is intended only for a specific test that measures physical memory
|
||||
/// consumption.
|
||||
fn linear_memory_base_ptr(&self) -> Option<*const u8> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the heap pages allocation strategy the wasm runtime should use.
|
||||
|
||||
Reference in New Issue
Block a user