Skip to content

Commit c2af398

Browse files
atheiascjonesHCastano
authored
Don't grow memory on first allocation (#1712)
* Don't always request a new page * Fix some spacing nits * fmt --------- Co-authored-by: Andrew Jones <ascjones@gmail.com> Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
1 parent 3d6784c commit c2af398

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

crates/allocator/src/bump.rs

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,22 @@ use core::alloc::{
2929
/// A page in Wasm is `64KiB`
3030
const PAGE_SIZE: usize = 64 * 1024;
3131

32-
static mut INNER: InnerAlloc = InnerAlloc::new();
32+
static mut INNER: Option<InnerAlloc> = None;
3333

3434
/// A bump allocator suitable for use in a Wasm environment.
3535
pub struct BumpAllocator;
3636

3737
unsafe impl GlobalAlloc for BumpAllocator {
3838
#[inline]
3939
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
40-
match INNER.alloc(layout) {
40+
if INNER.is_none() {
41+
INNER = Some(InnerAlloc::new());
42+
};
43+
match INNER
44+
.as_mut()
45+
.expect("We just set the value above; qed")
46+
.alloc(layout)
47+
{
4148
Some(start) => start as *mut u8,
4249
None => core::ptr::null_mut(),
4350
}
@@ -66,7 +73,7 @@ struct InnerAlloc {
6673
}
6774

6875
impl InnerAlloc {
69-
const fn new() -> Self {
76+
fn new() -> Self {
7077
Self {
7178
next: Self::heap_start(),
7279
upper_limit: Self::heap_end(),
@@ -75,11 +82,11 @@ impl InnerAlloc {
7582

7683
cfg_if::cfg_if! {
7784
if #[cfg(test)] {
78-
const fn heap_start() -> usize {
85+
fn heap_start() -> usize {
7986
0
8087
}
8188

82-
const fn heap_end() -> usize {
89+
fn heap_end() -> usize {
8390
0
8491
}
8592

@@ -93,11 +100,11 @@ impl InnerAlloc {
93100
Some(self.upper_limit)
94101
}
95102
} else if #[cfg(feature = "std")] {
96-
const fn heap_start() -> usize {
103+
fn heap_start() -> usize {
97104
0
98105
}
99106

100-
const fn heap_end() -> usize {
107+
fn heap_end() -> usize {
101108
0
102109
}
103110

@@ -108,12 +115,24 @@ impl InnerAlloc {
108115
)
109116
}
110117
} else if #[cfg(target_arch = "wasm32")] {
111-
const fn heap_start() -> usize {
112-
0
118+
fn heap_start() -> usize {
119+
extern "C" {
120+
static __heap_base: usize;
121+
}
122+
// # SAFETY
123+
//
124+
// The `__heap_base` symbol is defined by the wasm linker and is guaranteed
125+
// to point to the start of the heap.
126+
let heap_start = unsafe { &__heap_base as *const usize as usize };
127+
// if the symbol isn't found it will resolve to 0
128+
// for that to happen the rust compiler or linker need to break or change
129+
assert_ne!(heap_start, 0, "Can't find `__heap_base` symbol.");
130+
heap_start
113131
}
114132

115-
const fn heap_end() -> usize {
116-
0
133+
fn heap_end() -> usize {
134+
// Cannot overflow on this architecture
135+
core::arch::wasm32::memory_size(0) * PAGE_SIZE
117136
}
118137

119138
/// Request a `pages` number of pages of Wasm memory. Each page is `64KiB` in size.
@@ -125,7 +144,8 @@ impl InnerAlloc {
125144
return None;
126145
}
127146

128-
prev_page.checked_mul(PAGE_SIZE)
147+
// Cannot overflow on this architecture
148+
Some(prev_page * PAGE_SIZE)
129149
}
130150
} else if #[cfg(target_arch = "riscv32")] {
131151
const fn heap_start() -> usize {

0 commit comments

Comments
 (0)