-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8291718: Remove mark_for_deoptimization from klass unloading #9713
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
Conversation
|
👋 Welcome back xmas92! A progress list of the required criteria for merging this PR into |
Webrevs
|
fisk
left a comment
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.
Looks good.
|
@xmas92 This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 107 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@fisk, @dean-long) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
| set_dependencies(NULL); | ||
| int removed = 0; | ||
| while (b != NULL) { | ||
| b = release_and_get_next_not_unloading(b); |
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.
If we are being called by class unloading, finding an nmethod with nm->is_alive() returning true would be fatal, wouldn't it? Could we make it clear this function is used for unloading, and add an assert that !nm->is_alive() && nm->has_flushed_dependencies()?
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 are correct that nm should all be at least unloading, as if a klass is unloading all dependent nmethods should be unloading. So this code should boil down to:
void DependencyContext::remove_all_dependents() {
nmethodBucket* b = dependencies_not_unloading();
set_dependencies(NULL);
assert(b == nullptr, "All dependents should be unloading");
}As dependencies_not_unloading() will unlink and release every dependent that is unloading.
Have run stress tests on that change and no violations were found.
Will push and test this change.
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 are correct that nm should all be at least
unloading, as if a klass is unloading all dependentnmethodsshould be unloading. So this code should boil down to:void DependencyContext::remove_all_dependents() { nmethodBucket* b = dependencies_not_unloading(); set_dependencies(NULL); assert(b == nullptr, "All dependents should be unloading"); }As
dependencies_not_unloading()will unlink and release every dependent that isunloading. Have run stress tests on that change and no violations were found. Will push and test this change.
From testing this seems not to be the case. Will investigate some more. So there are dependents that do no become unloading when the klass unloads.
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 would like to find out more in detail what you want to ensure, or situation you are afraid that might occur.
I've tried to investigate what types of dependent nmethods are not unloading when the the klass with a dependency is unloaded. I suspect it has to do with class loading and compilation order. From what I understand the nmethod will only be unloading if it has a reference to a dead oop inside it. So the compiler must generate code which is dependent without having an oop baked in.
I do find it difficult to reason about the lifetime of these dependencies (at least the logical part, the release, purge cycle of the memory seems pretty straight forward) and nmethods (the sweeper removal does make the nmethod lifecycle a lot easier to reason about tough).
I am really interested in what you think. As this change is just always running an edge case which can happen in mainline. This just makes it default. Hotspot seems to have relied on this interaction being this way for some time.
The windows machines finally woke up and the patch passed tier 1-7
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.
My concern was that we could be removing the dependencies from nmethods that are still using them. But if that was the case, the old code would have the same problem.
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.
The compiler dependencies are protecting against loading of a class that is a subtype of X. If X is unloaded, then we can be pretty sure nobody is going to load a subclass of X.
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.
Isn't there something we can assert about the state of these nmethods? Maybe unlinked and !in_use?
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.
Seems like the culprit it CodeCache::UnloadingScope. Currently the CodeCache::UnloadingScope does not encompass the klass unloading (different for each GC, some do some don't). Only the CodeCache unloading. This means that the is_unloading data is not up to date.
After modifying serial to have the UnloadingScope covering both klass unloading and nmethod unloading this code seems to work.
void DependencyContext::remove_all_dependents() {
nmethodBucket* b = dependencies_not_unloading();
set_dependencies(NULL);
assert(b == nullptr, "All dependents should be unloading");
}The options here are to either fix the scopes for all GCs so it covers both, or introduce a slow is_unloading for the assert which does not use the cached unloading value. The second option still need to be GC aware as it requires the GCs notion of is_alive. The first option seems the best as it will be more correct with respect to the internal vm state. It will probably be better at catching future bugs as well.
|
The perf counters were double counting some deallocations. The release and purge code was already handling it. This code would just double count any |
|
Extended the UnloadingScope. |
|
Tier 1-7 testing done. |
|
/integrate |
|
/sponsor |
|
Going to push as commit fd4b2f2.
Your commit was automatically rebased without conflicts. |
@stefank suggested creating a separate issue for this part of JDK-8291237
Description from the original issue:
Testing: Tier 1-7
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/9713/head:pull/9713$ git checkout pull/9713Update a local copy of the PR:
$ git checkout pull/9713$ git pull https://git.openjdk.org/jdk pull/9713/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 9713View PR using the GUI difftool:
$ git pr show -t 9713Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/9713.diff