提交 4db6420a 编写于 作者: S stefank

8058563: InstanceKlass::_dependencies list isn't cleared from empty nmethodBucket entries

Reviewed-by: mgerdin, vlivanov
上级 295f7ff9
...@@ -1619,7 +1619,11 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) { ...@@ -1619,7 +1619,11 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
// During GC the is_alive closure is non-NULL, and is used to // During GC the is_alive closure is non-NULL, and is used to
// determine liveness of dependees that need to be updated. // determine liveness of dependees that need to be updated.
if (is_alive == NULL || klass->is_loader_alive(is_alive)) { if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
InstanceKlass::cast(klass)->remove_dependent_nmethod(this); // The GC defers deletion of this entry, since there might be multiple threads
// iterating over the _dependencies graph. Other call paths are single-threaded
// and may delete it immediately.
bool delete_immediately = is_alive == NULL;
InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately);
} }
} }
} }
......
...@@ -5045,12 +5045,8 @@ class G1KlassCleaningTask : public StackObj { ...@@ -5045,12 +5045,8 @@ class G1KlassCleaningTask : public StackObj {
public: public:
void clean_klass(InstanceKlass* ik) { void clean_klass(InstanceKlass* ik) {
ik->clean_implementors_list(_is_alive); ik->clean_weak_instanceklass_links(_is_alive);
ik->clean_method_data(_is_alive);
// G1 specific cleanup work that has
// been moved here to be done in parallel.
ik->clean_dependent_nmethods();
if (JvmtiExport::has_redefined_a_class()) { if (JvmtiExport::has_redefined_a_class()) {
InstanceKlass::purge_previous_versions(ik); InstanceKlass::purge_previous_versions(ik);
} }
......
...@@ -1969,7 +1969,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { ...@@ -1969,7 +1969,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
// find a corresponding bucket otherwise there's a bug in the // find a corresponding bucket otherwise there's a bug in the
// recording of dependecies. // recording of dependecies.
// //
void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
assert_locked_or_safepoint(CodeCache_lock); assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = _dependencies; nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL; nmethodBucket* last = NULL;
...@@ -1978,7 +1978,17 @@ void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { ...@@ -1978,7 +1978,17 @@ void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
int val = b->decrement(); int val = b->decrement();
guarantee(val >= 0, err_msg("Underflow: %d", val)); guarantee(val >= 0, err_msg("Underflow: %d", val));
if (val == 0) { if (val == 0) {
set_has_unloaded_dependent(true); if (delete_immediately) {
if (last == NULL) {
_dependencies = b->next();
} else {
last->set_next(b->next());
}
delete b;
} else {
// The deletion of this entry is deferred until a later, potentially parallel GC phase.
set_has_unloaded_dependent(true);
}
} }
return; return;
} }
...@@ -2318,6 +2328,13 @@ int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { ...@@ -2318,6 +2328,13 @@ int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
clean_implementors_list(is_alive);
clean_method_data(is_alive);
clean_dependent_nmethods();
}
void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
if (is_interface()) { if (is_interface()) {
......
...@@ -785,7 +785,7 @@ class InstanceKlass: public Klass { ...@@ -785,7 +785,7 @@ class InstanceKlass: public Klass {
// maintenance of deoptimization dependencies // maintenance of deoptimization dependencies
int mark_dependent_nmethods(DepChange& changes); int mark_dependent_nmethods(DepChange& changes);
void add_dependent_nmethod(nmethod* nm); void add_dependent_nmethod(nmethod* nm);
void remove_dependent_nmethod(nmethod* nm); void remove_dependent_nmethod(nmethod* nm, bool delete_immediately);
// On-stack replacement support // On-stack replacement support
nmethod* osr_nmethods_head() const { return _osr_nmethods_head; }; nmethod* osr_nmethods_head() const { return _osr_nmethods_head; };
...@@ -974,6 +974,7 @@ class InstanceKlass: public Klass { ...@@ -974,6 +974,7 @@ class InstanceKlass: public Klass {
void oop_follow_contents(oop obj); void oop_follow_contents(oop obj);
int oop_adjust_pointers(oop obj); int oop_adjust_pointers(oop obj);
void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
void clean_implementors_list(BoolObjectClosure* is_alive); void clean_implementors_list(BoolObjectClosure* is_alive);
void clean_method_data(BoolObjectClosure* is_alive); void clean_method_data(BoolObjectClosure* is_alive);
void clean_dependent_nmethods(); void clean_dependent_nmethods();
......
...@@ -454,8 +454,7 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive ...@@ -454,8 +454,7 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
// Clean the implementors list and method data. // Clean the implementors list and method data.
if (clean_alive_klasses && current->oop_is_instance()) { if (clean_alive_klasses && current->oop_is_instance()) {
InstanceKlass* ik = InstanceKlass::cast(current); InstanceKlass* ik = InstanceKlass::cast(current);
ik->clean_implementors_list(is_alive); ik->clean_weak_instanceklass_links(is_alive);
ik->clean_method_data(is_alive);
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册