Skip to content

Commit eab170c

Browse files
committed
8256415: Shenandoah: Should evacuate/update codecache concurrently when class unloading is off
Reviewed-by: rkennke
1 parent f504f41 commit eab170c

10 files changed

+79
-114
lines changed

src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,11 @@
4444
class ShenandoahBarrierSetC1;
4545
class ShenandoahBarrierSetC2;
4646

47-
static BarrierSetNMethod* make_barrier_set_nmethod(ShenandoahHeap* heap) {
48-
// NMethod barriers are only used when concurrent nmethod unloading is enabled
49-
if (!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
50-
return NULL;
51-
}
52-
return new ShenandoahBarrierSetNMethod(heap);
53-
}
54-
5547
ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
5648
BarrierSet(make_barrier_set_assembler<ShenandoahBarrierSetAssembler>(),
5749
make_barrier_set_c1<ShenandoahBarrierSetC1>(),
5850
make_barrier_set_c2<ShenandoahBarrierSetC2>(),
59-
make_barrier_set_nmethod(heap),
51+
new ShenandoahBarrierSetNMethod(heap),
6052
BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
6153
_heap(heap),
6254
_satb_mark_queue_buffer_allocator("SATB Buffer Allocator", ShenandoahSATBBufferSize),

src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
420420
}
421421

422422
// Perform concurrent class unloading
423-
if (heap->is_concurrent_weak_root_in_progress()) {
423+
if (heap->is_concurrent_weak_root_in_progress() &&
424+
ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
424425
heap->entry_class_unloading();
425426
}
426427

src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,9 +1142,7 @@ void ShenandoahHeap::evacuate_and_update_roots() {
11421142
{
11431143
// Include concurrent roots if current cycle can not process those roots concurrently
11441144
ShenandoahRootEvacuator rp(workers()->active_workers(),
1145-
ShenandoahPhaseTimings::init_evac,
1146-
!ShenandoahConcurrentRoots::should_do_concurrent_roots(),
1147-
!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading());
1145+
ShenandoahPhaseTimings::init_evac);
11481146
ShenandoahEvacuateUpdateRootsTask roots_task(&rp);
11491147
workers()->run_task(&roots_task);
11501148
}
@@ -1744,9 +1742,8 @@ void ShenandoahHeap::op_final_mark() {
17441742
set_has_forwarded_objects(true);
17451743

17461744
if (!is_degenerated_gc_in_progress()) {
1747-
if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
1748-
ShenandoahCodeRoots::arm_nmethods();
1749-
}
1745+
// Arm nmethods for concurrent codecache processing.
1746+
ShenandoahCodeRoots::arm_nmethods();
17501747
evacuate_and_update_roots();
17511748
}
17521749

@@ -1757,17 +1754,10 @@ void ShenandoahHeap::op_final_mark() {
17571754
if (ShenandoahVerify) {
17581755
// If OOM while evacuating/updating of roots, there is no guarantee of their consistencies
17591756
if (!cancelled_gc()) {
1760-
ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::None;
1761-
if (ShenandoahConcurrentRoots::should_do_concurrent_roots()) {
1762-
types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::JNIHandleRoots, ShenandoahRootVerifier::WeakRoots);
1763-
types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CLDGRoots);
1764-
types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::StringDedupRoots);
1765-
}
1766-
1767-
if (ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
1768-
types = ShenandoahRootVerifier::combine(types, ShenandoahRootVerifier::CodeRoots);
1769-
}
1770-
verifier()->verify_roots_no_forwarded_except(types);
1757+
// We only evacuate/update thread and serial weak roots at this pause
1758+
ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::ThreadRoots,
1759+
ShenandoahRootVerifier::SerialWeakRoots);
1760+
verifier()->verify_roots_no_forwarded(types);
17711761
}
17721762
verifier()->verify_during_evacuation();
17731763
}
@@ -1840,16 +1830,53 @@ void ShenandoahHeap::op_cleanup_complete() {
18401830
free_set()->recycle_trash();
18411831
}
18421832

1833+
class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure {
1834+
private:
1835+
BarrierSetNMethod* const _bs;
1836+
ShenandoahEvacuateUpdateRootsClosure<> _cl;
1837+
1838+
public:
1839+
ShenandoahEvacUpdateCodeCacheClosure() :
1840+
_bs(BarrierSet::barrier_set()->barrier_set_nmethod()),
1841+
_cl() {
1842+
}
1843+
1844+
void do_nmethod(nmethod* n) {
1845+
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
1846+
ShenandoahReentrantLocker locker(data->lock());
1847+
data->oops_do(&_cl, true/*fix relocation*/);
1848+
_bs->disarm(n);
1849+
}
1850+
};
1851+
18431852
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
18441853
private:
1854+
ShenandoahPhaseTimings::Phase _phase;
18451855
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
18461856
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /*single threaded*/> _cld_roots;
1857+
ShenandoahConcurrentNMethodIterator _nmethod_itr;
1858+
bool _process_codecache;
18471859

18481860
public:
18491861
ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
18501862
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
1863+
_phase(phase),
18511864
_vm_roots(phase),
1852-
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()) {}
1865+
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
1866+
_nmethod_itr(ShenandoahCodeRoots::table()),
1867+
_process_codecache(!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) {
1868+
if (_process_codecache) {
1869+
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1870+
_nmethod_itr.nmethods_do_begin();
1871+
}
1872+
}
1873+
1874+
~ShenandoahConcurrentRootsEvacUpdateTask() {
1875+
if (_process_codecache) {
1876+
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1877+
_nmethod_itr.nmethods_do_end();
1878+
}
1879+
}
18531880

18541881
void work(uint worker_id) {
18551882
ShenandoahConcurrentWorkerSession worker_session(worker_id);
@@ -1866,6 +1893,12 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
18661893
CLDToOopClosure clds(&cl, ClassLoaderData::_claim_strong);
18671894
_cld_roots.cld_do(&clds, worker_id);
18681895
}
1896+
1897+
if (_process_codecache) {
1898+
ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
1899+
ShenandoahEvacUpdateCodeCacheClosure cl;
1900+
_nmethod_itr.nmethods_do(&cl);
1901+
}
18691902
}
18701903
};
18711904

src/hotspot/share/gc/shenandoah/shenandoahNMethod.cpp

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,6 @@ ShenandoahNMethod* ShenandoahNMethod::for_nmethod(nmethod* nm) {
147147
GrowableArray<oop*> oops;
148148

149149
detect_reloc_oops(nm, oops, non_immediate_oops);
150-
151-
// No embedded oops
152-
if(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() &&
153-
oops.is_empty() && nm->oops_begin() >= nm->oops_end()) {
154-
return NULL;
155-
}
156-
157150
return new ShenandoahNMethod(nm, oops, non_immediate_oops);
158151
}
159152

@@ -195,7 +188,8 @@ void ShenandoahNMethod::heal_nmethod(nmethod* nm) {
195188
ShenandoahKeepNMethodMetadataAliveClosure<false> cl;
196189
data->oops_do(&cl);
197190
}
198-
} else if (heap->is_concurrent_weak_root_in_progress()) {
191+
} else if (heap->is_concurrent_weak_root_in_progress() ||
192+
heap->is_concurrent_strong_root_in_progress()) {
199193
ShenandoahEvacOOMScope evac_scope;
200194
heal_nmethod_metadata(data);
201195
} else {
@@ -288,12 +282,6 @@ void ShenandoahNMethod::assert_same_oops(bool allow_dead) {
288282
oops->length(), _oops_count, count, p2i(nm()->oops_begin()), p2i(nm()->oops_end()), debug_stream.as_string());
289283
}
290284
}
291-
292-
void ShenandoahNMethod::assert_no_oops(nmethod* nm, bool allow_dead) {
293-
ShenandoahNMethodOopDetector detector;
294-
nm->oops_do(&detector, allow_dead);
295-
assert(detector.oops()->length() == 0, "Should not have oops");
296-
}
297285
#endif
298286

299287
ShenandoahNMethodTable::ShenandoahNMethodTable() :
@@ -321,11 +309,7 @@ void ShenandoahNMethodTable::register_nmethod(nmethod* nm) {
321309
data->update();
322310
} else {
323311
data = ShenandoahNMethod::for_nmethod(nm);
324-
if (data == NULL) {
325-
assert(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
326-
"Only possible when concurrent class unloading is off");
327-
return;
328-
}
312+
assert(data != NULL, "Sanity");
329313
ShenandoahNMethod::attach_gc_data(nm, data);
330314
ShenandoahLocker locker(&_lock);
331315
log_register_nmethod(nm);
@@ -339,13 +323,7 @@ void ShenandoahNMethodTable::unregister_nmethod(nmethod* nm) {
339323
assert_locked_or_safepoint(CodeCache_lock);
340324

341325
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
342-
if (data == NULL) {
343-
assert(!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
344-
"Only possible when concurrent class unloading is off");
345-
ShenandoahNMethod::assert_no_oops(nm, true /*allow_dead*/);
346-
return;
347-
}
348-
326+
assert(data != NULL, "Sanity");
349327
if (Thread::current()->is_Code_cache_sweeper_thread()) {
350328
wait_until_concurrent_iteration_done();
351329
}
@@ -361,12 +339,7 @@ void ShenandoahNMethodTable::flush_nmethod(nmethod* nm) {
361339
assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
362340
assert(Thread::current()->is_Code_cache_sweeper_thread(), "Must from Sweep thread");
363341
ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
364-
assert(data != NULL || !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
365-
"Only possible when concurrent class unloading is off");
366-
if (data == NULL) {
367-
ShenandoahNMethod::assert_no_oops(nm, true /*allow_dead*/);
368-
return;
369-
}
342+
assert(data != NULL, "Sanity");
370343

371344
// Can not alter the array when iteration is in progress
372345
wait_until_concurrent_iteration_done();
@@ -598,8 +571,6 @@ ShenandoahConcurrentNMethodIterator::ShenandoahConcurrentNMethodIterator(Shenand
598571

599572
void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
600573
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
601-
assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
602-
"Only for concurrent class unloading");
603574
_table_snapshot = _table->snapshot_for_iteration();
604575
}
605576

@@ -610,8 +581,6 @@ void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
610581

611582
void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
612583
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
613-
assert(ShenandoahConcurrentRoots::can_do_concurrent_class_unloading(),
614-
"Only for concurrent class unloading");
615584
_table->finish_iteration(_table_snapshot);
616585
CodeCache_lock->notify_all();
617586
}

src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ class ShenandoahNMethod : public CHeapObj<mtGC> {
7575

7676
void assert_correct() NOT_DEBUG_RETURN;
7777
void assert_same_oops(bool allow_dead = false) NOT_DEBUG_RETURN;
78-
static void assert_no_oops(nmethod* nm, bool allow_dea = false) NOT_DEBUG_RETURN;
7978

8079
private:
8180
bool has_non_immed_oops() const { return _has_non_immed_oops; }

src/hotspot/share/gc/shenandoah/shenandoahNMethod.inline.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,6 @@ void ShenandoahNMethod::heal_nmethod_metadata(ShenandoahNMethod* nmethod_data) {
7878
}
7979

8080
void ShenandoahNMethod::disarm_nmethod(nmethod* nm) {
81-
if (!ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
82-
return;
83-
}
84-
8581
BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
8682
assert(bs != NULL, "Sanity");
8783
if (bs->is_armed(nm)) {

src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -182,50 +182,26 @@ void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CodeBlobC
182182
}
183183

184184
ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers,
185-
ShenandoahPhaseTimings::Phase phase,
186-
bool stw_roots_processing,
187-
bool stw_class_unloading) :
185+
ShenandoahPhaseTimings::Phase phase) :
188186
ShenandoahRootProcessor(phase),
189-
_vm_roots(phase),
190-
_cld_roots(phase, n_workers),
191187
_thread_roots(phase, n_workers > 1),
192-
_serial_weak_roots(phase),
193-
_weak_roots(phase),
194-
_dedup_roots(phase),
195-
_code_roots(phase),
196-
_stw_roots_processing(stw_roots_processing),
197-
_stw_class_unloading(stw_class_unloading) {
188+
_serial_weak_roots(phase) {
189+
nmethod::oops_do_marking_prologue();
198190
}
199191

200-
void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
201-
MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations);
202-
ShenandoahCodeBlobAndDisarmClosure blobs_and_disarm_Cl(oops);
203-
CodeBlobToOopClosure* codes_cl = ShenandoahConcurrentRoots::can_do_concurrent_class_unloading() ?
204-
static_cast<CodeBlobToOopClosure*>(&blobs_and_disarm_Cl) :
205-
static_cast<CodeBlobToOopClosure*>(&blobsCl);
206-
AlwaysTrueClosure always_true;
192+
ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
193+
nmethod::oops_do_marking_epilogue();
194+
}
207195

196+
void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
197+
// Always disarm on-stack nmethods, because we are evacuating/updating them
198+
// here
199+
ShenandoahCodeBlobAndDisarmClosure codeblob_cl(oops);
208200
// Process serial-claiming roots first
209201
_serial_weak_roots.weak_oops_do(oops, worker_id);
210202

211203
// Process light-weight/limited parallel roots then
212-
if (_stw_roots_processing) {
213-
_vm_roots.oops_do<OopClosure>(oops, worker_id);
214-
_weak_roots.oops_do<OopClosure>(oops, worker_id);
215-
_dedup_roots.oops_do(&always_true, oops, worker_id);
216-
}
217-
if (_stw_class_unloading) {
218-
CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
219-
_cld_roots.cld_do(&clds, worker_id);
220-
}
221-
222-
// Process heavy-weight/fully parallel roots the last
223-
if (_stw_class_unloading) {
224-
_code_roots.code_blobs_do(codes_cl, worker_id);
225-
_thread_roots.oops_do(oops, NULL, worker_id);
226-
} else {
227-
_thread_roots.oops_do(oops, codes_cl, worker_id);
228-
}
204+
_thread_roots.oops_do(oops, &codeblob_cl, worker_id);
229205
}
230206

231207
ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :

src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -232,19 +232,11 @@ class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
232232
// Evacuate all roots at a safepoint
233233
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
234234
private:
235-
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
236-
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
237-
_cld_roots;
238235
ShenandoahThreadRoots _thread_roots;
239236
ShenandoahSerialWeakRoots _serial_weak_roots;
240-
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
241-
ShenandoahStringDedupRoots _dedup_roots;
242-
ShenandoahCodeCacheRoots _code_roots;
243-
bool _stw_roots_processing;
244-
bool _stw_class_unloading;
245237
public:
246-
ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase,
247-
bool stw_roots_processing, bool stw_class_unloading);
238+
ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase);
239+
~ShenandoahRootEvacuator();
248240

249241
void roots_do(uint worker_id, OopClosure* oops);
250242
};

src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,12 @@ void ShenandoahVerifier::verify_roots_no_forwarded() {
10101010
verifier.oops_do(&cl);
10111011
}
10121012

1013+
void ShenandoahVerifier::verify_roots_no_forwarded(ShenandoahRootVerifier::RootTypes types) {
1014+
ShenandoahRootVerifier verifier(types);
1015+
ShenandoahVerifyNoForwared cl;
1016+
verifier.oops_do(&cl);
1017+
}
1018+
10131019
void ShenandoahVerifier::verify_roots_no_forwarded_except(ShenandoahRootVerifier::RootTypes types) {
10141020
ShenandoahRootVerifier verifier;
10151021
verifier.excludes(types);

src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class ShenandoahVerifier : public CHeapObj<mtGC> {
196196
void verify_roots_in_to_space_except(ShenandoahRootVerifier::RootTypes types);
197197

198198
void verify_roots_no_forwarded();
199+
void verify_roots_no_forwarded(ShenandoahRootVerifier::RootTypes types);
199200
void verify_roots_no_forwarded_except(ShenandoahRootVerifier::RootTypes types);
200201
};
201202

0 commit comments

Comments
 (0)