mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-04 19:50:19 +00:00
fix(runtime): support new wasm opcodes by removing unused memory limit setting (#299)
remove unused max memory setting
This commit is contained in:
parent
04914dd291
commit
b9dbf67376
517
Cargo.lock
generated
517
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -27,9 +27,6 @@ it-memory-traits = { workspace = true }
|
||||
bytesize = "1.1.0"
|
||||
|
||||
multimap = "0.8.3"
|
||||
boolinator = "2.4.0"
|
||||
parity-wasm = "0.45.0"
|
||||
pwasm-utils = "0.19.0"
|
||||
once_cell = "1.16.0"
|
||||
semver = "1.0.14"
|
||||
serde = "1.0.147"
|
||||
|
@ -108,8 +108,6 @@ impl<WB: WasmBackend> MarineCore<WB> {
|
||||
wasm_bytes: &[u8],
|
||||
config: MModuleConfig<WB>,
|
||||
) -> MResult<()> {
|
||||
let _prepared_wasm_bytes =
|
||||
crate::misc::prepare_module(wasm_bytes, config.max_heap_pages_count)?;
|
||||
let module = MModule::new(
|
||||
&name,
|
||||
self.store.get_mut(),
|
||||
|
@ -20,13 +20,6 @@ use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum PrepareError {
|
||||
/// Error that raises on a Wasm module validation.
|
||||
#[error("validation error: {0}, probably module is malformed")]
|
||||
ParseError(#[from] parity_wasm::elements::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
HeapBaseInvalidOrMissing(#[from] HeapBaseError),
|
||||
|
||||
#[error("overflow was happened while summation globals size '{globals_pages_count}' and heap size '{max_heap_pages_count}'")]
|
||||
MemSizesOverflow {
|
||||
globals_pages_count: u32,
|
||||
@ -57,15 +50,3 @@ pub enum PrepareError {
|
||||
provided: semver::Version,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum HeapBaseError {
|
||||
#[error("a Wasm module doesn't expose __heap_base entry")]
|
||||
ExportNotFound,
|
||||
|
||||
#[error("__heap_base is initialized not by i32.const, but by a different set of instructions, that's unsupported")]
|
||||
InitializationNotI32Const,
|
||||
|
||||
#[error("__heap_base has not a i32 type")]
|
||||
WrongType,
|
||||
}
|
||||
|
@ -15,12 +15,9 @@
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod prepare;
|
||||
mod version_checker;
|
||||
|
||||
pub(crate) use errors::HeapBaseError;
|
||||
pub(crate) use errors::PrepareError;
|
||||
pub(crate) use prepare::prepare_module;
|
||||
pub(crate) use version_checker::check_sdk_version;
|
||||
pub(crate) use version_checker::check_it_version;
|
||||
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Similar to
|
||||
// https://github.com/paritytech/substrate/blob/master/srml/contracts/src/wasm/prepare.rs
|
||||
// https://github.com/nearprotocol/nearcore/blob/master/runtime/near-vm-runner/src/prepare.rs
|
||||
|
||||
mod heap_base;
|
||||
|
||||
use super::PrepareResult;
|
||||
use crate::misc::PrepareError;
|
||||
use heap_base::get_heap_base;
|
||||
|
||||
use marine_utils::bytes_to_wasm_pages_ceil;
|
||||
use parity_wasm::builder;
|
||||
use parity_wasm::elements;
|
||||
|
||||
// not all clangs versions emits __heap_base, and this consts is a temporary solution
|
||||
// until node has a dedicated config for that
|
||||
const DEFAULT_GLOBALS_SIZE: u32 = 50;
|
||||
|
||||
struct ModuleBootstrapper {
|
||||
module: elements::Module,
|
||||
}
|
||||
|
||||
impl ModuleBootstrapper {
|
||||
fn init(module_code: &[u8]) -> PrepareResult<Self> {
|
||||
let module = elements::deserialize_buffer(module_code)?;
|
||||
|
||||
Ok(Self { module })
|
||||
}
|
||||
|
||||
fn set_max_heap_pages_count(self, max_heap_pages_count: u32) -> PrepareResult<Self> {
|
||||
use elements::MemoryType;
|
||||
use elements::MemorySection;
|
||||
|
||||
let Self { mut module } = self;
|
||||
let globals_pages_count = get_heap_base(&module)
|
||||
.map(bytes_to_wasm_pages_ceil)
|
||||
.unwrap_or(DEFAULT_GLOBALS_SIZE);
|
||||
let max_mem_pages_count = globals_pages_count
|
||||
.checked_add(max_heap_pages_count)
|
||||
.ok_or(PrepareError::MemSizesOverflow {
|
||||
globals_pages_count,
|
||||
max_heap_pages_count,
|
||||
})?;
|
||||
|
||||
// At now, there is could be only one memory section, so
|
||||
// it needs just to extract previous initial page count,
|
||||
// delete an old entry and add create a new one with updated limits
|
||||
let mem_initial_size = match module.memory_section_mut() {
|
||||
Some(section) => match section.entries_mut().pop() {
|
||||
Some(entry) => entry.limits().initial(),
|
||||
None => 0,
|
||||
},
|
||||
None => 0,
|
||||
};
|
||||
let mem_initial_size = std::cmp::min(mem_initial_size, max_mem_pages_count);
|
||||
|
||||
let memory_entry = MemoryType::new(mem_initial_size, Some(max_mem_pages_count));
|
||||
let mut default_mem_section = MemorySection::default();
|
||||
|
||||
module
|
||||
.memory_section_mut()
|
||||
.unwrap_or(&mut default_mem_section)
|
||||
.entries_mut()
|
||||
.push(memory_entry);
|
||||
|
||||
let builder = builder::from_module(module);
|
||||
|
||||
let module = builder.build();
|
||||
Ok(Self { module })
|
||||
}
|
||||
|
||||
fn into_wasm(self) -> PrepareResult<Vec<u8>> {
|
||||
elements::serialize(self.module).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares a Wasm module:
|
||||
/// - extracts __heap_base global
|
||||
/// - computes module max memory size by summation of heap and globals sizes
|
||||
/// - sets computed value as max memory page count of a module
|
||||
pub(crate) fn prepare_module(module: &[u8], max_heap_pages_count: u32) -> PrepareResult<Vec<u8>> {
|
||||
ModuleBootstrapper::init(module)?
|
||||
.set_max_heap_pages_count(max_heap_pages_count)?
|
||||
.into_wasm()
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::misc::HeapBaseError::*;
|
||||
|
||||
use parity_wasm::elements;
|
||||
|
||||
const HEAP_BASE_NAME: &str = "__heap_base";
|
||||
|
||||
type HResult<T> = std::result::Result<T, crate::misc::HeapBaseError>;
|
||||
|
||||
/// Return value of __heap_base.
|
||||
pub(super) fn get_heap_base(wasm_module: &elements::Module) -> HResult<u32> {
|
||||
let heap_base_index = find_global_name_index(wasm_module, HEAP_BASE_NAME)?;
|
||||
let global_entry = find_global_by_index(wasm_module, heap_base_index as usize)?;
|
||||
u32_from_global_entry(global_entry)
|
||||
}
|
||||
|
||||
fn find_global_name_index(wasm_module: &elements::Module, name: &str) -> HResult<u32> {
|
||||
use elements::Internal;
|
||||
|
||||
wasm_module
|
||||
.export_section()
|
||||
.and_then(|export_section| {
|
||||
export_section
|
||||
.entries()
|
||||
.iter()
|
||||
.find_map(|entry| match entry.internal() {
|
||||
Internal::Global(index) if entry.field() == name => Some(*index),
|
||||
_ => None,
|
||||
})
|
||||
})
|
||||
.ok_or(ExportNotFound)
|
||||
}
|
||||
|
||||
fn find_global_by_index(
|
||||
wasm_module: &elements::Module,
|
||||
index: usize,
|
||||
) -> HResult<&elements::GlobalEntry> {
|
||||
wasm_module
|
||||
.global_section()
|
||||
.and_then(|section| section.entries().get(index))
|
||||
.ok_or(ExportNotFound)
|
||||
}
|
||||
|
||||
fn u32_from_global_entry(global_entry: &elements::GlobalEntry) -> HResult<u32> {
|
||||
use elements::Instruction;
|
||||
use elements::ValueType;
|
||||
|
||||
let entry_type = global_entry.global_type().content_type();
|
||||
if !matches!(entry_type, ValueType::I32) {
|
||||
return Err(WrongType);
|
||||
}
|
||||
|
||||
let init_expr = global_entry.init_expr().code();
|
||||
// check that initialization expression consists of two instructions:
|
||||
// i32.const <heap_base>
|
||||
// end
|
||||
if init_expr.len() != 2 {
|
||||
return Err(InitializationNotI32Const);
|
||||
}
|
||||
|
||||
match (&init_expr[0], &init_expr[1]) {
|
||||
(Instruction::I32Const(value), Instruction::End) => Ok(*value as u32),
|
||||
_ => Err(InitializationNotI32Const),
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2022-12-01"
|
||||
channel = "nightly-2023-03-12"
|
||||
targets = [
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"x86_64-unknown-linux-musl",
|
||||
|
Loading…
Reference in New Issue
Block a user