mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 14:37:57 +00:00
Refactor WASM module instantiation (#10480)
* Refactor WASM module instantiation; enable WASM instance pooling * Disable the `uffd` feature on `wasmtime` * Restore the original behavior regarding the initial WASM memory size * Adjust error message * Remove unnecessary import in the benchmarks * Preinstantiate the WASM runtime for a slight speedup * Delete the asserts in `convert_memory_import_into_export` * `return` -> `break` * Revert WASM instance pooling for now * Have `convert_memory_import_into_export` return an error instead of panic * Update the warning when an import is missing * Rustfmt and clippy fix * Fix executor benchmarks' compilation without `wasmtime` being enabled * rustfmt again * Align to review comments * Extend tests so that both imported and exported memories are tested * Increase the number of heap pages for exported memories too * Fix `decommit_works` test
This commit is contained in:
@@ -19,7 +19,10 @@
|
||||
use crate::error::WasmError;
|
||||
use wasm_instrument::{
|
||||
export_mutable_globals,
|
||||
parity_wasm::elements::{deserialize_buffer, serialize, DataSegment, Internal, Module},
|
||||
parity_wasm::elements::{
|
||||
deserialize_buffer, serialize, DataSegment, ExportEntry, External, Internal, MemorySection,
|
||||
MemoryType, Module, Section,
|
||||
},
|
||||
};
|
||||
|
||||
/// A bunch of information collected from a WebAssembly module.
|
||||
@@ -104,6 +107,85 @@ impl RuntimeBlob {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Converts a WASM memory import into a memory section and exports it.
|
||||
///
|
||||
/// Does nothing if there's no memory import.
|
||||
///
|
||||
/// May return an error in case the WASM module is invalid.
|
||||
pub fn convert_memory_import_into_export(&mut self) -> Result<(), WasmError> {
|
||||
let import_section = match self.raw_module.import_section_mut() {
|
||||
Some(import_section) => import_section,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let import_entries = import_section.entries_mut();
|
||||
for index in 0..import_entries.len() {
|
||||
let entry = &import_entries[index];
|
||||
let memory_ty = match entry.external() {
|
||||
External::Memory(memory_ty) => *memory_ty,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let memory_name = entry.field().to_owned();
|
||||
import_entries.remove(index);
|
||||
|
||||
self.raw_module
|
||||
.insert_section(Section::Memory(MemorySection::with_entries(vec![memory_ty])))
|
||||
.map_err(|error| {
|
||||
WasmError::Other(format!(
|
||||
"can't convert a memory import into an export: failed to insert a new memory section: {}",
|
||||
error
|
||||
))
|
||||
})?;
|
||||
|
||||
if self.raw_module.export_section_mut().is_none() {
|
||||
// A module without an export section is somewhat unrealistic, but let's do this
|
||||
// just in case to cover all of our bases.
|
||||
self.raw_module
|
||||
.insert_section(Section::Export(Default::default()))
|
||||
.expect("an export section can be always inserted if it doesn't exist; qed");
|
||||
}
|
||||
self.raw_module
|
||||
.export_section_mut()
|
||||
.expect("export section already existed or we just added it above, so it always exists; qed")
|
||||
.entries_mut()
|
||||
.push(ExportEntry::new(memory_name, Internal::Memory(0)));
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Increases the number of memory pages requested by the WASM blob by
|
||||
/// the given amount of `extra_heap_pages`.
|
||||
///
|
||||
/// Will return an error in case there is no memory section present,
|
||||
/// or if the memory section is empty.
|
||||
///
|
||||
/// Only modifies the initial size of the memory; the maximum is unmodified
|
||||
/// unless it's smaller than the initial size, in which case it will be increased
|
||||
/// so that it's at least as big as the initial size.
|
||||
pub fn add_extra_heap_pages_to_memory_section(
|
||||
&mut self,
|
||||
extra_heap_pages: u32,
|
||||
) -> Result<(), WasmError> {
|
||||
let memory_section = self
|
||||
.raw_module
|
||||
.memory_section_mut()
|
||||
.ok_or_else(|| WasmError::Other("no memory section found".into()))?;
|
||||
|
||||
if memory_section.entries().is_empty() {
|
||||
return Err(WasmError::Other("memory section is empty".into()))
|
||||
}
|
||||
for memory_ty in memory_section.entries_mut() {
|
||||
let min = memory_ty.limits().initial().saturating_add(extra_heap_pages);
|
||||
let max = memory_ty.limits().maximum().map(|max| std::cmp::max(min, max));
|
||||
*memory_ty = MemoryType::new(min, max);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns an iterator of all globals which were exported by [`expose_mutable_globals`].
|
||||
pub(super) fn exported_internal_global_names<'module>(
|
||||
&'module self,
|
||||
|
||||
Reference in New Issue
Block a user