Skip to content

Commit 51085b5

Browse files
author
Thomas Schatzl
committedSep 22, 2021
8274054: Add custom enqueue calls during reference processing
Reviewed-by: ayang, kbarrett, sjohanss
1 parent c77ebe8 commit 51085b5

9 files changed

+81
-31
lines changed
 

‎src/hotspot/share/gc/g1/g1ConcurrentMark.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -1581,8 +1581,9 @@ class G1CMRefProcProxyTask : public RefProcProxyTask {
15811581
G1CMIsAliveClosure is_alive(&_g1h);
15821582
uint index = (_tm == RefProcThreadModel::Single) ? 0 : worker_id;
15831583
G1CMKeepAliveAndDrainClosure keep_alive(&_cm, _cm.task(index), _tm == RefProcThreadModel::Single);
1584+
BarrierEnqueueDiscoveredFieldClosure enqueue;
15841585
G1CMDrainMarkingStackClosure complete_gc(&_cm, _cm.task(index), _tm == RefProcThreadModel::Single);
1585-
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc);
1586+
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc);
15861587
}
15871588

15881589
void prepare_run_task_hook() override {
@@ -1695,6 +1696,7 @@ void G1ConcurrentMark::preclean() {
16951696
SuspendibleThreadSetJoiner joiner;
16961697

16971698
G1CMKeepAliveAndDrainClosure keep_alive(this, task(0), true /* is_serial */);
1699+
BarrierEnqueueDiscoveredFieldClosure enqueue;
16981700
G1CMDrainMarkingStackClosure drain_mark_stack(this, task(0), true /* is_serial */);
16991701

17001702
set_concurrency_and_phase(1, true);
@@ -1706,6 +1708,7 @@ void G1ConcurrentMark::preclean() {
17061708
ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(rp, false);
17071709
rp->preclean_discovered_references(rp->is_alive_non_header(),
17081710
&keep_alive,
1711+
&enqueue,
17091712
&drain_mark_stack,
17101713
&yield_cl,
17111714
_gc_timer_cm);

‎src/hotspot/share/gc/g1/g1FullCollector.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,9 @@ class G1FullGCRefProcProxyTask : public RefProcProxyTask {
248248
G1IsAliveClosure is_alive(&_collector);
249249
uint index = (_tm == RefProcThreadModel::Single) ? 0 : worker_id;
250250
G1FullKeepAliveClosure keep_alive(_collector.marker(index));
251+
BarrierEnqueueDiscoveredFieldClosure enqueue;
251252
G1FollowStackClosure* complete_gc = _collector.marker(index)->stack_closure();
252-
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, complete_gc);
253+
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, complete_gc);
253254
}
254255
};
255256

‎src/hotspot/share/gc/g1/g1YoungCollector.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,9 @@ class G1STWRefProcProxyTask : public RefProcProxyTask {
912912

913913
G1STWIsAliveClosure is_alive(&_g1h);
914914
G1CopyingKeepAliveClosure keep_alive(&_g1h, pss);
915+
BarrierEnqueueDiscoveredFieldClosure enqueue;
915916
G1ParEvacuateFollowersClosure complete_gc(&_g1h, pss, &_task_queues, _tm == RefProcThreadModel::Single ? nullptr : &_terminator, G1GCPhaseTimes::ObjCopy);
916-
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc);
917+
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc);
917918

918919
// We have completed copying any necessary live referent objects.
919920
assert(pss->queue_is_empty(), "both queue and overflow should be empty");

‎src/hotspot/share/gc/parallel/psParallelCompact.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2067,8 +2067,9 @@ class ParallelCompactRefProcProxyTask : public RefProcProxyTask {
20672067
assert(worker_id < _max_workers, "sanity");
20682068
ParCompactionManager* cm = (_tm == RefProcThreadModel::Single) ? ParCompactionManager::get_vmthread_cm() : ParCompactionManager::gc_thread_compaction_manager(worker_id);
20692069
PCMarkAndPushClosure keep_alive(cm);
2070+
BarrierEnqueueDiscoveredFieldClosure enqueue;
20702071
ParCompactionManager::FollowStackClosure complete_gc(cm, (_tm == RefProcThreadModel::Single) ? nullptr : &_terminator, worker_id);
2071-
_rp_task->rp_work(worker_id, PSParallelCompact::is_alive_closure(), &keep_alive, &complete_gc);
2072+
_rp_task->rp_work(worker_id, PSParallelCompact::is_alive_closure(), &keep_alive, &enqueue, &complete_gc);
20722073
}
20732074

20742075
void prepare_run_task_hook() override {

‎src/hotspot/share/gc/parallel/psScavenge.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,10 @@ class ParallelScavengeRefProcProxyTask : public RefProcProxyTask {
209209
assert(worker_id < _max_workers, "sanity");
210210
PSPromotionManager* promotion_manager = (_tm == RefProcThreadModel::Single) ? PSPromotionManager::vm_thread_promotion_manager() : PSPromotionManager::gc_thread_promotion_manager(worker_id);
211211
PSIsAliveClosure is_alive;
212-
PSKeepAliveClosure keep_alive(promotion_manager);;
212+
PSKeepAliveClosure keep_alive(promotion_manager);
213+
BarrierEnqueueDiscoveredFieldClosure enqueue;
213214
PSEvacuateFollowersClosure complete_gc(promotion_manager, (_marks_oops_alive && _tm == RefProcThreadModel::Multi) ? &_terminator : nullptr, worker_id);;
214-
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &complete_gc);
215+
_rp_task->rp_work(worker_id, &is_alive, &keep_alive, &enqueue, &complete_gc);
215216
}
216217

217218
void prepare_run_task_hook() override {

‎src/hotspot/share/gc/serial/serialGcRefProcProxyTask.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class SerialGCRefProcProxyTask : public RefProcProxyTask {
4141

4242
void work(uint worker_id) override {
4343
assert(worker_id < _max_workers, "sanity");
44-
_rp_task->rp_work(worker_id, &_is_alive, &_keep_alive, &_complete_gc);
44+
BarrierEnqueueDiscoveredFieldClosure enqueue;
45+
_rp_task->rp_work(worker_id, &_is_alive, &_keep_alive, &enqueue, &_complete_gc);
4546
}
4647
};
4748

‎src/hotspot/share/gc/shared/referenceProcessor.cpp

+32-19
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(RefPro
218218
return stats;
219219
}
220220

221+
void BarrierEnqueueDiscoveredFieldClosure::enqueue(oop reference, oop value) {
222+
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(reference,
223+
java_lang_ref_Reference::discovered_offset(),
224+
value);
225+
}
226+
221227
void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) {
222228
_current_discovered_addr = java_lang_ref_Reference::discovered_addr_raw(_current_discovered);
223229
oop discovered = java_lang_ref_Reference::discovered(_current_discovered);
@@ -271,18 +277,16 @@ void DiscoveredListIterator::clear_referent() {
271277
}
272278

273279
void DiscoveredListIterator::enqueue() {
274-
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_current_discovered,
275-
java_lang_ref_Reference::discovered_offset(),
276-
_next_discovered);
280+
_enqueue->enqueue(_current_discovered, _next_discovered);
277281
}
278282

279283
void DiscoveredListIterator::complete_enqueue() {
280-
if (_prev_discovered != NULL) {
284+
if (_prev_discovered != nullptr) {
281285
// This is the last object.
282286
// Swap refs_list into pending list and set obj's
283287
// discovered to what we read from the pending list.
284288
oop old = Universe::swap_reference_pending_list(_refs_list.head());
285-
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(_prev_discovered, java_lang_ref_Reference::discovered_offset(), old);
289+
_enqueue->enqueue(_prev_discovered, old);
286290
}
287291
}
288292

@@ -307,8 +311,9 @@ inline void log_enqueued_ref(const DiscoveredListIterator& iter, const char* rea
307311
size_t ReferenceProcessor::process_discovered_list_work(DiscoveredList& refs_list,
308312
BoolObjectClosure* is_alive,
309313
OopClosure* keep_alive,
314+
EnqueueDiscoveredFieldClosure* enqueue,
310315
bool do_enqueue_and_clear) {
311-
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
316+
DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue);
312317
while (iter.has_next()) {
313318
iter.load_ptrs(DEBUG_ONLY(discovery_is_concurrent() /* allow_null_referent */));
314319
if (iter.referent() == NULL) {
@@ -350,8 +355,9 @@ size_t ReferenceProcessor::process_discovered_list_work(DiscoveredList& refs_
350355
}
351356

352357
size_t ReferenceProcessor::process_final_keep_alive_work(DiscoveredList& refs_list,
353-
OopClosure* keep_alive) {
354-
DiscoveredListIterator iter(refs_list, keep_alive, NULL);
358+
OopClosure* keep_alive,
359+
EnqueueDiscoveredFieldClosure* enqueue) {
360+
DiscoveredListIterator iter(refs_list, keep_alive, NULL, enqueue);
355361
while (iter.has_next()) {
356362
iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));
357363
// keep the referent and followers around
@@ -421,7 +427,8 @@ size_t ReferenceProcessor::total_reference_count(ReferenceType type) const {
421427
void RefProcTask::process_discovered_list(uint worker_id,
422428
ReferenceType ref_type,
423429
BoolObjectClosure* is_alive,
424-
OopClosure* keep_alive) {
430+
OopClosure* keep_alive,
431+
EnqueueDiscoveredFieldClosure* enqueue) {
425432
ReferenceProcessor::RefProcSubPhases subphase;
426433
DiscoveredList* dl;
427434
switch (ref_type) {
@@ -453,6 +460,7 @@ void RefProcTask::process_discovered_list(uint worker_id,
453460
size_t const removed = _ref_processor.process_discovered_list_work(dl[worker_id],
454461
is_alive,
455462
keep_alive,
463+
enqueue,
456464
do_enqueue_and_clear);
457465
_phase_times->add_ref_cleared(ref_type, removed);
458466
}
@@ -468,14 +476,15 @@ class RefProcSoftWeakFinalPhaseTask: public RefProcTask {
468476
void rp_work(uint worker_id,
469477
BoolObjectClosure* is_alive,
470478
OopClosure* keep_alive,
479+
EnqueueDiscoveredFieldClosure* enqueue,
471480
VoidClosure* complete_gc) override {
472481
RefProcWorkerTimeTracker t(_phase_times->soft_weak_final_refs_phase_worker_time_sec(), tracker_id(worker_id));
473482

474-
process_discovered_list(worker_id, REF_SOFT, is_alive, keep_alive);
483+
process_discovered_list(worker_id, REF_SOFT, is_alive, keep_alive, enqueue);
475484

476-
process_discovered_list(worker_id, REF_WEAK, is_alive, keep_alive);
485+
process_discovered_list(worker_id, REF_WEAK, is_alive, keep_alive, enqueue);
477486

478-
process_discovered_list(worker_id, REF_FINAL, is_alive, keep_alive);
487+
process_discovered_list(worker_id, REF_FINAL, is_alive, keep_alive, enqueue);
479488

480489
// Close the reachable set; needed for collectors which keep_alive_closure do
481490
// not immediately complete their work.
@@ -493,9 +502,10 @@ class RefProcKeepAliveFinalPhaseTask: public RefProcTask {
493502
void rp_work(uint worker_id,
494503
BoolObjectClosure* is_alive,
495504
OopClosure* keep_alive,
505+
EnqueueDiscoveredFieldClosure* enqueue,
496506
VoidClosure* complete_gc) override {
497507
RefProcSubPhasesWorkerTimeTracker tt(ReferenceProcessor::KeepAliveFinalRefsSubPhase, _phase_times, tracker_id(worker_id));
498-
_ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], keep_alive);
508+
_ref_processor.process_final_keep_alive_work(_ref_processor._discoveredFinalRefs[worker_id], keep_alive, enqueue);
499509
// Close the reachable set
500510
complete_gc->do_void();
501511
}
@@ -511,8 +521,9 @@ class RefProcPhantomPhaseTask: public RefProcTask {
511521
void rp_work(uint worker_id,
512522
BoolObjectClosure* is_alive,
513523
OopClosure* keep_alive,
524+
EnqueueDiscoveredFieldClosure* enqueue,
514525
VoidClosure* complete_gc) override {
515-
process_discovered_list(worker_id, REF_PHANTOM, is_alive, keep_alive);
526+
process_discovered_list(worker_id, REF_PHANTOM, is_alive, keep_alive, enqueue);
516527

517528
// Close the reachable set; needed for collectors which keep_alive_closure do
518529
// not immediately complete their work.
@@ -1039,6 +1050,7 @@ bool ReferenceProcessor::has_discovered_references() {
10391050

10401051
void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_alive,
10411052
OopClosure* keep_alive,
1053+
EnqueueDiscoveredFieldClosure* enqueue,
10421054
VoidClosure* complete_gc,
10431055
YieldClosure* yield,
10441056
GCTimer* gc_timer) {
@@ -1053,7 +1065,7 @@ void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_al
10531065
return;
10541066
}
10551067
if (preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
1056-
keep_alive, complete_gc, yield)) {
1068+
keep_alive, enqueue, complete_gc, yield)) {
10571069
log_reflist("SoftRef abort: ", _discoveredSoftRefs, _max_num_queues);
10581070
return;
10591071
}
@@ -1070,7 +1082,7 @@ void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_al
10701082
return;
10711083
}
10721084
if (preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
1073-
keep_alive, complete_gc, yield)) {
1085+
keep_alive, enqueue, complete_gc, yield)) {
10741086
log_reflist("WeakRef abort: ", _discoveredWeakRefs, _max_num_queues);
10751087
return;
10761088
}
@@ -1087,7 +1099,7 @@ void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_al
10871099
return;
10881100
}
10891101
if (preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
1090-
keep_alive, complete_gc, yield)) {
1102+
keep_alive, enqueue, complete_gc, yield)) {
10911103
log_reflist("FinalRef abort: ", _discoveredFinalRefs, _max_num_queues);
10921104
return;
10931105
}
@@ -1104,7 +1116,7 @@ void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_al
11041116
return;
11051117
}
11061118
if (preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
1107-
keep_alive, complete_gc, yield)) {
1119+
keep_alive, enqueue, complete_gc, yield)) {
11081120
log_reflist("PhantomRef abort: ", _discoveredPhantomRefs, _max_num_queues);
11091121
return;
11101122
}
@@ -1124,9 +1136,10 @@ void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_al
11241136
bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
11251137
BoolObjectClosure* is_alive,
11261138
OopClosure* keep_alive,
1139+
EnqueueDiscoveredFieldClosure* enqueue,
11271140
VoidClosure* complete_gc,
11281141
YieldClosure* yield) {
1129-
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
1142+
DiscoveredListIterator iter(refs_list, keep_alive, is_alive, enqueue);
11301143
while (iter.has_next()) {
11311144
if (yield->should_return_fine_grain()) {
11321145
return true;

‎src/hotspot/share/gc/shared/referenceProcessor.hpp

+31-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ class ReferenceProcessorPhaseTimes;
3838
class RefProcTask;
3939
class RefProcProxyTask;
4040

41+
// Provides a callback to the garbage collector to set the given value to the
42+
// discovered field of the j.l.ref.Reference instance. This is called during STW
43+
// reference processing when iterating over the discovered lists for all
44+
// discovered references.
45+
// Typically garbage collectors may just call the barrier, but for some garbage
46+
// collectors the barrier environment (e.g. card table) may not be set up correctly
47+
// at the point of invocation.
48+
class EnqueueDiscoveredFieldClosure {
49+
public:
50+
// For the given j.l.ref.Reference reference, set the discovered field to value.
51+
virtual void enqueue(oop reference, oop value) = 0;
52+
};
53+
54+
// EnqueueDiscoveredFieldClosure that executes the default barrier on the discovered
55+
// field of the j.l.ref.Reference reference with the given value.
56+
class BarrierEnqueueDiscoveredFieldClosure : public EnqueueDiscoveredFieldClosure {
57+
public:
58+
void enqueue(oop reference, oop value) override;
59+
};
60+
4161
// List of discovered references.
4262
class DiscoveredList {
4363
public:
@@ -66,7 +86,6 @@ class DiscoveredList {
6686

6787
// Iterator for the list of discovered references.
6888
class DiscoveredListIterator {
69-
private:
7089
DiscoveredList& _refs_list;
7190
HeapWord* _prev_discovered_addr;
7291
oop _prev_discovered;
@@ -78,6 +97,7 @@ class DiscoveredListIterator {
7897

7998
OopClosure* _keep_alive;
8099
BoolObjectClosure* _is_alive;
100+
EnqueueDiscoveredFieldClosure* _enqueue;
81101

82102
DEBUG_ONLY(
83103
oop _first_seen; // cyclic linked list check
@@ -89,7 +109,8 @@ class DiscoveredListIterator {
89109
public:
90110
inline DiscoveredListIterator(DiscoveredList& refs_list,
91111
OopClosure* keep_alive,
92-
BoolObjectClosure* is_alive);
112+
BoolObjectClosure* is_alive,
113+
EnqueueDiscoveredFieldClosure* enqueue);
93114

94115
// End Of List.
95116
inline bool has_next() const { return _current_discovered != NULL; }
@@ -255,12 +276,14 @@ class ReferenceProcessor : public ReferenceDiscoverer {
255276
size_t process_discovered_list_work(DiscoveredList& refs_list,
256277
BoolObjectClosure* is_alive,
257278
OopClosure* keep_alive,
279+
EnqueueDiscoveredFieldClosure* enqueue,
258280
bool do_enqueue_and_clear);
259281

260282
// Keep alive followers of referents for FinalReferences. Must only be called for
261283
// those.
262284
size_t process_final_keep_alive_work(DiscoveredList& refs_list,
263-
OopClosure* keep_alive);
285+
OopClosure* keep_alive,
286+
EnqueueDiscoveredFieldClosure* enqueue);
264287

265288

266289
void setup_policy(bool always_clear) {
@@ -291,6 +314,7 @@ class ReferenceProcessor : public ReferenceDiscoverer {
291314
// (or predicates involved) by other threads.
292315
void preclean_discovered_references(BoolObjectClosure* is_alive,
293316
OopClosure* keep_alive,
317+
EnqueueDiscoveredFieldClosure* enqueue,
294318
VoidClosure* complete_gc,
295319
YieldClosure* yield,
296320
GCTimer* gc_timer);
@@ -307,6 +331,7 @@ class ReferenceProcessor : public ReferenceDiscoverer {
307331
bool preclean_discovered_reflist(DiscoveredList& refs_list,
308332
BoolObjectClosure* is_alive,
309333
OopClosure* keep_alive,
334+
EnqueueDiscoveredFieldClosure* enqueue,
310335
VoidClosure* complete_gc,
311336
YieldClosure* yield);
312337

@@ -542,7 +567,8 @@ class RefProcTask : StackObj {
542567
void process_discovered_list(uint worker_id,
543568
ReferenceType ref_type,
544569
BoolObjectClosure* is_alive,
545-
OopClosure* keep_alive);
570+
OopClosure* keep_alive,
571+
EnqueueDiscoveredFieldClosure* enqueue);
546572
public:
547573
RefProcTask(ReferenceProcessor& ref_processor,
548574
ReferenceProcessorPhaseTimes* phase_times)
@@ -552,6 +578,7 @@ class RefProcTask : StackObj {
552578
virtual void rp_work(uint worker_id,
553579
BoolObjectClosure* is_alive,
554580
OopClosure* keep_alive,
581+
EnqueueDiscoveredFieldClosure* enqueue,
555582
VoidClosure* complete_gc) = 0;
556583
};
557584

‎src/hotspot/share/gc/shared/referenceProcessor.inline.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ void DiscoveredList::clear() {
6060

6161
DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list,
6262
OopClosure* keep_alive,
63-
BoolObjectClosure* is_alive):
63+
BoolObjectClosure* is_alive,
64+
EnqueueDiscoveredFieldClosure* enqueue):
6465
_refs_list(refs_list),
6566
_prev_discovered_addr(refs_list.adr_head()),
6667
_prev_discovered(NULL),
@@ -70,6 +71,7 @@ DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list,
7071
_referent(NULL),
7172
_keep_alive(keep_alive),
7273
_is_alive(is_alive),
74+
_enqueue(enqueue),
7375
#ifdef ASSERT
7476
_first_seen(refs_list.head()),
7577
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.