Skip to content

Commit 421f949

Browse files
author
William Kemper
committed
8310062: [Shenandoah] Incomplete SATB buffers may not be processed during degenerated young collection
Reviewed-by: ysr, kdnilsen
1 parent c7cd380 commit 421f949

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-14
lines changed

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

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,6 @@ void ShenandoahDegenGC::op_degenerated() {
125125
// we can do the most aggressive degen cycle, which includes processing references and
126126
// class unloading, unless those features are explicitly disabled.
127127

128-
if (heap->is_concurrent_old_mark_in_progress()) {
129-
// We have come straight into a degenerated cycle without running a concurrent cycle
130-
// first and the SATB barrier is enabled to support concurrent old marking. The SATB buffer
131-
// may hold a mix of old and young pointers. The old pointers need to be transferred
132-
// to the old generation mark queues and the young pointers are _not_ part of this
133-
// snapshot, so they must be dropped here.
134-
heap->transfer_old_pointers_from_satb();
135-
}
136-
137128
// Note that we can only do this for "outside-cycle" degens, otherwise we would risk
138129
// changing the cycle parameters mid-cycle during concurrent -> degenerated handover.
139130
heap->set_unload_classes(_generation->heuristics()->can_unload_classes() &&
@@ -156,9 +147,20 @@ void ShenandoahDegenGC::op_degenerated() {
156147
if (_generation->is_concurrent_mark_in_progress()) {
157148
// We want to allow old generation marking to be punctuated by young collections
158149
// (even if they have degenerated). If this is a global cycle, we'd have cancelled
159-
// the entire old gc before coming into this switch.
150+
// the entire old gc before coming into this switch. Note that cancel_marking on
151+
// the generation does NOT abandon incomplete SATB buffers as cancel_concurrent_mark does.
152+
// We need to separate out the old pointers which is done below.
160153
_generation->cancel_marking();
161154
}
155+
156+
if (heap->is_concurrent_mark_in_progress()) {
157+
// If either old or young marking is in progress, the SATB barrier will be enabled.
158+
// The SATB buffer may hold a mix of old and young pointers. The old pointers need to be
159+
// transferred to the old generation mark queues and the young pointers are NOT part
160+
// of this snapshot, so they must be dropped here. It is safe to drop them here because
161+
// we will rescan the roots on this safepoint.
162+
heap->transfer_old_pointers_from_satb();
163+
}
162164
}
163165

164166
if (_degen_point == ShenandoahDegenPoint::_degenerated_roots) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class ShenandoahOldGeneration : public ShenandoahGeneration {
6565
// We leave the SATB barrier on for the entirety of the old generation
6666
// marking phase. In some cases, this can cause a write to a perfectly
6767
// reachable oop to enqueue a pointer that later becomes garbage (because
68-
// it points at an object in the collection set, for example). There are
68+
// it points at an object that is later chosen for the collection set). There are
6969
// also cases where the referent of a weak reference ends up in the SATB
7070
// and is later collected. In these cases the oop in the SATB buffer becomes
7171
// invalid and the _next_ cycle will crash during its marking phase. To

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
8787
_loc(nullptr),
8888
_generation(nullptr) {
8989
if (options._verify_marked == ShenandoahVerifier::_verify_marked_complete_except_references ||
90+
options._verify_marked == ShenandoahVerifier::_verify_marked_complete_satb_empty ||
9091
options._verify_marked == ShenandoahVerifier::_verify_marked_disable) {
9192
set_ref_discoverer_internal(new ShenandoahIgnoreReferenceDiscoverer());
9293
}
@@ -257,6 +258,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
257258
"Must be marked in complete bitmap");
258259
break;
259260
case ShenandoahVerifier::_verify_marked_complete_except_references:
261+
case ShenandoahVerifier::_verify_marked_complete_satb_empty:
260262
check(ShenandoahAsserts::_safe_all, obj, _heap->complete_marking_context()->is_marked_or_old(obj),
261263
"Must be marked in complete bitmap, except j.l.r.Reference referents");
262264
break;
@@ -597,6 +599,20 @@ class ShenandoahVerifierReachableTask : public WorkerTask {
597599
}
598600
};
599601

602+
class ShenandoahVerifyNoIncompleteSatbBuffers : public ThreadClosure {
603+
public:
604+
virtual void do_thread(Thread* thread) {
605+
SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread);
606+
if (!is_empty(queue)) {
607+
fatal("All SATB buffers should have been flushed during mark");
608+
}
609+
}
610+
private:
611+
bool is_empty(SATBMarkQueue& queue) {
612+
return queue.buffer() == nullptr || queue.index() == queue.capacity();
613+
}
614+
};
615+
600616
class ShenandoahVerifierMarkedRegionTask : public WorkerTask {
601617
private:
602618
const char* _label;
@@ -622,6 +638,10 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask {
622638
_claimed(0),
623639
_processed(0),
624640
_generation(nullptr) {
641+
if (_options._verify_marked == ShenandoahVerifier::_verify_marked_complete_satb_empty) {
642+
Threads::change_thread_claim_token();
643+
}
644+
625645
if (_heap->mode()->is_generational()) {
626646
_generation = _heap->active_generation();
627647
assert(_generation != nullptr, "Expected active generation in this mode.");
@@ -633,6 +653,11 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask {
633653
}
634654

635655
virtual void work(uint worker_id) {
656+
if (_options._verify_marked == ShenandoahVerifier::_verify_marked_complete_satb_empty) {
657+
ShenandoahVerifyNoIncompleteSatbBuffers verify_satb;
658+
Threads::possibly_parallel_threads_do(true, &verify_satb);
659+
}
660+
636661
ShenandoahVerifierStack stack;
637662
ShenandoahVerifyOopClosure cl(&stack, _bitmap, _ld,
638663
ShenandoahMessageBuffer("%s, Marked", _label),
@@ -945,7 +970,10 @@ void ShenandoahVerifier::verify_at_safepoint(const char* label,
945970
// version
946971

947972
size_t count_marked = 0;
948-
if (ShenandoahVerifyLevel >= 4 && (marked == _verify_marked_complete || marked == _verify_marked_complete_except_references)) {
973+
if (ShenandoahVerifyLevel >= 4 &&
974+
(marked == _verify_marked_complete ||
975+
marked == _verify_marked_complete_except_references ||
976+
marked == _verify_marked_complete_satb_empty)) {
949977
guarantee(_heap->marking_context()->is_complete(), "Marking context should be complete");
950978
ShenandoahVerifierMarkedRegionTask task(_verification_bit_map, ld, label, options);
951979
_heap->workers()->run_task(&task);
@@ -1031,7 +1059,7 @@ void ShenandoahVerifier::verify_after_concmark() {
10311059
"After Mark",
10321060
_verify_remembered_disable, // do not verify remembered set
10331061
_verify_forwarded_none, // no forwarded references
1034-
_verify_marked_complete_except_references,
1062+
_verify_marked_complete_satb_empty,
10351063
// bitmaps as precise as we can get, except dangling j.l.r.Refs
10361064
_verify_cset_none, // no references to cset anymore
10371065
_verify_liveness_complete, // liveness data must be complete here

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,12 @@ class ShenandoahVerifier : public CHeapObj<mtGC> {
8888

8989
// Objects should be marked in "complete" bitmap, except j.l.r.Reference referents, which
9090
// may be dangling after marking but before conc-weakrefs-processing.
91-
_verify_marked_complete_except_references
91+
_verify_marked_complete_except_references,
92+
93+
// Objects should be marked in "complete" bitmap, except j.l.r.Reference referents, which
94+
// may be dangling after marking but before conc-weakrefs-processing. All SATB buffers must
95+
// be empty.
96+
_verify_marked_complete_satb_empty,
9297
} VerifyMarked;
9398

9499
typedef enum {

0 commit comments

Comments
 (0)