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

Precise heap traversal API #1186

Open
qinsoon opened this issue Aug 12, 2024 · 2 comments
Open

Precise heap traversal API #1186

qinsoon opened this issue Aug 12, 2024 · 2 comments
Labels
A-heap Area: Heap (including Mmapper, VMMap) A-interface Area: Interface/API

Comments

@qinsoon
Copy link
Member

qinsoon commented Aug 12, 2024

#1174 introduced an API that allows heap traversal. The API will enumerate objects based on the VO bit at the time of enumeration. So if there is GC or allocation going on at the same time, we may see objects being reclaimed, or missing objects. We may want a version of the API that blocks allocation and GC so we can have a consistent heap snapshot.

@qinsoon qinsoon added A-interface Area: Interface/API A-heap Area: Heap (including Mmapper, VMMap) labels Aug 12, 2024
@wks
Copy link
Collaborator

wks commented Aug 19, 2024

The heap traversal API introduced in #1174 requires that the invocation of MMTK::enumerate_objects does not happen concurrently with allocation or GC, or it has undefined behavior. This means if the VM binding uses that API, the VM binding must block allocation and GC, and, as a result, the heap traversal must be consistent.

It is arguable that since mmtk-core can call Collection::stop_all_mutators and Collection::resume_mutators, mmtk-core can provide an API that automatically blocks all mutator activities and enumerate objects at a time when it is guaranteed not to race with allocation or GC. While the API can be convenient to use, it increases the complexity of the overall MMTk-binding API in some ways:

  • The API Collection::stop_all_mutators will also need a parameter to tell the VM binding what is the purpose of the current stop-the-world. (Alternatively, the MMTK struct of the Plan should provide a method fn current_stw_purpose() -> STWPurpose where STWPurpose::GC means it is for GC, while STWPurpose::Traversal means heap traversal.) Some VM bindings need to do extra preparation when the GC starts. For example, if the current GC is a copying GC, the Ruby binding will need to pin all the children of "potential pinning parents" (PPPs). But if mmtk-core is requesting a stop-the-world for traversing the heap, the pinning is unnecessary.
  • VMs which don't need heap traversal will be aware of such STW requests.

And the caller of the "precise" traversal API (say MMTK::enumerate_objects_precise), still needs to ensure the current thread is in GC safepoint (i.e. has yielded). This is the same as using the API in #1174 which has undefined behavior if there are races.

Implementation-wise, mmtk-core will need another "WorkerGoal::HeapTraversal" as the reason to stop the world, and we will need something like schedule_collection to schedule the invocation of Collection::stop_all_mutators and Collection::resume_mutators (which are supposed to be called by GC workers) in the appropriate work packets (which are currently all designed for GC, not heap traversal). On the contrary, if the VM already has a nice safepoint synchronization mechanism, it can stop all mutators and invoke MMTK::enumerate_objects quite trivially. For example, in OpenJDK, it only needs to make a new VMOperation and let the "VM thread" run it. The VM will automatically stop mutators at safepoints and let the VM thread run MMTK::enumerate_objects.

So I don't see the advantage of letting mmtk-core provide a heap-traversal API that stops/resumes mutators for the binding. The binding can stop/resume mutators (if it has multiple mutators at all) by itself and it's probably easier.

@k-sareen
Copy link
Collaborator

I think we're bikeshedding the issue, personally. The idea is that this is an expensive operation and VM developers essentially need to be cognizant of that. We don't need a separate API to pause the mutators or even have a separate function for enumerating objects. Just need to have a separate GC "type" essentially wherein we only have one work packet in it which is a heap traversal work packet that will use the visitor provided in the enumerate_objects API. I think this should be simple and non-controversial to implement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-heap Area: Heap (including Mmapper, VMMap) A-interface Area: Interface/API
Projects
None yet
Development

No branches or pull requests

3 participants