8210330: Make CLD claiming allow multiple claim bits
Reviewed-by: pliden, coleenp
This commit is contained in:
parent
782fa608d2
commit
e39c5811b5
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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(¬Older, true);
|
||||
CLDToOopClosure cld_closure(¬Older, 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(¬Older, true);
|
||||
CLDToOopClosure cld_closure(¬Older, 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()) {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user