8319955: Improve dependencies removal during class unloading
Reviewed-by: dholmes, eosterlund
This commit is contained in:
parent
4c1540baa6
commit
fbe19378c3
@ -111,8 +111,7 @@ void DependencyContext::add_dependent_nmethod(nmethod* nm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DependencyContext::release(nmethodBucket* b) {
|
void DependencyContext::release(nmethodBucket* b) {
|
||||||
bool expunge = Atomic::load(&_cleaning_epoch) == 0;
|
if (delete_on_release()) {
|
||||||
if (expunge) {
|
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
delete b;
|
delete b;
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
@ -178,9 +177,41 @@ nmethodBucket* DependencyContext::release_and_get_next_not_unloading(nmethodBuck
|
|||||||
//
|
//
|
||||||
// Invalidate all dependencies in the context
|
// Invalidate all dependencies in the context
|
||||||
void DependencyContext::remove_all_dependents() {
|
void DependencyContext::remove_all_dependents() {
|
||||||
nmethodBucket* b = dependencies_not_unloading();
|
// Assume that the dependency is not deleted immediately but moved into the
|
||||||
|
// purge list when calling this.
|
||||||
|
assert(!delete_on_release(), "should not delete on release");
|
||||||
|
|
||||||
|
nmethodBucket* first = Atomic::load_acquire(_dependency_context_addr);
|
||||||
|
if (first == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nmethodBucket* cur = first;
|
||||||
|
nmethodBucket* last = cur;
|
||||||
|
jlong count = 0;
|
||||||
|
for (; cur != nullptr; cur = cur->next()) {
|
||||||
|
assert(cur->get_nmethod()->is_unloading(), "must be");
|
||||||
|
last = cur;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the whole list to the purge list at once.
|
||||||
|
nmethodBucket* old_purge_list_head = Atomic::load(&_purge_list);
|
||||||
|
for (;;) {
|
||||||
|
last->set_purge_list_next(old_purge_list_head);
|
||||||
|
nmethodBucket* next_purge_list_head = Atomic::cmpxchg(&_purge_list, old_purge_list_head, first);
|
||||||
|
if (old_purge_list_head == next_purge_list_head) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
old_purge_list_head = next_purge_list_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UsePerfData) {
|
||||||
|
_perf_total_buckets_stale_count->inc(count);
|
||||||
|
_perf_total_buckets_stale_acc_count->inc(count);
|
||||||
|
}
|
||||||
|
|
||||||
set_dependencies(nullptr);
|
set_dependencies(nullptr);
|
||||||
assert(b == nullptr, "All dependents should be unloading");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DependencyContext::remove_and_mark_for_deoptimization_all_dependents(DeoptimizationScope* deopt_scope) {
|
void DependencyContext::remove_and_mark_for_deoptimization_all_dependents(DeoptimizationScope* deopt_scope) {
|
||||||
@ -234,6 +265,10 @@ bool DependencyContext::claim_cleanup() {
|
|||||||
return Atomic::cmpxchg(_last_cleanup_addr, last_cleanup, cleaning_epoch) == last_cleanup;
|
return Atomic::cmpxchg(_last_cleanup_addr, last_cleanup, cleaning_epoch) == last_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DependencyContext::delete_on_release() {
|
||||||
|
return Atomic::load(&_cleaning_epoch) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve the first nmethodBucket that has a dependent that does not correspond to
|
// Retrieve the first nmethodBucket that has a dependent that does not correspond to
|
||||||
// an is_unloading nmethod. Any nmethodBucket entries observed from the original head
|
// an is_unloading nmethod. Any nmethodBucket entries observed from the original head
|
||||||
// that is_unloading() will be unlinked and placed on the purge list.
|
// that is_unloading() will be unlinked and placed on the purge list.
|
||||||
|
@ -75,6 +75,7 @@ class DependencyContext : public StackObj {
|
|||||||
volatile uint64_t* _last_cleanup_addr;
|
volatile uint64_t* _last_cleanup_addr;
|
||||||
|
|
||||||
bool claim_cleanup();
|
bool claim_cleanup();
|
||||||
|
static bool delete_on_release();
|
||||||
void set_dependencies(nmethodBucket* b);
|
void set_dependencies(nmethodBucket* b);
|
||||||
nmethodBucket* dependencies();
|
nmethodBucket* dependencies();
|
||||||
nmethodBucket* dependencies_not_unloading();
|
nmethodBucket* dependencies_not_unloading();
|
||||||
|
Loading…
Reference in New Issue
Block a user