Skip to content

Conversation

@febo
Copy link
Collaborator

@febo febo commented Dec 16, 2025

Problem

Currently, the BumpAllocator allocates memory backwards and it has a fixed limit of 32KiB size. Even if a program requests a larger heap size, this won't be used unless a custom allocator is implemented.

Solution

Refactor the BumpAllocator to allocate memory forward. This has 2 benefits:

  1. It is slightly more efficient, saving ~7 CUs per allocation;
  2. Removes the need to implement a custom allocator when a different heap size is requested.

The implementation relies on the runtime to zero initialize the heap region and to enforce the available heap length. The execution of a program is sand-boxed and the runtime prevents memory access outside the program memory space.

@febo febo requested review from Lichtso and joncinque December 16, 2025 12:14
@febo febo force-pushed the febo/forward-bump-allocator branch from 4ab6fab to 1b0bfc6 Compare December 16, 2025 12:24
@febo febo marked this pull request as ready for review December 16, 2025 13:58
Lichtso
Lichtso previously approved these changes Dec 16, 2025
Copy link
Collaborator

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! Mostly nits and one comment

Comment on lines +676 to +677
/// `layout` must have non-zero size. Attempting to allocate for a zero-sized layout will
/// result in undefined behavior.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is ok, since most users of allocators no-op if the type is zero-sized, ie https://doc.rust-lang.org/src/alloc/boxed.rs.html#571

Comment on lines 692 to 695
let padding = layout.align() - 1;

if unlikely(self.end - pos < padding) {
return null_mut();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm being dense, but is this check necessary? allocation finds the start address, so we should just need to later check that self.end > allocation + layout.size()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was avoiding doing the allocation + layout.size() operation without checks since it can overflow if you try to allocate u64::MAX for example. And allocation might be bigger than self.end if there is no "space" left for the alignment padding.

We could probably save 1 CU by testing that layout.size() is not greater than MAX_HEAP_SIZE and then do the check self.end > allocation + layout.size() instead. I will try that.

Copy link
Collaborator Author

@febo febo Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does save 1 extra CU. 😊

Comment on lines +717 to +718
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
self.alloc(layout)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe, very cool!

Copy link
Collaborator

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect!

@febo febo merged commit e555bfe into main Dec 16, 2025
8 checks passed
@febo febo deleted the febo/forward-bump-allocator branch December 16, 2025 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants