diff --git a/src/hotspot/share/ci/ciInstanceKlass.cpp b/src/hotspot/share/ci/ciInstanceKlass.cpp index 5c65ffff3ac..2346f0d027d 100644 --- a/src/hotspot/share/ci/ciInstanceKlass.cpp +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp @@ -72,7 +72,7 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) : // by the GC but need to be strong roots if reachable from a current compilation. // InstanceKlass are created for both weak and strong metadata. Ensuring this metadata // alive covers the cases where there are weak roots without performance cost. - oop holder = ik->holder_phantom(); + oop holder = ik->klass_holder(); if (ik->is_anonymous()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep // VM anonymous classes alive (loader == NULL). Klass holder should be used instead. diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index 45c938c8929..2d1830bc895 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -692,6 +692,15 @@ oop ClassLoaderData::holder_phantom() const { } } +// Let the GC read the holder without keeping it alive. +oop ClassLoaderData::holder_no_keepalive() const { + if (!_holder.is_null()) { // NULL class_loader + return _holder.peek(); + } else { + return NULL; + } +} + // Unloading support bool ClassLoaderData::is_alive() const { bool alive = keep_alive() // null class loader and incomplete anonymous klasses. diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp index 730feeef812..7d64d23d649 100644 --- a/src/hotspot/share/classfile/classLoaderData.hpp +++ b/src/hotspot/share/classfile/classLoaderData.hpp @@ -287,12 +287,13 @@ class ClassLoaderData : public CHeapObj { void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = true; } void clear_accumulated_modified_oops() { _accumulated_modified_oops = false; } bool has_accumulated_modified_oops() { return _accumulated_modified_oops; } - private: + oop holder_no_keepalive() const; + oop holder_phantom() const; + private: void unload(); bool keep_alive() const { return _keep_alive > 0; } - oop holder_phantom() const; void classes_do(void f(Klass* const)); void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); diff --git a/src/hotspot/share/classfile/classLoaderData.inline.hpp b/src/hotspot/share/classfile/classLoaderData.inline.hpp index 4e9223221af..a77ff426a4f 100644 --- a/src/hotspot/share/classfile/classLoaderData.inline.hpp +++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp @@ -33,7 +33,7 @@ inline oop ClassLoaderData::class_loader() const { assert(!_unloading, "This oop is not available to unloading class loader data"); - assert(_holder.is_null() || _holder.peek() != NULL , "This class loader data holder must be alive"); + assert(_holder.is_null() || holder_no_keepalive() != NULL , "This class loader data holder must be alive"); return _class_loader.resolve(); } diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index 98a2fe7f1c3..367ef2a6d8e 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -165,7 +165,7 @@ void G1FullGCMarker::drain_stack() { } inline void G1FullGCMarker::follow_klass(Klass* k) { - oop op = k->klass_holder(); + oop op = k->class_loader_data()->holder_no_keepalive(); mark_and_push(&op); } diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp index f5f7201af4b..6daa8a4dd60 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp @@ -93,7 +93,7 @@ inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p) { do_ inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } inline void ParCompactionManager::follow_klass(Klass* klass) { - oop holder = klass->klass_holder(); + oop holder = klass->class_loader_data()->holder_no_keepalive(); mark_and_push(&holder); } diff --git a/src/hotspot/share/gc/serial/markSweep.inline.hpp b/src/hotspot/share/gc/serial/markSweep.inline.hpp index 25a5a315fce..39a35037427 100644 --- a/src/hotspot/share/gc/serial/markSweep.inline.hpp +++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp @@ -58,7 +58,7 @@ template inline void MarkSweep::mark_and_push(T* p) { } inline void MarkSweep::follow_klass(Klass* klass) { - oop op = klass->klass_holder(); + oop op = klass->class_loader_data()->holder_no_keepalive(); MarkSweep::mark_and_push(&op); } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 7b0622961f3..28199eebce2 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -49,14 +49,14 @@ JVMCIKlassHandle::JVMCIKlassHandle(Thread* thread, Klass* klass) { _thread = thread; _klass = klass; if (klass != NULL) { - _holder = Handle(_thread, klass->holder_phantom()); + _holder = Handle(_thread, klass->klass_holder()); } } JVMCIKlassHandle& JVMCIKlassHandle::operator=(Klass* klass) { _klass = klass; if (klass != NULL) { - _holder = Handle(_thread, klass->holder_phantom()); + _holder = Handle(_thread, klass->klass_holder()); } return *this; } diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index c81e45a8942..d0bbcd45a42 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -680,12 +680,6 @@ class InstanceKlass: public Klass { } } - // Oop that keeps the metadata for this class from being unloaded - // in places where the metadata is stored in other places, like nmethods - oop klass_holder() const { - return is_anonymous() ? java_mirror() : class_loader(); - } - bool is_contended() const { return (_misc_flags & _misc_is_contended) != 0; } diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 4b97cf7eb2c..5ee432a966f 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -393,10 +393,6 @@ void Klass::append_to_sibling_list() { debug_only(verify();) } -oop Klass::holder_phantom() const { - return class_loader_data()->holder_phantom(); -} - void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses) { if (!ClassUnloading || !unloading_occurred) { return; diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 3ade5867a66..af7a198d7bd 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -506,7 +506,11 @@ class Klass : public Metadata { oop class_loader() const; - virtual oop klass_holder() const { return class_loader(); } + // This loads the klass's holder as a phantom. This is useful when a weak Klass + // pointer has been "peeked" and then must be kept alive before it may + // be used safely. All uses of klass_holder need to apply the appropriate barriers, + // except during GC. + oop klass_holder() const { return class_loader_data()->holder_phantom(); } protected: virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); @@ -657,11 +661,6 @@ class Klass : public Metadata { // Klass is considered alive. Has already been marked as unloading. bool is_loader_alive() const { return !class_loader_data()->is_unloading(); } - // Load the klass's holder as a phantom. This is useful when a weak Klass - // pointer has been "peeked" and then must be kept alive before it may - // be used safely. - oop holder_phantom() const; - static void clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses = true); static void clean_subklass_tree() { clean_weak_klass_links(/*unloading_occurred*/ true , /* clean_alive_klasses */ false);