8220343: Move scavenge_root_nmethods from shared code

Reviewed-by: kvn, eosterlund
This commit is contained in:
Stefan Karlsson 2019-03-14 09:15:51 +01:00
parent 3796014d86
commit 2370adc703
32 changed files with 521 additions and 399 deletions

View file

@ -145,7 +145,6 @@ class CodeBlob_sizes {
address CodeCache::_low_bound = 0;
address CodeCache::_high_bound = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
ExceptionCache* volatile CodeCache::_exception_cache_purge_list = NULL;
// Initialize arrays of CodeHeap subsets
@ -711,167 +710,6 @@ void CodeCache::blobs_do(CodeBlobClosure* f) {
}
}
// Walk the list of methods which might contain oops to the java heap.
void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
const bool fix_relocations = f->fix_relocations();
debug_only(mark_scavenge_root_nmethods());
nmethod* prev = NULL;
nmethod* cur = scavenge_root_nmethods();
while (cur != NULL) {
debug_only(cur->clear_scavenge_root_marked());
assert(cur->scavenge_root_not_marked(), "");
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
bool is_live = (!cur->is_zombie() && !cur->is_unloaded());
LogTarget(Trace, gc, nmethod) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
CompileTask::print(&ls, cur,
is_live ? "scavenge root " : "dead scavenge root", /*short_form:*/ true);
}
if (is_live) {
// Perform cur->oops_do(f), maybe just once per nmethod.
f->do_code_blob(cur);
}
nmethod* const next = cur->scavenge_root_link();
// The scavengable nmethod list must contain all methods with scavengable
// oops. It is safe to include more nmethod on the list, but we do not
// expect any live non-scavengable nmethods on the list.
if (fix_relocations) {
if (!is_live || !cur->detect_scavenge_root_oops()) {
unlink_scavenge_root_nmethod(cur, prev);
} else {
prev = cur;
}
}
cur = next;
}
// Check for stray marks.
debug_only(verify_perm_nmethods(NULL));
}
void CodeCache::register_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
if (!nm->on_scavenge_root_list() && nm->detect_scavenge_root_oops()) {
add_scavenge_root_nmethod(nm);
}
}
void CodeCache::verify_scavenge_root_nmethod(nmethod* nm) {
nm->verify_scavenge_root_oops();
}
void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
nm->set_on_scavenge_root_list();
nm->set_scavenge_root_link(_scavenge_root_nmethods);
set_scavenge_root_nmethods(nm);
print_trace("add_scavenge_root", nm);
}
void CodeCache::unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev) {
assert_locked_or_safepoint(CodeCache_lock);
assert((prev == NULL && scavenge_root_nmethods() == nm) ||
(prev != NULL && prev->scavenge_root_link() == nm), "precondition");
print_trace("unlink_scavenge_root", nm);
if (prev == NULL) {
set_scavenge_root_nmethods(nm->scavenge_root_link());
} else {
prev->set_scavenge_root_link(nm->scavenge_root_link());
}
nm->set_scavenge_root_link(NULL);
nm->clear_on_scavenge_root_list();
}
void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
print_trace("drop_scavenge_root", nm);
nmethod* prev = NULL;
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
if (cur == nm) {
unlink_scavenge_root_nmethod(cur, prev);
return;
}
prev = cur;
}
assert(false, "should have been on list");
}
void CodeCache::prune_scavenge_root_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
debug_only(mark_scavenge_root_nmethods());
nmethod* last = NULL;
nmethod* cur = scavenge_root_nmethods();
while (cur != NULL) {
nmethod* next = cur->scavenge_root_link();
debug_only(cur->clear_scavenge_root_marked());
assert(cur->scavenge_root_not_marked(), "");
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
if (!cur->is_zombie() && !cur->is_unloaded()
&& cur->detect_scavenge_root_oops()) {
// Keep it. Advance 'last' to prevent deletion.
last = cur;
} else {
// Prune it from the list, so we don't have to look at it any more.
print_trace("prune_scavenge_root", cur);
unlink_scavenge_root_nmethod(cur, last);
}
cur = next;
}
// Check for stray marks.
debug_only(verify_perm_nmethods(NULL));
}
#ifndef PRODUCT
void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
// While we are here, verify the integrity of the list.
mark_scavenge_root_nmethods();
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
cur->clear_scavenge_root_marked();
}
verify_perm_nmethods(f);
}
// Temporarily mark nmethods that are claimed to be on the scavenge list.
void CodeCache::mark_scavenge_root_nmethods() {
NMethodIterator iter(NMethodIterator::only_alive);
while(iter.next()) {
nmethod* nm = iter.method();
assert(nm->scavenge_root_not_marked(), "clean state");
if (nm->on_scavenge_root_list())
nm->set_scavenge_root_marked();
}
}
// If the closure is given, run it on the unlisted nmethods.
// Also make sure that the effects of mark_scavenge_root_nmethods is gone.
void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) {
NMethodIterator iter(NMethodIterator::only_alive);
while(iter.next()) {
nmethod* nm = iter.method();
bool call_f = (f_or_null != NULL);
assert(nm->scavenge_root_not_marked(), "must be already processed");
if (nm->on_scavenge_root_list())
call_f = false; // don't show this one to the client
Universe::heap()->verify_nmethod(nm);
if (call_f) f_or_null->do_code_blob(nm);
}
}
#endif //PRODUCT
void CodeCache::verify_clean_inline_caches() {
#ifdef ASSERT
NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
@ -929,12 +767,6 @@ void CodeCache::purge_exception_caches() {
_exception_cache_purge_list = NULL;
}
void CodeCache::gc_prologue() { }
void CodeCache::gc_epilogue() {
prune_scavenge_root_nmethods();
}
uint8_t CodeCache::_unloading_cycle = 1;
void CodeCache::increment_unloading_cycle() {