8210330: Make CLD claiming allow multiple claim bits

Reviewed-by: pliden, coleenp
This commit is contained in:
Erik Österlund 2018-10-16 13:16:11 +02:00
parent 782fa608d2
commit e39c5811b5
23 changed files with 68 additions and 53 deletions

View File

@ -139,7 +139,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous
// it from being unloaded during parsing of the unsafe anonymous class.
// The null-class-loader should always be kept alive.
_keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0),
_claimed(0),
_claim(0),
_handles(),
_klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL),
_jmethod_ids(NULL),
@ -268,12 +268,17 @@ bool ClassLoaderData::ChunkedHandleList::owner_of(oop* oop_handle) {
}
#endif // PRODUCT
bool ClassLoaderData::claim() {
if (_claimed == 1) {
return false;
bool ClassLoaderData::try_claim(int claim) {
for (;;) {
int old_claim = Atomic::load(&_claim);
if ((old_claim & claim) == claim) {
return false;
}
int new_claim = old_claim | claim;
if (Atomic::cmpxchg(new_claim, &_claim, old_claim) == old_claim) {
return true;
}
}
return (int) Atomic::cmpxchg(1, &_claimed, 0) == 0;
}
// Unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive
@ -295,8 +300,8 @@ void ClassLoaderData::dec_keep_alive() {
}
}
void ClassLoaderData::oops_do(OopClosure* f, bool must_claim, bool clear_mod_oops) {
if (must_claim && !claim()) {
void ClassLoaderData::oops_do(OopClosure* f, int claim_value, bool clear_mod_oops) {
if (claim_value != ClassLoaderData::_claim_none && !try_claim(claim_value)) {
return;
}

View File

@ -128,9 +128,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// loader. _keep_alive does not need to be volatile or
// atomic since there is one unique CLD per unsafe anonymous class.
volatile int _claimed; // true if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
// Has to be an int because we cas it.
volatile int _claim; // non-zero if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which
// have the same life cycle of the corresponding ClassLoader.
@ -200,11 +199,22 @@ class ClassLoaderData : public CHeapObj<mtClass> {
Dictionary* create_dictionary();
void initialize_name(Handle class_loader);
public:
// GC interface.
void clear_claimed() { _claimed = 0; }
bool claimed() const { return _claimed == 1; }
bool claim();
// The "claim" is typically used to check if oops_do needs to be applied on
// the CLD or not. Most GCs only perform strong marking during the marking phase.
enum {
_claim_none = 0,
_claim_finalizable = 2,
_claim_strong = 3
};
void clear_claim() { _claim = 0; }
bool claimed() const { return _claim != 0; }
bool try_claim(int claim);
int get_claim() const { return _claim; }
void set_claim(int claim) { _claim = claim; }
// Computes if the CLD is alive or not. This is safe to call in concurrent
// contexts.
@ -264,7 +274,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void initialize_holder(Handle holder);
void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false);
void oops_do(OopClosure* f, int claim_value, bool clear_modified_oops = false);
void classes_do(KlassClosure* klass_closure);
Klass* klasses() { return _klasses; }

View File

@ -48,7 +48,7 @@ volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
void ClassLoaderDataGraph::clear_claimed_marks() {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->clear_claimed();
cld->clear_claim();
}
}

View File

@ -41,8 +41,7 @@ inline void MetadataVisitingOopsInGenClosure::do_klass(Klass* k) {
}
inline void MetadataVisitingOopsInGenClosure::do_cld(ClassLoaderData* cld) {
bool claim = true; // Must claim the class loader data before processing.
cld->oops_do(this, claim);
cld->oops_do(this, ClassLoaderData::_claim_strong);
}
// Decode the oop and call do_oop on it.

View File

@ -2398,7 +2398,7 @@ class VerifyCLDOopsCLDClosure : public CLDClosure {
public:
VerifyCLDOopsCLDClosure(CMSBitMap* bitmap) : _oop_closure(bitmap) {}
void do_cld(ClassLoaderData* cld) {
cld->oops_do(&_oop_closure, false, false);
cld->oops_do(&_oop_closure, ClassLoaderData::_claim_none, false);
}
};
@ -2413,7 +2413,7 @@ void CMSCollector::verify_after_remark_work_2() {
// Mark from roots one level into CMS
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
markBitMap());
CLDToOopClosure cld_closure(&notOlder, true);
CLDToOopClosure cld_closure(&notOlder, ClassLoaderData::_claim_strong);
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
@ -2886,7 +2886,7 @@ void CMSCollector::checkpointRootsInitialWork() {
}
} else {
// The serial version.
CLDToOopClosure cld_closure(&notOlder, true);
CLDToOopClosure cld_closure(&notOlder, ClassLoaderData::_claim_strong);
heap->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
StrongRootsScope srs(1);
@ -4269,7 +4269,7 @@ void CMSParInitialMarkTask::work(uint worker_id) {
_timer.reset();
_timer.start();
CLDToOopClosure cld_closure(&par_mri_cl, true);
CLDToOopClosure cld_closure(&par_mri_cl, ClassLoaderData::_claim_strong);
heap->cms_process_roots(_strong_roots_scope,
false, // yg was scanned above
@ -4331,7 +4331,7 @@ class CMSParRemarkTask: public CMSParMarkTask {
class RemarkCLDClosure : public CLDClosure {
CLDToOopClosure _cm_closure;
public:
RemarkCLDClosure(OopClosure* oop_closure) : _cm_closure(oop_closure) {}
RemarkCLDClosure(OopClosure* oop_closure) : _cm_closure(oop_closure, ClassLoaderData::_claim_strong) {}
void do_cld(ClassLoaderData* cld) {
// Check if we have modified any oops in the CLD during the concurrent marking.
if (cld->has_accumulated_modified_oops()) {

View File

@ -108,7 +108,7 @@ void G1FullGCAdjustTask::work(uint worker_id) {
AlwaysTrueClosure always_alive;
_weak_proc_task.work(worker_id, &always_alive, &_adjust);
CLDToOopClosure adjust_cld(&_adjust);
CLDToOopClosure adjust_cld(&_adjust, ClassLoaderData::_claim_strong);
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
_root_processor.process_all_roots(
&_adjust,

View File

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "memory/iterator.inline.hpp"
@ -36,7 +37,7 @@ G1FullGCMarker::G1FullGCMarker(uint worker_id, PreservedMarks* preserved_stack,
_mark_closure(worker_id, this, G1CollectedHeap::heap()->ref_processor_stw()),
_verify_closure(VerifyOption_G1UseFullMarking),
_stack_closure(this),
_cld_closure(mark_closure()) {
_cld_closure(mark_closure(), ClassLoaderData::_claim_strong) {
_oop_stack.initialize();
_objarray_stack.initialize();
}

View File

@ -170,10 +170,10 @@ class VerifyCLDClosure: public CLDClosure {
public:
VerifyCLDClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {}
void do_cld(ClassLoaderData* cld) {
cld->oops_do(_oop_closure, false);
cld->oops_do(_oop_closure, ClassLoaderData::_claim_none);
_young_ref_counter_closure.reset_count();
cld->oops_do(&_young_ref_counter_closure, false);
cld->oops_do(&_young_ref_counter_closure, ClassLoaderData::_claim_none);
if (_young_ref_counter_closure.count() > 0) {
guarantee(cld->has_modified_oops(), "CLD " PTR_FORMAT ", has young %d refs but is not dirty.", p2i(cld), _young_ref_counter_closure.count());
}

View File

@ -52,7 +52,7 @@ void G1CLDScanClosure::do_cld(ClassLoaderData* cld) {
// Clean the cld since we're going to scavenge all the metadata.
// Clear modified oops only if this cld is claimed.
cld->oops_do(_closure, _must_claim, /*clear_modified_oops*/true);
cld->oops_do(_closure, _claim, /*clear_modified_oops*/true);
_closure->set_scanned_cld(NULL);

View File

@ -160,12 +160,12 @@ public:
class G1CLDScanClosure : public CLDClosure {
G1ParCopyHelper* _closure;
bool _process_only_dirty;
bool _must_claim;
int _claim;
int _count;
public:
G1CLDScanClosure(G1ParCopyHelper* closure,
bool process_only_dirty, bool must_claim)
: _closure(closure), _process_only_dirty(process_only_dirty), _must_claim(must_claim), _count(0) {}
bool process_only_dirty, int claim_value)
: _closure(closure), _process_only_dirty(process_only_dirty), _claim(claim_value), _count(0) {}
void do_cld(ClassLoaderData* cld);
};

View File

@ -35,7 +35,7 @@ public:
G1EvacuationClosures(G1CollectedHeap* g1h,
G1ParScanThreadState* pss,
bool in_young_gc) :
_closures(g1h, pss, in_young_gc, /* must_claim_cld */ false) {}
_closures(g1h, pss, in_young_gc, /* cld_claim */ ClassLoaderData::_claim_none) {}
OopClosure* weak_oops() { return &_closures._oops; }
OopClosure* strong_oops() { return &_closures._oops; }
@ -73,8 +73,8 @@ class G1InitialMarkClosures : public G1EvacuationRootClosures {
public:
G1InitialMarkClosures(G1CollectedHeap* g1h,
G1ParScanThreadState* pss) :
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true),
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true) {}
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong),
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong) {}
OopClosure* weak_oops() { return &_weak._oops; }
OopClosure* strong_oops() { return &_strong._oops; }

View File

@ -39,9 +39,9 @@ public:
G1CLDScanClosure _clds;
G1CodeBlobClosure _codeblobs;
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty, bool must_claim_cld) :
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty, int cld_claim) :
_oops(g1h, pss),
_oops_in_cld(g1h, pss),
_clds(&_oops_in_cld, process_only_dirty, must_claim_cld),
_clds(&_oops_in_cld, process_only_dirty, cld_claim),
_codeblobs(&_oops) {}
};

View File

@ -110,7 +110,7 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
break;
case class_loader_data: {
CLDToOopClosure cld_closure(&mark_and_push_closure);
CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
ClassLoaderDataGraph::always_strong_cld_do(&cld_closure);
}
break;

View File

@ -2213,7 +2213,7 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
Management::oops_do(&oop_closure);
JvmtiExport::oops_do(&oop_closure);
SystemDictionary::oops_do(&oop_closure);
CLDToOopClosure cld_closure(&oop_closure);
CLDToOopClosure cld_closure(&oop_closure, ClassLoaderData::_claim_strong);
ClassLoaderDataGraph::cld_do(&cld_closure);
// Now adjust pointers in remaining weak roots. (All of which should

View File

@ -137,7 +137,7 @@ void CLDScanClosure::do_cld(ClassLoaderData* cld) {
_scavenge_closure->set_scanned_cld(cld);
// Clean the cld since we're going to scavenge all the metadata.
cld->oops_do(_scavenge_closure, false, /*clear_modified_oops*/true);
cld->oops_do(_scavenge_closure, ClassLoaderData::_claim_none, /*clear_modified_oops*/true);
_scavenge_closure->set_scanned_cld(NULL);
}

View File

@ -58,9 +58,9 @@ SerialOldTracer* MarkSweep::_gc_tracer = NULL;
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
MarkAndPushClosure MarkSweep::mark_and_push_closure;
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
MarkAndPushClosure MarkSweep::mark_and_push_closure;
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_strong);
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
mark_and_push(p);

View File

@ -242,7 +242,7 @@ void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph);
CLDToOopClosure cld_cl(cl, _marking /* must_claim */);
CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none);
ClassLoaderDataGraph::cld_do(&cld_cl);
}

View File

@ -92,7 +92,7 @@ void RootSetClosure::process_roots(OopClosure* closure) {
SaveRestoreCLDClaimBits save_restore_cld_claim_bits;
RootSetClosureMarkScope mark_scope;
CLDToOopClosure cldt_closure(closure);
CLDToOopClosure cldt_closure(closure, ClassLoaderData::_claim_strong);
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
CodeBlobToOopClosure blobs(closure, false);
Threads::oops_do(closure, &blobs);

View File

@ -128,7 +128,7 @@ class ReferenceToRootClosure : public StackObj {
bool ReferenceToRootClosure::do_cldg_roots() {
assert(!complete(), "invariant");
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
CLDToOopClosure cldt_closure(&rlc);
CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_strong);
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
return rlc.complete();
}

View File

@ -69,12 +69,12 @@ CLDClaimContext::CLDClaimContext() : _cld(NULL) {}
CLDClaimContext::CLDClaimContext(ClassLoaderData* cld) : _cld(cld) {
assert(_cld->claimed(), "invariant");
_cld->clear_claimed();
_cld->clear_claim();
}
CLDClaimContext::~CLDClaimContext() {
if (_cld != NULL) {
_cld->claim();
_cld->try_claim(ClassLoaderData::_claim_strong);
assert(_cld->claimed(), "invariant");
}
}

View File

@ -32,7 +32,7 @@
DoNothingClosure do_nothing_cl;
void CLDToOopClosure::do_cld(ClassLoaderData* cld) {
cld->oops_do(_oop_closure, _must_claim_cld);
cld->oops_do(_oop_closure, _cld_claim);
}
void ObjectToOopClosure::do_object(oop obj) {

View File

@ -127,12 +127,13 @@ class CLDClosure : public Closure {
class CLDToOopClosure : public CLDClosure {
OopClosure* _oop_closure;
bool _must_claim_cld;
int _cld_claim;
public:
CLDToOopClosure(OopClosure* oop_closure, bool must_claim_cld = true) :
CLDToOopClosure(OopClosure* oop_closure,
int cld_claim) :
_oop_closure(oop_closure),
_must_claim_cld(must_claim_cld) {}
_cld_claim(cld_claim) {}
void do_cld(ClassLoaderData* cld);
};

View File

@ -39,8 +39,7 @@
#include "utilities/debug.hpp"
inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
bool claim = true; // Must claim the class loader data before processing.
cld->oops_do(this, claim);
cld->oops_do(this, ClassLoaderData::_claim_strong);
}
inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {