Unverified Commit b0681a04 authored by Hero Bird's avatar Hero Bird Committed by GitHub

Add method to finalize the dynamic storage allocator (#418)

* [core] implement alloc::finalize for the dynamic storage allocator

* [core] adjust tests for the changes

* [core] apply rustfmt

* [core] fix clippy warning

* [core] add SAFETY comments to dynamic storage allocator for Wasm

* [core] add a Note to the docs of alloc::{initialize, finalize}
parent 718b9f5e
Pipeline #93822 failed with stages
in 6 minutes and 2 seconds
This diff is collapsed.
...@@ -75,21 +75,15 @@ mod init; ...@@ -75,21 +75,15 @@ mod init;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use self::allocator::DynamicAllocator;
pub use self::{ pub use self::{
allocation::DynamicAllocation, allocation::DynamicAllocation,
init::{ init::ContractPhase,
initialize_for,
ContractPhase,
},
};
use self::{
allocator::DynamicAllocator,
init::on_call,
}; };
/// Returns a new dynamic storage allocation. /// Returns a new dynamic storage allocation.
pub fn alloc() -> DynamicAllocation { pub fn alloc() -> DynamicAllocation {
on_call(DynamicAllocator::alloc) init::on_instance(DynamicAllocator::alloc)
} }
/// Frees the given dynamic storage allocation. /// Frees the given dynamic storage allocation.
...@@ -97,5 +91,43 @@ pub fn alloc() -> DynamicAllocation { ...@@ -97,5 +91,43 @@ pub fn alloc() -> DynamicAllocation {
/// This makes the given dynamic storage allocation available again /// This makes the given dynamic storage allocation available again
/// for new dynamic storage allocations. /// for new dynamic storage allocations.
pub fn free(allocation: DynamicAllocation) { pub fn free(allocation: DynamicAllocation) {
on_call(|allocator| allocator.free(allocation)) init::on_instance(|allocator| allocator.free(allocation))
}
/// Tells the global dynamic storage allocator instance how it shall initialize.
///
/// # Note
///
/// Normally users of ink! do not have to call this function directly as it is
/// automatically being use in the correct order and way by the generated code.
///
/// - The `phase` parameter describes for which execution phase the dynamic
/// storage allocator needs to be initialized since this is different
/// in contract instantiations and calls.
/// - This has to be issued before the first interaction with the global allocator.
/// - The actual instantiation will happen only upon the first interaction with
/// the global allocator, e.g. using its `alloc` or `free` calls. Until then
/// it remains uninitialized.
///
/// If this function is not called before the first global allocator interaction
/// then the default initialization scheme is for contract instantiation.
/// However, this behavior might change and must not be relied upon.
pub fn initialize(phase: ContractPhase) {
init::initialize(phase);
}
/// Finalizes the global dynamic storage allocator instance.
///
/// This pushes all the accumulated state from this contract execution back to
/// the contract storage to be used in the next contract execution for the same
/// contract instance.
///
/// The global dynamic storage allocator must not be used after this!
///
/// # Note
///
/// Normally users of ink! do not have to call this function directly as it is
/// automatically being use in the correct order and way by the generated code.
pub fn finalize() {
init::finalize()
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
use super::{ use super::{
alloc, alloc,
free, free,
initialize_for,
ContractPhase, ContractPhase,
DynamicAllocation, DynamicAllocation,
DynamicAllocator, DynamicAllocator,
...@@ -25,9 +24,12 @@ use crate::{ ...@@ -25,9 +24,12 @@ use crate::{
test, test,
DefaultEnvTypes, DefaultEnvTypes,
}, },
storage2::traits::{ storage2::{
KeyPtr, alloc,
SpreadLayout, traits::{
KeyPtr,
SpreadLayout,
},
}, },
}; };
use ink_primitives::Key; use ink_primitives::Key;
...@@ -36,7 +38,7 @@ fn run_default_test<F>(f: F) ...@@ -36,7 +38,7 @@ fn run_default_test<F>(f: F)
where where
F: FnOnce(), F: FnOnce(),
{ {
initialize_for(ContractPhase::Deploy); alloc::initialize(ContractPhase::Deploy);
test::run_test::<DefaultEnvTypes, _>(|_| { test::run_test::<DefaultEnvTypes, _>(|_| {
f(); f();
Ok(()) Ok(())
...@@ -195,7 +197,7 @@ fn test_call_setup_works() { ...@@ -195,7 +197,7 @@ fn test_call_setup_works() {
assert_eq!(allocator.alloc(), DynamicAllocation(1)); assert_eq!(allocator.alloc(), DynamicAllocation(1));
let root_key = Key([0xFE; 32]); let root_key = Key([0xFE; 32]);
SpreadLayout::push_spread(&allocator, &mut KeyPtr::from(root_key)); SpreadLayout::push_spread(&allocator, &mut KeyPtr::from(root_key));
initialize_for(ContractPhase::Call); alloc::initialize(ContractPhase::Call);
assert_eq!(alloc(), DynamicAllocation(2)); assert_eq!(alloc(), DynamicAllocation(2));
assert_eq!(alloc(), DynamicAllocation(3)); assert_eq!(alloc(), DynamicAllocation(3));
free(DynamicAllocation(0)); free(DynamicAllocation(0));
......
...@@ -17,10 +17,8 @@ use crate::{ ...@@ -17,10 +17,8 @@ use crate::{
env, env,
env::test::DefaultAccounts, env::test::DefaultAccounts,
storage2::{ storage2::{
alloc::{ alloc,
initialize_for, alloc::ContractPhase,
ContractPhase,
},
traits::{ traits::{
KeyPtr, KeyPtr,
SpreadLayout, SpreadLayout,
...@@ -50,7 +48,7 @@ where ...@@ -50,7 +48,7 @@ where
F: FnOnce(DefaultAccounts<env::DefaultEnvTypes>), F: FnOnce(DefaultAccounts<env::DefaultEnvTypes>),
{ {
env::test::run_test::<env::DefaultEnvTypes, _>(|default_accounts| { env::test::run_test::<env::DefaultEnvTypes, _>(|default_accounts| {
initialize_for(ContractPhase::Deploy); alloc::initialize(ContractPhase::Deploy);
f(default_accounts); f(default_accounts);
Ok(()) Ok(())
}) })
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment