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

mini-alloc: a very simple bump allocator #87

Merged
merged 7 commits into from
Dec 22, 2023
Merged

Conversation

mikebenfield
Copy link

No description provided.

Copy link
Contributor

@rachel-bousfield rachel-bousfield left a comment

Choose a reason for hiding this comment

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

Nice work! This is def going to make binaries smaller :)

A few things

examples/erc20/Cargo.toml Outdated Show resolved Hide resolved
mini-alloc/src/lib.rs Outdated Show resolved Hide resolved
mini-alloc/src/lib.rs Outdated Show resolved Hide resolved
mini-alloc/src/lib.rs Outdated Show resolved Hide resolved
mini-alloc/Cargo.toml Outdated Show resolved Hide resolved
let p1 = Vec::<u8>::with_capacity(700);
assert!(p1.as_ptr() as usize > 0);
let p2 = Vec::<u8>::with_capacity(65536);
assert_eq!(p1.as_ptr() as usize + 700, p2.as_ptr() as usize);
Copy link
Contributor

Choose a reason for hiding this comment

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

p1.as_ptr().add(700) == p2.as_ptr()

Copy link
Author

Choose a reason for hiding this comment

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

This will require an unsafe block. Is that still your preference?

mini-alloc/tests/wasm.rs Outdated Show resolved Hide resolved
mini-alloc/src/lib.rs Outdated Show resolved Hide resolved
}

fn round_up_to_alignment(val: usize, align: usize) -> usize {
(val + align - 1) & (-(align as isize) as usize)
Copy link
Contributor

@rachel-bousfield rachel-bousfield Nov 30, 2023

Choose a reason for hiding this comment

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

Let's make this const

This isn't right for non power-of-two alignments

Copy link
Author

Choose a reason for hiding this comment

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

align is always a power of two in Layout:

https://doc.rust-lang.org/std/alloc/struct.Layout.html

But I can add a comment on this function making it clear that align must be a power of two.

@mikebenfield
Copy link
Author

Now supports unix and windows, with a completely separate implementation from wasm32. Addressed your other comments as well.

I'd like to squash this before merging.

@mikebenfield
Copy link
Author

Oh, also, the only windows testing I've done is cargo check --target x86_64-pc-windows-gnu.

@mikebenfield mikebenfield force-pushed the mini-alloc3 branch 6 times, most recently from a2a0c83 to 3953ba2 Compare December 4, 2023 19:58
Copy link
Contributor

@rauljordan rauljordan left a comment

Choose a reason for hiding this comment

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

Everything looks great! Only had minor comments

/// instructions than the positive offset.
static mut STATE: Option<(NonZero, usize)> = None;

unsafe fn alloc_impl(layout: Layout) -> Option<*mut u8> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @mikebenfield should we validate layout.size() before doing more stuff here? Maybe check it is non-zero or not some excessive value

Copy link
Author

Choose a reason for hiding this comment

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

It's the caller's responsibility to ensure the size is non-zero. Our behavior is undefined if we receive a zero size. See the method documentation.

As for an excessively large size, I think we already do the only reasonable thing we can do - if we need to grow more pages and can't, we fail. Is there another check you'd like to see?

unsafe fn alloc_impl(layout: Layout) -> Option<*mut u8> {
let (neg_offset, neg_bound) = STATE.get_or_insert_with(|| {
let heap_base = &__heap_base as *const u8 as usize;
let bound = PAGE_SIZE * wasm32::memory_size(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

Each time this occurs, it has to call wasm32::memory_size(0) which I believe won't change throughout the duration of a program. Is it possible to cache this?

Copy link
Author

Choose a reason for hiding this comment

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

get_or_insert_with will only call this closure the first time this is executed. After that STATE will contain a Some rather than a None and the values will just be retrieved.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh perfect, I missed that you are indeed caching the bound there

Copy link
Contributor

@rachel-bousfield rachel-bousfield left a comment

Choose a reason for hiding this comment

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

I've pushed a commit that adds a test for various edge cases. We're getting close!

Btw don't worry about force pushing :)

if wasm32::memory_grow(0, pages_needed) == usize::MAX {
return None;
}
*neg_bound -= PAGE_SIZE * pages_needed;
Copy link
Contributor

Choose a reason for hiding this comment

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

This overflows if the max number of pages are allocated.
This is why in #89 we start the boundary 1 off.

@mikebenfield mikebenfield force-pushed the mini-alloc3 branch 2 times, most recently from 781084e to bbad3d1 Compare December 22, 2023 19:49
Copy link
Contributor

@rachel-bousfield rachel-bousfield 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! Nice work!

@rachel-bousfield rachel-bousfield merged commit f0709fc into stylus Dec 22, 2023
9 of 10 checks passed
@rachel-bousfield rachel-bousfield deleted the mini-alloc3 branch December 22, 2023 20:55
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.

3 participants