-
Notifications
You must be signed in to change notification settings - Fork 77
Remove unsafe
code related to get_allocator
#1319
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
Comments
I'm not entirely sure what you're suggesting, but I use this trick for ART as well since I rebind the default allocators after the zygote has been forked for the first time (from an immix allocator pointing to the zygote space to whatever the collector requires for their default space). |
In simple terms, I am suggesting fn common_release_mutator(...) {
for allocator in mutator.all_allocators() {
allocator.release();
}
}
fn semispace_release_mutator(...) {
mutator.allocators.bump_allocators[0].rebind(semispace.get_to_space());
common_release_mutator(...);
} So that
This behavior is interesting. Maybe it is specific to Zygote space. But it is interesting that we can implement it this way. |
We can rethink about the safety in some of the methods, e.g. allowing panic does not mean the function is not safe. If we want to use |
The following methods are labelled as
unsafe
:And those functions are called in many places. (Actually only
Allocators::get_allocator_mut
is properly used. The rest are only used in wrappers or tests.)immix_mutator_release
. It gets the appropriate allocators and callrelease
orreset
functions.alloc
andpost_alloc
functions (5 call sites) ofMutator
. Users callalloc
andpost_alloc
withAllocatorSemantics
. The first thing those alloc functions do is looking up the proper allocator (as&dyn Allocator
), and then it callsAllocator::alloc
(with dynamic dispatch).Mutator::on_destroy
. It iterates through all allocators and callon_mutator_destroy
.Why are they unsafe?
Those functions all serve the purpose of getting an allocator from a given
AllocatorSelector
. They can't guarantee to return an allocator becauseAllocatorSelector
may not always be valid. It may select an allocator that does not exist for the current Plan.Allocators
struct holds allocators in[MaybeUninit<T>; MAX_T_ALLOCATOR]
whereT
is the allocator type. The raw array does not record the number of elements "pushed" into the array, andMaybeUninit
has no way to check if it is initialized at run time.If #1318 is fixed, the
Allocators
struct will be able to hold the concreteAllocator
instances in vectors. Then we will be able to useVec::get
to return anOption<&allocator>
which gracefully handles invalidAllocatorSelector
and solves both problems above.Impacts on allocation site.
Mutator::alloc
and related functions currently contain the following call site:After the change,
get_allocator_mut
will return anOption<&dyn Allocator>
. It will becomeThis involves an extra
unwrap()
operation. But I assume the cost of this is trivial compared to theallocator_mapping
look-up and the dynamic dispatching. Any VM binding that cares about performance should have inlined the allocation fast path, and used theBumpPointer
directly instead of relying on those dynamism. In my opinion, it is not worth trade safety for such trivial performance gain in uninlined code.Regarding mutator prepare/release functions
It could be possible to simply iterate through all Allocators using for loops (which becomes possible because we are now using
Vec
with no uninitialized elements) and call their prepare/release/end_of_gc methods. (Note that currentlyMutator::on_destroy
is doing this indirectly viaMutators::get_all_allocator_selectors()
.) This should be enough to handle most plans. And this should make thecommon_release_func
introduced in #1308 easier to implement.One exception is SemiSpace which needs to rebind the
BumpAllocator
with a different space. This can be handled specially.The text was updated successfully, but these errors were encountered: