Skip to content

Commit 03e769b

Browse files
author
Thomas Schatzl
committed
8159984: Remove call to ClassLoaderDataGraph::clear_claimed_marks during the initial mark pause
The CLDG is only iterated once during garbage collection, so we do not need to claim CLDs any more. Reviewed-by: sjohanss, kbarrett
1 parent 9ccc00d commit 03e769b

File tree

11 files changed

+59
-85
lines changed

11 files changed

+59
-85
lines changed

src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
6262
_gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):");
6363
AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scan (ms):");)
6464
_gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):");
65-
_gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
66-
_gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
65+
_gc_par_phases[WaitForStrongRoots] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong Roots (ms):");
6766

6867
_gc_par_phases[MergeER] = new WorkerDataArray<double>(max_gc_threads, "Eager Reclaim (ms):");
6968

@@ -567,8 +566,7 @@ const char* G1GCPhaseTimes::phase_name(GCParPhases phase) {
567566
"JVMTIRoots",
568567
AOT_ONLY("AOTCodeRoots" COMMA)
569568
"CMRefRoots",
570-
"WaitForStrongCLD",
571-
"WeakCLDRoots",
569+
"WaitForStrongRoots",
572570
"MergeER",
573571
"MergeRS",
574572
"OptMergeRS",

src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
5757
JVMTIRoots,
5858
AOT_ONLY(AOTCodeRoots COMMA)
5959
CMRefRoots,
60-
WaitForStrongCLD,
61-
WeakCLDRoots,
60+
WaitForStrongRoots,
6261
MergeER,
6362
MergeRS,
6463
OptMergeRS,
@@ -84,7 +83,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
8483
};
8584

8685
static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots;
87-
static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots;
86+
static const GCParPhases ExtRootScanSubPhasesLast = WaitForStrongRoots;
8887

8988
enum GCMergeRSWorkTimes {
9089
MergeRSMergedSparse,

src/hotspot/share/gc/g1/g1OopClosures.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,14 @@ G1ScanClosureBase::G1ScanClosureBase(G1CollectedHeap* g1h, G1ParScanThreadState*
4343

4444
void G1CLDScanClosure::do_cld(ClassLoaderData* cld) {
4545
// If the class loader data has not been dirtied we know that there's
46-
// no references into the young gen and we can skip it.
46+
// no references into the young gen and we can skip it.
4747
if (!_process_only_dirty || cld->has_modified_oops()) {
4848

4949
// Tell the closure that this class loader data is the CLD to scavenge
5050
// and is the one to dirty if oops are left pointing into the young gen.
5151
_closure->set_scanned_cld(cld);
52-
53-
// Clean the cld since we're going to scavenge all the metadata.
54-
// Clear modified oops only if this cld is claimed.
55-
cld->oops_do(_closure, _claim, /*clear_modified_oops*/true);
52+
// Clean modified oops since we're going to scavenge all the metadata.
53+
cld->oops_do(_closure, ClassLoaderData::_claim_none, true /*clear_modified_oops*/);
5654

5755
_closure->set_scanned_cld(NULL);
5856

src/hotspot/share/gc/g1/g1OopClosures.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,10 @@ class G1ParCopyClosure : public G1ParCopyHelper {
175175
class G1CLDScanClosure : public CLDClosure {
176176
G1ParCopyHelper* _closure;
177177
bool _process_only_dirty;
178-
int _claim;
179178
int _count;
180179
public:
181-
G1CLDScanClosure(G1ParCopyHelper* closure,
182-
bool process_only_dirty, int claim_value)
183-
: _closure(closure), _process_only_dirty(process_only_dirty), _claim(claim_value), _count(0) {}
180+
G1CLDScanClosure(G1ParCopyHelper* closure, bool process_only_dirty)
181+
: _closure(closure), _process_only_dirty(process_only_dirty), _count(0) {}
184182
void do_cld(ClassLoaderData* cld);
185183
};
186184

src/hotspot/share/gc/g1/g1RootClosures.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ class G1EvacuationClosures : public G1EvacuationRootClosures {
3535
G1EvacuationClosures(G1CollectedHeap* g1h,
3636
G1ParScanThreadState* pss,
3737
bool in_young_gc) :
38-
_closures(g1h, pss, in_young_gc, /* cld_claim */ ClassLoaderData::_claim_none) {}
38+
_closures(g1h, pss, in_young_gc) {}
3939

4040
OopClosure* weak_oops() { return &_closures._oops; }
4141
OopClosure* strong_oops() { return &_closures._oops; }
4242

4343
CLDClosure* weak_clds() { return &_closures._clds; }
4444
CLDClosure* strong_clds() { return &_closures._clds; }
45-
CLDClosure* second_pass_weak_clds() { return NULL; }
4645

4746
CodeBlobClosure* strong_codeblobs() { return &_closures._codeblobs; }
4847
CodeBlobClosure* weak_codeblobs() { return &_closures._codeblobs; }
@@ -58,33 +57,18 @@ class G1InitialMarkClosures : public G1EvacuationRootClosures {
5857
G1SharedClosures<G1MarkFromRoot> _strong;
5958
G1SharedClosures<MarkWeak> _weak;
6059

61-
// Filter method to help with returning the appropriate closures
62-
// depending on the class template parameter.
63-
template <G1Mark Mark, typename T>
64-
T* null_if(T* t) {
65-
if (Mark == MarkWeak) {
66-
return NULL;
67-
}
68-
return t;
69-
}
70-
7160
public:
7261
G1InitialMarkClosures(G1CollectedHeap* g1h,
7362
G1ParScanThreadState* pss) :
74-
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong),
75-
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* cld_claim */ ClassLoaderData::_claim_strong) {}
63+
_strong(g1h, pss, /* process_only_dirty_klasses */ false),
64+
_weak(g1h, pss, /* process_only_dirty_klasses */ false) {}
7665

7766
OopClosure* weak_oops() { return &_weak._oops; }
7867
OopClosure* strong_oops() { return &_strong._oops; }
7968

80-
// If MarkWeak is G1MarkPromotedFromRoot then the weak CLDs must be processed in a second pass.
81-
CLDClosure* weak_clds() { return null_if<G1MarkPromotedFromRoot>(&_weak._clds); }
69+
CLDClosure* weak_clds() { return &_weak._clds; }
8270
CLDClosure* strong_clds() { return &_strong._clds; }
8371

84-
// If MarkWeak is G1MarkFromRoot then all CLDs are processed by the weak and strong variants
85-
// return a NULL closure for the following specialized versions in that case.
86-
CLDClosure* second_pass_weak_clds() { return null_if<G1MarkFromRoot>(&_weak._clds); }
87-
8872
CodeBlobClosure* strong_codeblobs() { return &_strong._codeblobs; }
8973
CodeBlobClosure* weak_codeblobs() { return &_weak._codeblobs; }
9074

src/hotspot/share/gc/g1/g1RootClosures.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ class G1RootClosures : public CHeapObj<mtGC> {
4949

5050
class G1EvacuationRootClosures : public G1RootClosures {
5151
public:
52-
// Applied to the weakly reachable CLDs when all strongly reachable
53-
// CLDs are guaranteed to have been processed.
54-
virtual CLDClosure* second_pass_weak_clds() = 0;
55-
5652
// Applied to code blobs treated as weak roots.
5753
virtual CodeBlobClosure* weak_codeblobs() = 0;
5854

src/hotspot/share/gc/g1/g1RootProcessor.cpp

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#include "services/management.hpp"
4646
#include "utilities/macros.hpp"
4747

48-
void G1RootProcessor::worker_has_discovered_all_strong_classes() {
48+
void G1RootProcessor::worker_has_discovered_all_strong_nmethods() {
4949
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
5050

5151
uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
@@ -56,7 +56,7 @@ void G1RootProcessor::worker_has_discovered_all_strong_classes() {
5656
}
5757
}
5858

59-
void G1RootProcessor::wait_until_all_strong_classes_discovered() {
59+
void G1RootProcessor::wait_until_all_strong_nmethods_discovered() {
6060
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
6161

6262
if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
@@ -71,7 +71,7 @@ G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
7171
_g1h(g1h),
7272
_process_strong_tasks(G1RP_PS_NumElements),
7373
_srs(n_workers),
74-
_lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
74+
_lock(Mutex::leaf, "G1 Root Scan barrier lock", false, Monitor::_safepoint_check_never),
7575
_n_workers_discovered_strong_classes(0) {}
7676

7777
void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
@@ -80,13 +80,7 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
8080
G1EvacPhaseTimesTracker timer(phase_times, pss, G1GCPhaseTimes::ExtRootScan, worker_i);
8181

8282
G1EvacuationRootClosures* closures = pss->closures();
83-
process_java_roots(closures, phase_times, worker_i);
84-
85-
// This is the point where this worker thread will not find more strong CLDs/nmethods.
86-
// Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
87-
if (closures->trace_metadata()) {
88-
worker_has_discovered_all_strong_classes();
89-
}
83+
process_java_roots(closures, phase_times, worker_i, closures->trace_metadata() /* notify_claimed_nmethods_done */);
9084

9185
process_vm_roots(closures, phase_times, worker_i);
9286

@@ -103,21 +97,9 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) {
10397
}
10498

10599
if (closures->trace_metadata()) {
106-
{
107-
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
108-
// Barrier to make sure all workers passed
109-
// the strong CLD and strong nmethods phases.
110-
wait_until_all_strong_classes_discovered();
111-
}
112-
113-
// Now take the complement of the strong CLDs.
114-
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
115-
assert(closures->second_pass_weak_clds() != NULL, "Should be non-null if we are tracing metadata.");
116-
ClassLoaderDataGraph::roots_cld_do(NULL, closures->second_pass_weak_clds());
117-
} else {
118-
phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0);
119-
phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0);
120-
assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata.");
100+
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongRoots, worker_i);
101+
// Wait to make sure all workers passed the strong nmethods phase.
102+
wait_until_all_strong_nmethods_discovered();
121103
}
122104

123105
_process_strong_tasks.all_tasks_completed(n_workers());
@@ -189,24 +171,44 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
189171

190172
void G1RootProcessor::process_java_roots(G1RootClosures* closures,
191173
G1GCPhaseTimes* phase_times,
192-
uint worker_i) {
193-
// Iterating over the CLDG and the Threads are done early to allow us to
194-
// first process the strong CLDs and nmethods and then, after a barrier,
195-
// let the thread process the weak CLDs and nmethods.
196-
{
197-
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
198-
if (_process_strong_tasks.try_claim_task(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
199-
ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds());
200-
}
201-
}
202-
174+
uint worker_i,
175+
bool notify_claimed_nmethods_done) {
176+
// We need to make make sure that the "strong" nmethods are processed first
177+
// using the strong closure. Only after that we process the weakly reachable
178+
// nmethods.
179+
// We need to strictly separate the strong and weak nmethod processing because
180+
// any processing claims that nmethod, i.e. will not be iterated again.
181+
// Which means if an nmethod is processed first and claimed, the strong processing
182+
// will not happen, and the oops reachable by that nmethod will not be marked
183+
// properly.
184+
//
185+
// That is why we process strong nmethods first, synchronize all threads via a
186+
// barrier, and only then allow weak processing. To minimize the wait time at
187+
// that barrier we do the strong nmethod processing first, and immediately after-
188+
// wards indicate that that thread is done. Hopefully other root processing after
189+
// nmethod processing is enough so there is no need to wait.
190+
//
191+
// This is only required in the concurrent start pause with class unloading enabled.
203192
{
204193
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
205194
bool is_par = n_workers() > 1;
206195
Threads::possibly_parallel_oops_do(is_par,
207196
closures->strong_oops(),
208197
closures->strong_codeblobs());
209198
}
199+
200+
// This is the point where this worker thread will not find more strong nmethods.
201+
// Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
202+
if (notify_claimed_nmethods_done) {
203+
worker_has_discovered_all_strong_nmethods();
204+
}
205+
206+
{
207+
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
208+
if (_process_strong_tasks.try_claim_task(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
209+
ClassLoaderDataGraph::roots_cld_do(closures->strong_clds(), closures->weak_clds());
210+
}
211+
}
210212
}
211213

212214
void G1RootProcessor::process_vm_roots(G1RootClosures* closures,

src/hotspot/share/gc/g1/g1RootProcessor.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,13 @@ class G1RootProcessor : public StackObj {
6969
G1RP_PS_NumElements
7070
};
7171

72-
void worker_has_discovered_all_strong_classes();
73-
void wait_until_all_strong_classes_discovered();
72+
void worker_has_discovered_all_strong_nmethods();
73+
void wait_until_all_strong_nmethods_discovered();
7474

7575
void process_java_roots(G1RootClosures* closures,
7676
G1GCPhaseTimes* phase_times,
77-
uint worker_i);
77+
uint worker_i,
78+
bool notify_claimed_nmethods_done = false);
7879

7980
void process_vm_roots(G1RootClosures* closures,
8081
G1GCPhaseTimes* phase_times,

src/hotspot/share/gc/g1/g1SharedClosures.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ class G1SharedClosures {
3939
G1CLDScanClosure _clds;
4040
G1CodeBlobClosure _codeblobs;
4141

42-
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty, int cld_claim) :
42+
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty) :
4343
_oops(g1h, pss),
4444
_oops_in_cld(g1h, pss),
45-
_clds(&_oops_in_cld, process_only_dirty, cld_claim),
45+
_clds(&_oops_in_cld, process_only_dirty),
4646
_codeblobs(&_oops) {}
4747
};

test/hotspot/jtreg/gc/g1/TestGCLogMessages.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ public boolean isAvailable() {
128128
new LogMessageWithLevel("CLDG Roots", Level.TRACE),
129129
new LogMessageWithLevel("JVMTI Roots", Level.TRACE),
130130
new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
131-
new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE),
132-
new LogMessageWithLevel("Weak CLD Roots", Level.TRACE),
131+
new LogMessageWithLevel("Wait For Strong Roots", Level.TRACE),
133132
// Redirty Cards
134133
new LogMessageWithLevel("Redirty Cards", Level.DEBUG),
135134
new LogMessageWithLevel("Parallel Redirty", Level.TRACE),

0 commit comments

Comments
 (0)