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

Tidy up mutator scan API #875

Merged
merged 7 commits into from
Aug 9, 2023
Merged

Conversation

qinsoon
Copy link
Member

@qinsoon qinsoon commented Jul 31, 2023

This PR closes #496.

  • Remove Scanning::SCAN_MUTATORS_IN_SAFEPOINT, and Scanning::SINGLE_THREAD_MUTATOR_SCANNING.
  • Remove Scanning::scan_roots_in_all_mutator_threads.
  • Remove Collection::prepare_mutator
  • Update comments for a few methods

* Remove Scanning::SCAN_MUTATORS_IN_SAFEPOINT, and Scanning::SINGLE_THREAD_MUTATOR_SCANNING.
* Remove Scanning::scan_roots_in_all_mutator_threads.
* Remove Collection::prepare_mutator
* Update comments for a few methods
@k-sareen
Copy link
Collaborator

I also just realized that the GC state is never updated to GcProper in case the binding does not use the callback and does not implement scan_roots_in_mutator_thread , i.e. the case where the binding prefers not to or cannot differentiate stack roots from other kinds of roots. It's not a big deal, but thought I'd mention it

@qinsoon
Copy link
Member Author

qinsoon commented Jul 31, 2023

I also just realized that the GC state is never updated to GcProper in case the binding does not use the callback and does not implement scan_roots_in_mutator_thread , i.e. the case where the binding prefers not to or cannot differentiate stack roots from other kinds of roots. It's not a big deal, but thought I'd mention it

Right. We should require the binding to use the callback. Bindings should use the callback, but do not have to implement scan_roots_in_mutator_thread.

@k-sareen
Copy link
Collaborator

That feels like a bit of a waste though? We'll end up scheduling empty ScanStackRoot work packets

@k-sareen
Copy link
Collaborator

k-sareen commented Aug 1, 2023

But I also realized that if the binding doesn't execute the ScanStackRoot work packets, then the remembered sets for mutators won't be flushed

@k-sareen
Copy link
Collaborator

k-sareen commented Aug 1, 2023

Perhaps we should just flush the mutators in prepare_mutator instead of doing it in the ScanStackRoot work packet

It should fix a crash in JikesRVM caused by overflown stack overwriting
objects in the VM space.
@qinsoon qinsoon marked this pull request as ready for review August 7, 2023 05:50
@qinsoon qinsoon requested a review from wks August 7, 2023 05:51
Copy link
Collaborator

@k-sareen k-sareen left a comment

Choose a reason for hiding this comment

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

My understanding of the discussion was that if the binding/VM can't tell us when its threads are ready for scanning, then we should still provide a way to flush each mutator. Or is that the binding's job? If it is, then it should be documented.

src/vm/collection.rs Outdated Show resolved Hide resolved
@qinsoon
Copy link
Member Author

qinsoon commented Aug 7, 2023

My understanding of the discussion was that if the binding/VM can't tell us when its threads are ready for scanning, then we should still provide a way to flush each mutator. Or is that the binding's job? If it is, then it should be documented.

I think we conclude that a binding will tell us when the thread is ready to be scanned. It can tell us as soon as a thread is stopped, or after all the threads are stopped. But the binding has to tell us that.

Flushing mutator is not a binding's job. MMTk will do that. We require a binding to tell us if a thread can be scanned, and we schedule ScanStackRoot for the thread. In ScanStackRoot, we ask the binding for stack roots, and also flush mutators.

@k-sareen
Copy link
Collaborator

k-sareen commented Aug 7, 2023

Right. I'm getting hung up on the case where the binding/VM doesn't differentiate between thread roots and other kinds of roots. In that case the binding will just dump all roots into the scan_vm_specific_roots function. But that won't flush mutators unless the binding also creates empty ScanStackRoot work packets by using the callback in stop_all_mutators.

Also can we rename the ScanStackRoot work packet while we're at it? It's ambiguous. Renaming to ScanStackRoots (given that we're removing the ScanStackRoots work packet) or ScanStackRootsForMutator would be better imo.

Comment on lines +185 to +186
// TODO: The stack scanning work won't start immediately, as the `Prepare` bucket is not opened yet (the bucket is opened in notify_mutators_paused).
// Should we push to Unconstrained instead?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Someone may want some work to be done before scanning any stacks, but currently there is no such things. For Ruby, "potential pinning parents" (PPP) needs to be handled before transitive closure, but can be done at the same time as stack scanning.

We also had some issue letting OpenJDK report the yielding of individual threads. See mmtk/openjdk#9 There used to be something called report_java_thread_yield, but we removed that. So the current status is that OpenJDK can only report that all threads have come to a stop.

I think we can leave the code as is for now. After we figure out how to report the yielding of each thread (for OpenJDK 11, 17 and 22), we can make another attempt and move the ScanStackRoot work packet to Unconstrained or another bucket.

Copy link
Collaborator

Choose a reason for hiding this comment

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

There is the prepare_mutator function for VM-specific behaviour. But this PR would remove that.

Copy link
Member Author

@qinsoon qinsoon Aug 7, 2023

Choose a reason for hiding this comment

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

Someone may want some work to be done before scanning any stacks, but currently there is no such things. For Ruby, "potential pinning parents" (PPP) needs to be handled before transitive closure, but can be done at the same time as stack scanning.

The binding can do whatever work is needed before it tells MMTk that the thread is ready. For the Ruby case, the binding can just schedule the PPP work to a bucket prior to the Closure bucket.

Copy link
Member Author

Choose a reason for hiding this comment

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

There is the prepare_mutator function for VM-specific behaviour. But this PR would remove that.

Yeah. I think it is confusing about when we should invoke it. For the old timing where we call prepare_mutator, the binding can do it before returning stop_all_mutators. JikesRVM is the only binding we know that uses the method. I changed it to https://github.com/mmtk/mmtk-jikesrvm/pull/147/files#diff-54f4f04a18788baf9bf66cff8c4256151b680087e3490fb8e8f62e2d60ad9fabR30.

@wks
Copy link
Collaborator

wks commented Aug 7, 2023

Also can we rename the ScanStackRoot work packet while we're at it? It's ambiguous. Renaming to ScanStackRoots (given that we're removing the ScanStackRoots work packet) or ScanStackRootsForMutator would be better imo.

I would suggest simply calling it ScanMutatorRoots. It's not only stack roots, but may include other thread-local states as well. For example, for OpenJDK, it calls JavaThread::oops_do which scans not only Java frames, but also thread-local JNI handles, pending exceptions, monitors, etc.

src/vm/collection.rs Outdated Show resolved Hide resolved
@qinsoon
Copy link
Member Author

qinsoon commented Aug 8, 2023

Also can we rename the ScanStackRoot work packet while we're at it? It's ambiguous. Renaming to ScanStackRoots (given that we're removing the ScanStackRoots work packet) or ScanStackRootsForMutator would be better imo.

I would suggest simply calling it ScanMutatorRoots. It's not only stack roots, but may include other thread-local states as well. For example, for OpenJDK, it calls JavaThread::oops_do which scans not only Java frames, but also thread-local JNI handles, pending exceptions, monitors, etc.

I have renamed the packet to ScanMutatorRoots.

src/vm/scanning.rs Outdated Show resolved Hide resolved
qinsoon and others added 2 commits August 8, 2023 18:26
Copy link
Collaborator

@wks wks left a comment

Choose a reason for hiding this comment

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

LGTM. But bindings need to adapt to this change, too.

@qinsoon qinsoon merged commit 04a47fe into mmtk:master Aug 9, 2023
qinsoon added a commit to mmtk/mmtk-jikesrvm that referenced this pull request Aug 9, 2023
qinsoon added a commit to mmtk/mmtk-openjdk that referenced this pull request Aug 9, 2023
qinsoon added a commit to mmtk/mmtk-julia that referenced this pull request Aug 9, 2023
wenyuzhao pushed a commit to wenyuzhao/mmtk-core that referenced this pull request Aug 17, 2023
This PR closes mmtk#496.
* Remove Scanning::SCAN_MUTATORS_IN_SAFEPOINT, and
Scanning::SINGLE_THREAD_MUTATOR_SCANNING.
* Remove Scanning::scan_roots_in_all_mutator_threads.
* Remove Collection::prepare_mutator
* Update comments for a few methods
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.

Clarify stack root scanning in API
3 participants