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:
yjh
2023-09-18 13:53:06 +08:00
committed by GitHub
parent cf5c195237
commit e38998801e
16 changed files with 20 additions and 710 deletions
@@ -27,9 +27,7 @@ use crate::{
use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator};
use sc_executor_common::{
error::{Error, Result, WasmError},
runtime_blob::{
self, DataSegmentsSnapshot, ExposedMutableGlobalsSet, GlobalsSnapshot, RuntimeBlob,
},
runtime_blob::RuntimeBlob,
util::checked_range,
wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmInstance, WasmModule},
};
@@ -69,17 +67,11 @@ impl StoreData {
pub(crate) type Store = wasmtime::Store<StoreData>;
enum Strategy {
LegacyInstanceReuse {
instance_wrapper: InstanceWrapper,
globals_snapshot: GlobalsSnapshot<wasmtime::Global>,
data_segments_snapshot: Arc<DataSegmentsSnapshot>,
heap_base: u32,
},
RecreateInstance(InstanceCreator),
}
struct InstanceCreator {
engine: wasmtime::Engine,
engine: Engine,
instance_pre: Arc<wasmtime::InstancePre<StoreData>>,
}
@@ -89,40 +81,10 @@ impl InstanceCreator {
}
}
struct InstanceGlobals<'a> {
instance: &'a mut InstanceWrapper,
}
impl<'a> runtime_blob::InstanceGlobals for InstanceGlobals<'a> {
type Global = wasmtime::Global;
fn get_global(&mut self, export_name: &str) -> Self::Global {
self.instance
.get_global(export_name)
.expect("get_global is guaranteed to be called with an export name of a global; qed")
}
fn get_global_value(&mut self, global: &Self::Global) -> Value {
util::from_wasmtime_val(global.get(&mut self.instance.store_mut()))
}
fn set_global_value(&mut self, global: &Self::Global, value: Value) {
global.set(&mut self.instance.store_mut(), util::into_wasmtime_val(value)).expect(
"the value is guaranteed to be of the same value; the global is guaranteed to be mutable; qed",
);
}
}
/// Data required for creating instances with the fast instance reuse strategy.
struct InstanceSnapshotData {
mutable_globals: ExposedMutableGlobalsSet,
data_segments_snapshot: Arc<DataSegmentsSnapshot>,
}
/// A `WasmModule` implementation using wasmtime to compile the runtime module to machine code
/// and execute the compiled code.
pub struct WasmtimeRuntime {
engine: wasmtime::Engine,
engine: Engine,
instance_pre: Arc<wasmtime::InstancePre<StoreData>>,
instantiation_strategy: InternalInstantiationStrategy,
}
@@ -130,26 +92,6 @@ pub struct WasmtimeRuntime {
impl WasmModule for WasmtimeRuntime {
fn new_instance(&self) -> Result<Box<dyn WasmInstance>> {
let strategy = match self.instantiation_strategy {
InternalInstantiationStrategy::LegacyInstanceReuse(ref snapshot_data) => {
let mut instance_wrapper = InstanceWrapper::new(&self.engine, &self.instance_pre)?;
let heap_base = instance_wrapper.extract_heap_base()?;
// This function panics if the instance was created from a runtime blob different
// from which 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,
&mut InstanceGlobals { instance: &mut instance_wrapper },
);
Strategy::LegacyInstanceReuse {
instance_wrapper,
globals_snapshot,
data_segments_snapshot: snapshot_data.data_segments_snapshot.clone(),
heap_base,
}
},
InternalInstantiationStrategy::Builtin => Strategy::RecreateInstance(InstanceCreator {
engine: self.engine.clone(),
instance_pre: self.instance_pre.clone(),
@@ -174,39 +116,12 @@ impl WasmtimeInstance {
allocation_stats: &mut Option<AllocationStats>,
) -> Result<Vec<u8>> {
match &mut self.strategy {
Strategy::LegacyInstanceReuse {
ref mut instance_wrapper,
globals_snapshot,
data_segments_snapshot,
heap_base,
} => {
let entrypoint = instance_wrapper.resolve_entrypoint(method)?;
data_segments_snapshot.apply(|offset, contents| {
util::write_memory_from(
instance_wrapper.store_mut(),
Pointer::new(offset),
contents,
)
})?;
globals_snapshot.apply(&mut InstanceGlobals { instance: instance_wrapper });
let allocator = FreeingBumpHeapAllocator::new(*heap_base);
let result =
perform_call(data, instance_wrapper, entrypoint, allocator, allocation_stats);
// Signal to the OS that we are done with the linear memory and that it can be
// reclaimed.
instance_wrapper.decommit();
result
},
Strategy::RecreateInstance(ref mut instance_creator) => {
let mut instance_wrapper = instance_creator.instantiate()?;
let heap_base = instance_wrapper.extract_heap_base()?;
let entrypoint = instance_wrapper.resolve_entrypoint(method)?;
let allocator = FreeingBumpHeapAllocator::new(heap_base);
perform_call(data, &mut instance_wrapper, entrypoint, allocator, allocation_stats)
},
}
@@ -226,24 +141,10 @@ impl WasmInstance for WasmtimeInstance {
fn get_global_const(&mut self, name: &str) -> Result<Option<Value>> {
match &mut self.strategy {
Strategy::LegacyInstanceReuse { instance_wrapper, .. } =>
instance_wrapper.get_global_val(name),
Strategy::RecreateInstance(ref mut instance_creator) =>
instance_creator.instantiate()?.get_global_val(name),
}
}
fn linear_memory_base_ptr(&self) -> Option<*const u8> {
match &self.strategy {
Strategy::RecreateInstance(_) => {
// We do not keep the wasm instance around, therefore there is no linear memory
// associated with it.
None
},
Strategy::LegacyInstanceReuse { instance_wrapper, .. } =>
Some(instance_wrapper.base_ptr()),
}
}
}
/// Prepare a directory structure and a config file to enable wasmtime caching.
@@ -338,7 +239,6 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
InstantiationStrategy::Pooling => (true, false),
InstantiationStrategy::RecreateInstanceCopyOnWrite => (false, true),
InstantiationStrategy::RecreateInstance => (false, false),
InstantiationStrategy::LegacyInstanceReuse => (false, false),
};
const WASM_PAGE_SIZE: u64 = 65536;
@@ -409,7 +309,7 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
///
/// See [here][stack_height] for more details of the instrumentation
///
/// [stack_height]: https://github.com/paritytech/wasm-utils/blob/d9432baf/src/stack_height/mod.rs#L1-L50
/// [stack_height]: https://github.com/paritytech/wasm-instrument/blob/master/src/stack_limiter/mod.rs
#[derive(Clone)]
pub struct DeterministicStackLimit {
/// A number of logical "values" that can be pushed on the wasm stack. A trap will be triggered
@@ -458,13 +358,9 @@ pub enum InstantiationStrategy {
/// Recreate the instance from scratch on every instantiation. Very slow.
RecreateInstance,
/// Legacy instance reuse mechanism. DEPRECATED. Will be removed. Do not use.
LegacyInstanceReuse,
}
enum InternalInstantiationStrategy {
LegacyInstanceReuse(InstanceSnapshotData),
Builtin,
}
@@ -655,22 +551,6 @@ where
.map_err(|e| WasmError::Other(format!("cannot create module: {:#}", e)))?;
match config.semantics.instantiation_strategy {
InstantiationStrategy::LegacyInstanceReuse => {
let data_segments_snapshot =
DataSegmentsSnapshot::take(&blob).map_err(|e| {
WasmError::Other(format!("cannot take data segments snapshot: {}", e))
})?;
let data_segments_snapshot = Arc::new(data_segments_snapshot);
let mutable_globals = ExposedMutableGlobalsSet::collect(&blob);
(
module,
InternalInstantiationStrategy::LegacyInstanceReuse(InstanceSnapshotData {
data_segments_snapshot,
mutable_globals,
}),
)
},
InstantiationStrategy::Pooling |
InstantiationStrategy::PoolingCopyOnWrite |
InstantiationStrategy::RecreateInstance |
@@ -679,12 +559,6 @@ where
}
},
CodeSupplyMode::Precompiled(compiled_artifact_path) => {
if let InstantiationStrategy::LegacyInstanceReuse =
config.semantics.instantiation_strategy
{
return Err(WasmError::Other("the legacy instance reuse instantiation strategy is incompatible with precompiled modules".into()));
}
// SAFETY: The unsafety of `deserialize_file` is covered by this function. The
// responsibilities to maintain the invariants are passed to the caller.
//
@@ -695,12 +569,6 @@ where
(module, InternalInstantiationStrategy::Builtin)
},
CodeSupplyMode::PrecompiledBytes(compiled_artifact_bytes) => {
if let InstantiationStrategy::LegacyInstanceReuse =
config.semantics.instantiation_strategy
{
return Err(WasmError::Other("the legacy instance reuse instantiation strategy is incompatible with precompiled modules".into()));
}
// SAFETY: The unsafety of `deserialize` is covered by this function. The
// responsibilities to maintain the invariants are passed to the caller.
//
@@ -730,13 +598,6 @@ fn prepare_blob_for_compilation(
blob = blob.inject_stack_depth_metering(logical_max)?;
}
if let InstantiationStrategy::LegacyInstanceReuse = semantics.instantiation_strategy {
// When this strategy is used this must be called after all other passes which may introduce
// new global variables, otherwise they will not be reset when we call into the runtime
// again.
blob.expose_mutable_globals();
}
// We don't actually need the memory to be imported so we can just convert any memory
// import into an export with impunity. This simplifies our code since `wasmtime` will
// now automatically take care of creating the memory for us, and it is also necessary