-
Notifications
You must be signed in to change notification settings - Fork 69
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
Implement AllocatorInfo #889
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the changes look good. This is something we need to properly support compiler generated allocation fastpath.
src/util/alloc/allocators.rs
Outdated
limit_offset: usize, | ||
top_offset: usize, | ||
}, | ||
Immix { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can just remove the Immix
variant as well. Immix's overflow_alloc
(which uses the large cursor/limit) and alloc_slow_hot
(which tries to find a recyclable line) is considered as the 'intermediate' path (i.e. between fastpath and slowpath). Normally the compiler don't need to inline it. In that case, generating allocation fastpath for Immix would be the same as BumpPointer
fastpath (just checking cursor/limit, and adjust cursor).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not small limit still be checked? Or am I wrong here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to check "small_limit". If the allocation can fit into the normal buffer (cursor/limit), it will be allocated in the buffer. However, the buffer can be as small as one line (depending on how fragment the heap is). So sometimes the allocation that is larger than one line can't fit into the normal buffer, then the large cursor/limit is used. But that is not in the fastpath path any more.
The actual code that is considered as Immix's fastpath is (which is as simple as a normal bump pointer allocation):
mmtk-core/src/util/alloc/immix_allocator.rs
Lines 75 to 78 in 4c1e58a
let result = align_allocation_no_fill::<VM>(self.cursor, align, offset); | |
let new_cursor = result + size; | |
if new_cursor > self.limit { |
and
mmtk-core/src/util/alloc/immix_allocator.rs
Lines 90 to 102 in 4c1e58a
} else { | |
// Simple bump allocation. | |
fill_alignment_gap::<VM>(self.cursor, result); | |
self.cursor = new_cursor; | |
trace!( | |
"{:?}: Bump allocation size: {}, result: {}, new_cursor: {}, limit: {}", | |
self.tls, | |
size, | |
result, | |
self.cursor, | |
self.limit | |
); | |
result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remembered @wenyuzhao mentioning something about this in-person to me (Re: limit for Immix allocator being 256 bytes). Maybe he can chime in and clarify expectations.
src/util/alloc/bumpallocator.rs
Outdated
pub(crate) cursor: Address, | ||
/// Limit for bump pointer | ||
limit: Address, | ||
pub(crate) limit: Address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make a #[repr(C)] struct
for these two fields since it appears so often. Then we only need to return one offset for those two fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be done in this PR as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please. This is the best chance to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How this structure should be named? And also, where should I put it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I think we should discuss on Zulip and let everyone vote.
It should be defined in allocator.rs
because it is common to many concrete allocators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This PR seems a step in the right direction. Thank you!
- Placing cursor and limit in a struct seems sensible.
- The cursor and limit should be called a bump pointer, because that is literally what it is (edit: at least that's what I think you're doing, from my read). I teach people how GCs are built and this is literally how I describe a bump pointer: a cursor and a limit. Inventing a new term to describe this most basic of data structures is not a good idea.
Meta point: I don't think "voting" on conceptual points like this on Zulip is a great idea in general.
So far what would be the next proper steps to get this PR merged? I am actually now all in for idea of bindings storing bump-pointers/free-lists on their side and syncing with MMTk when necessary. BDWGC works this way by providing support for inline allocation by allowing user-code to create free-lists. |
It seems there are two options:
My preference is Option 1. It covers what Option2 does, and is more flexible for the bindings. Option 2 enforces the binding to create their own fastpath data structures, and sync values with MMTk. I am not sure what others think about. @steveblackburn @wks We will get this resolved no later than tomorrow (we have a meeting tomorrow and I will raise this if necessary). |
We discussed this. Exposing field offsets to the binding is a good idea. It allows the JIT compiler to generate code, and allows the runtime to load/store the values. A refinement on the current PR we plan to do is that we could have public fastpath structs with #[repr(C)]
pub struct BumpPointer {
pub cursor: Address,
pub limit: Address,
}
struct BumpAllocator {
bump_pointer: BumpPointer
...
}
pub enum AllocatorInfo {
BumpPointer(usize), // offset from mutator to the BumpPointer struct
// FIXME: Add free-list fast-path
Unimplemented,
None,
} This change does not have to be included in the PR. Just FYI, as we may change the actual interface in the future. But we will follow the general idea of exposing offsets to fields for bindings. If this sounds good to you, you can make the PR ready, and we can proceed from there. Thanks for the PR. |
@qinsoon I see, I'll implement BumpPointer in this PR as well, I need to get fast-path allocations in my runtime working now. Will do that on weekends probably, right now busy with getting into new job. |
I am trying to push some changes to the PR. Mainly about the new method |
fields only public in util::alloc
84b6b61
to
ff456e5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This type adds
AllocatorInfo
enum that can be used to query offset of allocator fields for fast-path generation. Currently all bindings have to re-declare*Allocator
types with the same layout as in mmtk-core in order to get offset of these fields. This enum simplifies that, all you need to do is invokeget_allocator_info(selector)
.