Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bump Allocator #831

Merged
merged 41 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d4f1d58
Add bump allocator skeleton
HCastano Jun 25, 2021
c2b019e
Implement `alloc` for our bump allocator
HCastano Jun 25, 2021
3deb3d8
Make the allocator usable globally
HCastano Jun 28, 2021
b4bec3d
Remove unused `init()` function
HCastano Jun 28, 2021
0267f88
Nightly RustFmt
HCastano Jun 28, 2021
5b87b12
Use global mutable static instead of Mutex
HCastano Jun 29, 2021
605aafe
Stop assuming that memory is allocated at address `0`
HCastano Jun 29, 2021
de3095b
Remove semicolon
HCastano Jun 29, 2021
d668dac
Use correct address when checking if we're OOM
HCastano Jun 29, 2021
1d776d9
Remove unnecessary unsafe block
HCastano Jun 30, 2021
1ff4965
Return null pointers instead of panicking
HCastano Jun 30, 2021
6bff7cd
Use `checked_add` when getting upper limit memory address
HCastano Jun 30, 2021
46f0e1d
Use `MAX` associated const instead of `max_value`
HCastano Jun 30, 2021
a608499
Inline `GlobalAlloc` methods
HCastano Jun 30, 2021
52d05de
Turns out I can't early return from `unwrap_or_else` 🤦
HCastano Jun 30, 2021
d382bae
Rollback my build script hacks
HCastano Jun 30, 2021
1c62e7f
Add initialization function to allocator
HCastano Jul 1, 2021
68741fe
Add some docs
HCastano Jul 1, 2021
95adb71
Make the bump allocator the default allocator
HCastano Jul 1, 2021
80ee405
Allow bump allocator to be tested on Unix platforms
HCastano Jul 6, 2021
767f234
Remove unecessary checked_add
HCastano Jul 6, 2021
53af550
Add error messages to unrecoverable errors
HCastano Jul 6, 2021
fb49543
Remove `init` function from allocator
HCastano Jul 7, 2021
b1c4de1
Try switching from `mmap` to `malloc` when in `std` env
HCastano Jul 7, 2021
3ea81cc
Fix `is_null()` check when requesting memory
HCastano Jul 9, 2021
509c9c4
Stop requesting real memory for `std` testing
HCastano Jul 9, 2021
8e8af79
Gate the global bump allocator when not in `std`
HCastano Jul 12, 2021
2208229
Allow for multi-page allocations
HCastano Jul 12, 2021
f042526
Update the module documentation
HCastano Jul 12, 2021
bcf728b
Override `alloc_zeroed` implementation
HCastano Jul 12, 2021
6dade8f
Merge branch 'master' into hc-bump-allocator
HCastano Jul 12, 2021
ae097bf
Forgot to update Wasm target function name
HCastano Jul 12, 2021
f4e6a31
Appease the spellchecker
HCastano Jul 12, 2021
baceccd
Use proper English I guess
HCastano Jul 12, 2021
560fe2f
Get rid of `page_requests` field
HCastano Jul 12, 2021
c971868
Explicitly allow test builds to use test implementation
HCastano Jul 13, 2021
13b8bd3
All link to zero'd Wasm memory reference
HCastano Jul 13, 2021
6b452a6
Check that our initial pointer is 0 in a test
HCastano Jul 13, 2021
7fce248
Add `cfg_if` branch for non-test, `std` enabled builds
HCastano Jul 16, 2021
b12c9f9
Merge branch 'master' into hc-bump-allocator
HCastano Jul 16, 2021
8e84f34
Simplify `cfg_if` statement
HCastano Jul 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/allocator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ categories = ["no-std", "embedded"]
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]

[dependencies]
wee_alloc = { version = "0.4", default-features = false }
wee_alloc = { version = "0.4", default-features = false, optional = true }

[features]
default = ["std"]
std = []
bump-allocator = []
wee-allocator = ["wee_alloc"]
HCastano marked this conversation as resolved.
Show resolved Hide resolved
107 changes: 107 additions & 0 deletions crates/allocator/src/bump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
//
// 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.

//! A simple bump allocator.
//!
//! It's goal to have a much smaller footprint than the admittedly more full-featured `wee_alloc`
//! allocator which is currently being used by ink! smart contracts.
//!
//! The heap which will be used by this allocator is a single page of memory, which in Wasm is
//! 64KiB. We do not expect contracts to use more memory than this (for now), so we will throw an
//! OOM error instead of requesting more memory.

use core::alloc::{
GlobalAlloc,
Layout,
};

/// A page in Wasm is 64KiB
const PAGE_SIZE: usize = 64 * 1024;

static mut INNER: InnerAlloc = InnerAlloc::new();
HCastano marked this conversation as resolved.
Show resolved Hide resolved

pub struct BumpAllocator;

unsafe impl GlobalAlloc for BumpAllocator {
athei marked this conversation as resolved.
Show resolved Hide resolved
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
INNER.alloc(layout)
}

#[inline]
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}

struct InnerAlloc {
/// Points to the start of the next available allocation.
///
/// If the heap hasn't been initialized yet this value will be `None`.
next: Option<usize>,

/// The address of the upper limit of our heap.
///
/// If the heap hasn't been initialized yet this value will be `None`.
upper_limit: Option<usize>,
}

impl InnerAlloc {
const fn new() -> Self {
Self {
next: None,
upper_limit: None,
}
}

fn alloc(&mut self, layout: Layout) -> *mut u8 {
// TODO: Figure out how to properly initalize the heap
let alloc_start = if let Some(start) = self.next {
start
} else {
let prev_page = core::arch::wasm32::memory_grow(0, 1);
if prev_page == usize::MAX {
return core::ptr::null_mut()
}

let start = match prev_page.checked_mul(PAGE_SIZE) {
Some(s) => s,
None => return core::ptr::null_mut(),
};
HCastano marked this conversation as resolved.
Show resolved Hide resolved

self.upper_limit = match start.checked_add(PAGE_SIZE) {
Some(u) => Some(u),
None => return core::ptr::null_mut(),
};

start
};

let aligned_layout = layout.pad_to_align();
let alloc_end = match alloc_start.checked_add(aligned_layout.size()) {
Some(end) => end,
None => return core::ptr::null_mut(),
};

let upper_limit = match self.upper_limit {
Some(u) => u,
None => return core::ptr::null_mut(),
};

if alloc_end > upper_limit {
return core::ptr::null_mut()
}

self.next = Some(alloc_end);
alloc_start as *mut u8
}
}
13 changes: 13 additions & 0 deletions crates/allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@
// We use `wee_alloc` as the global allocator since it is optimized for binary file size
// so that contracts compiled with it as allocator do not grow too much in size.
#[cfg(not(feature = "std"))]
#[cfg(feature = "wee-allocator")]
#[cfg(not(feature = "bump-allocator"))]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[cfg(not(feature = "std"))]
#[cfg(feature = "bump-allocator")]
#[cfg(not(feature = "wee-allocator"))]
#[global_allocator]
static mut ALLOC: bump::BumpAllocator = bump::BumpAllocator {};

#[cfg(not(feature = "std"))]
mod handlers;

#[cfg(not(feature = "std"))]
#[cfg(feature = "bump-allocator")]
#[cfg(not(feature = "wee-allocator"))]
HCastano marked this conversation as resolved.
Show resolved Hide resolved
mod bump;
3 changes: 2 additions & 1 deletion crates/env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
[dependencies]
ink_engine = { version = "3.0.0-rc3", path = "../engine/", default-features = false, optional = true }
ink_metadata = { version = "3.0.0-rc3", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
ink_allocator = { version = "3.0.0-rc3", path = "../allocator/", default-features = false }
# ink_allocator = { version = "3.0.0-rc3", path = "../allocator/", default-features = false, features = ["wee-allocator"] }
ink_allocator = { version = "3.0.0-rc3", path = "../allocator/", default-features = false, features = ["bump-allocator"] }
ink_primitives = { version = "3.0.0-rc3", path = "../primitives/", default-features = false }
ink_prelude = { version = "3.0.0-rc3", path = "../prelude/", default-features = false }

Expand Down
16 changes: 8 additions & 8 deletions scripts/check-examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,26 +71,26 @@ metadata() {

for example in $(ls -d examples/*/ | grep -v delegator); do
build $example
run_tests $example
metadata $example
# run_tests $example
# metadata $example
done

# the delegator is a special case, we need to build it's sub-contracts first
for example in $(ls -d examples/delegator/{accumulator,adder,subber}/); do
build $example
run_tests $example
# build $example
# run_tests $example
done
build examples/delegator/
run_tests examples/delegator/
metadata examples/delegator/
# run_tests examples/delegator/
# metadata examples/delegator/

banner="---------------"
echo "Example Results"
echo "$banner"
for entry in ${!results_wasm[@]}; do
echo "- $entry (wasm): ${results_wasm[$entry]}"
echo "- $entry (test): ${results_test[$entry]}"
echo "- $entry (metadata): ${results_metadata[$entry]}"
# echo "- $entry (test): ${results_test[$entry]}"
# echo "- $entry (metadata): ${results_metadata[$entry]}"
done
echo ""
if [ $all_checks_passed -eq 0 ]
Expand Down