Skip to content

Commit b2e431a

Browse files
author
William Kemper
committed
8369068: GenShen: Generations still aren't reconciled assertion failure
Reviewed-by: ysr, kdnilsen
1 parent b0721e2 commit b2e431a

32 files changed

+361
-401
lines changed

src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio
127127
// Reclaim humongous regions here, and count them as the immediate garbage
128128
#ifdef ASSERT
129129
bool reg_live = region->has_live();
130-
bool bm_live = heap->active_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom()));
130+
bool bm_live = _generation->complete_marking_context()->is_marked(cast_to_oop(region->bottom()));
131131
assert(reg_live == bm_live,
132132
"Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu",
133133
BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words());

src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,11 @@ ShenandoahHeuristics::~ShenandoahHeuristics() {
7373
}
7474

7575
void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) {
76-
assert(collection_set->is_empty(), "Must be empty");
77-
7876
ShenandoahHeap* heap = ShenandoahHeap::heap();
7977

78+
assert(collection_set->is_empty(), "Must be empty");
79+
assert(!heap->mode()->is_generational(), "Wrong heuristic for heap mode");
80+
8081
// Check all pinned regions have updated status before choosing the collection set.
8182
heap->assert_pinned_region_status();
8283

@@ -120,7 +121,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec
120121
// Reclaim humongous regions here, and count them as the immediate garbage
121122
#ifdef ASSERT
122123
bool reg_live = region->has_live();
123-
bool bm_live = heap->gc_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom()));
124+
bool bm_live = heap->global_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom()));
124125
assert(reg_live == bm_live,
125126
"Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu",
126127
BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words());

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

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,16 @@ void ShenandoahAsserts::assert_marked_strong(void *interior_loc, oop obj, const
425425
}
426426
}
427427

428+
void ShenandoahAsserts::assert_mark_complete(HeapWord* obj, const char* file, int line) {
429+
const ShenandoahHeap* heap = ShenandoahHeap::heap();
430+
const ShenandoahHeapRegion* region = heap->heap_region_containing(obj);
431+
const ShenandoahGeneration* generation = heap->generation_for(region->affiliation());
432+
if (!generation->is_mark_complete()) {
433+
ShenandoahMessageBuffer msg("Marking should be complete for object " PTR_FORMAT " in the %s generation", p2i(obj), generation->name());
434+
report_vm_error(file, line, msg.buffer());
435+
}
436+
}
437+
428438
void ShenandoahAsserts::assert_in_cset(void* interior_loc, oop obj, const char* file, int line) {
429439
assert_correct(interior_loc, obj, file, line);
430440

@@ -542,23 +552,6 @@ void ShenandoahAsserts::assert_control_or_vm_thread_at_safepoint(bool at_safepoi
542552
report_vm_error(file, line, msg.buffer());
543553
}
544554

545-
void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line) {
546-
if (!ShenandoahSafepoint::is_at_shenandoah_safepoint()) {
547-
// Only shenandoah safepoint operations participate in the active/gc generation scheme
548-
return;
549-
}
550-
551-
ShenandoahHeap* heap = ShenandoahHeap::heap();
552-
ShenandoahGeneration* ggen = heap->gc_generation();
553-
ShenandoahGeneration* agen = heap->active_generation();
554-
if (agen == ggen) {
555-
return;
556-
}
557-
558-
ShenandoahMessageBuffer msg("Active(%s) & GC(%s) Generations aren't reconciled", agen->name(), ggen->name());
559-
report_vm_error(file, line, msg.buffer());
560-
}
561-
562555
bool ShenandoahAsserts::extract_klass_safely(oop obj, narrowKlass& nk, const Klass*& k) {
563556
nk = 0;
564557
k = nullptr;

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class ShenandoahAsserts {
6565
static void assert_marked(void* interior_loc, oop obj, const char* file, int line);
6666
static void assert_marked_weak(void* interior_loc, oop obj, const char* file, int line);
6767
static void assert_marked_strong(void* interior_loc, oop obj, const char* file, int line);
68+
69+
// Assert that marking is complete for the generation where this obj resides
70+
static void assert_mark_complete(HeapWord* obj, const char* file, int line);
6871
static void assert_in_cset(void* interior_loc, oop obj, const char* file, int line);
6972
static void assert_not_in_cset(void* interior_loc, oop obj, const char* file, int line);
7073
static void assert_not_in_cset_loc(void* interior_loc, const char* file, int line);
@@ -76,7 +79,6 @@ class ShenandoahAsserts {
7679
static void assert_heaplocked_or_safepoint(const char* file, int line);
7780
static void assert_control_or_vm_thread_at_safepoint(bool at_safepoint, const char* file, int line);
7881
static void assert_generational(const char* file, int line);
79-
static void assert_generations_reconciled(const char* file, int line);
8082

8183
// Given a possibly invalid oop, extract narrowKlass (if UCCP) and Klass*
8284
// from it safely.
@@ -133,6 +135,9 @@ class ShenandoahAsserts {
133135
#define shenandoah_assert_marked_strong(interior_loc, obj) \
134136
ShenandoahAsserts::assert_marked_strong(interior_loc, obj, __FILE__, __LINE__)
135137

138+
#define shenandoah_assert_mark_complete(obj) \
139+
ShenandoahAsserts::assert_mark_complete(obj, __FILE__, __LINE__)
140+
136141
#define shenandoah_assert_in_cset_if(interior_loc, obj, condition) \
137142
if (condition) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__)
138143
#define shenandoah_assert_in_cset_except(interior_loc, obj, exception) \
@@ -184,10 +189,6 @@ class ShenandoahAsserts {
184189
#define shenandoah_assert_generational() \
185190
ShenandoahAsserts::assert_generational(__FILE__, __LINE__)
186191

187-
// Some limited sanity checking of the _gc_generation and _active_generation fields of ShenandoahHeap
188-
#define shenandoah_assert_generations_reconciled() \
189-
ShenandoahAsserts::assert_generations_reconciled(__FILE__, __LINE__)
190-
191192
#else
192193
#define shenandoah_assert_in_heap_bounds(interior_loc, obj)
193194
#define shenandoah_assert_in_heap_bounds_or_null(interior_loc, obj)
@@ -217,6 +218,8 @@ class ShenandoahAsserts {
217218
#define shenandoah_assert_marked_strong_except(interior_loc, obj, exception)
218219
#define shenandoah_assert_marked_strong(interior_loc, obj)
219220

221+
#define shenandoah_assert_mark_complete(obj)
222+
220223
#define shenandoah_assert_in_cset_if(interior_loc, obj, condition)
221224
#define shenandoah_assert_in_cset_except(interior_loc, obj, exception)
222225
#define shenandoah_assert_in_cset(interior_loc, obj)
@@ -241,7 +244,6 @@ class ShenandoahAsserts {
241244
#define shenandoah_assert_control_or_vm_thread()
242245
#define shenandoah_assert_control_or_vm_thread_at_safepoint()
243246
#define shenandoah_assert_generational()
244-
#define shenandoah_assert_generations_reconciled()
245247

246248
#endif
247249

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

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class ShenandoahBreakpointMarkScope : public StackObj {
9191
};
9292

9393
ShenandoahConcurrentGC::ShenandoahConcurrentGC(ShenandoahGeneration* generation, bool do_old_gc_bootstrap) :
94+
ShenandoahGC(generation),
9495
_mark(generation),
95-
_generation(generation),
9696
_degen_point(ShenandoahDegenPoint::_degenerated_unset),
9797
_abbreviated(false),
9898
_do_old_gc_bootstrap(do_old_gc_bootstrap) {
@@ -576,7 +576,7 @@ void ShenandoahConcurrentGC::entry_promote_in_place() const {
576576
ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::promote_in_place);
577577
EventMark em("%s", "Promote in place");
578578

579-
ShenandoahGenerationalHeap::heap()->promote_regions_in_place(true);
579+
ShenandoahGenerationalHeap::heap()->promote_regions_in_place(_generation, true);
580580
}
581581

582582
void ShenandoahConcurrentGC::entry_update_thread_roots() {
@@ -706,7 +706,7 @@ void ShenandoahConcurrentGC::op_init_mark() {
706706

707707
if (ShenandoahVerify) {
708708
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::init_mark_verify);
709-
heap->verifier()->verify_before_concmark();
709+
heap->verifier()->verify_before_concmark(_generation);
710710
}
711711

712712
if (VerifyBeforeGC) {
@@ -763,7 +763,7 @@ void ShenandoahConcurrentGC::op_final_mark() {
763763
assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
764764

765765
if (ShenandoahVerify) {
766-
heap->verifier()->verify_roots_no_forwarded();
766+
heap->verifier()->verify_roots_no_forwarded(_generation);
767767
}
768768

769769
if (!heap->cancelled_gc()) {
@@ -791,7 +791,7 @@ void ShenandoahConcurrentGC::op_final_mark() {
791791

792792
if (ShenandoahVerify) {
793793
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
794-
heap->verifier()->verify_before_evacuation();
794+
heap->verifier()->verify_before_evacuation(_generation);
795795
}
796796

797797
heap->set_evacuation_in_progress(true);
@@ -806,9 +806,9 @@ void ShenandoahConcurrentGC::op_final_mark() {
806806
if (ShenandoahVerify) {
807807
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
808808
if (has_in_place_promotions(heap)) {
809-
heap->verifier()->verify_after_concmark_with_promotions();
809+
heap->verifier()->verify_after_concmark_with_promotions(_generation);
810810
} else {
811-
heap->verifier()->verify_after_concmark();
811+
heap->verifier()->verify_after_concmark(_generation);
812812
}
813813
}
814814
}
@@ -877,18 +877,20 @@ void ShenandoahConcurrentGC::op_weak_refs() {
877877
class ShenandoahEvacUpdateCleanupOopStorageRootsClosure : public BasicOopIterateClosure {
878878
private:
879879
ShenandoahHeap* const _heap;
880+
ShenandoahGeneration* const _generation;
880881
ShenandoahMarkingContext* const _mark_context;
881882
bool _evac_in_progress;
882883
Thread* const _thread;
883884

884885
public:
885-
ShenandoahEvacUpdateCleanupOopStorageRootsClosure();
886+
explicit ShenandoahEvacUpdateCleanupOopStorageRootsClosure(ShenandoahGeneration* generation);
886887
void do_oop(oop* p);
887888
void do_oop(narrowOop* p);
888889
};
889890

890-
ShenandoahEvacUpdateCleanupOopStorageRootsClosure::ShenandoahEvacUpdateCleanupOopStorageRootsClosure() :
891+
ShenandoahEvacUpdateCleanupOopStorageRootsClosure::ShenandoahEvacUpdateCleanupOopStorageRootsClosure(ShenandoahGeneration* generation) :
891892
_heap(ShenandoahHeap::heap()),
893+
_generation(generation),
892894
_mark_context(ShenandoahHeap::heap()->marking_context()),
893895
_evac_in_progress(ShenandoahHeap::heap()->is_evacuation_in_progress()),
894896
_thread(Thread::current()) {
@@ -898,8 +900,7 @@ void ShenandoahEvacUpdateCleanupOopStorageRootsClosure::do_oop(oop* p) {
898900
const oop obj = RawAccess<>::oop_load(p);
899901
if (!CompressedOops::is_null(obj)) {
900902
if (!_mark_context->is_marked(obj)) {
901-
shenandoah_assert_generations_reconciled();
902-
if (_heap->is_in_active_generation(obj)) {
903+
if (_generation->contains(obj)) {
903904
// Note: The obj is dead here. Do not touch it, just clear.
904905
ShenandoahHeap::atomic_clear_oop(p, obj);
905906
}
@@ -942,29 +943,31 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public WorkerTask {
942943
ShenandoahClassLoaderDataRoots<true /* concurrent */>
943944
_cld_roots;
944945
ShenandoahConcurrentNMethodIterator _nmethod_itr;
946+
ShenandoahGeneration* _generation;
945947
ShenandoahPhaseTimings::Phase _phase;
946948

947949
public:
948-
ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
950+
ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahGeneration* generation, ShenandoahPhaseTimings::Phase phase) :
949951
WorkerTask("Shenandoah Evacuate/Update Concurrent Weak Roots"),
950952
_vm_roots(phase),
951953
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
952954
_nmethod_itr(ShenandoahCodeRoots::table()),
955+
_generation(generation),
953956
_phase(phase) {}
954957

955958
~ShenandoahConcurrentWeakRootsEvacUpdateTask() {
956959
// Notify runtime data structures of potentially dead oops
957960
_vm_roots.report_num_dead();
958961
}
959962

960-
void work(uint worker_id) {
963+
void work(uint worker_id) override {
961964
ShenandoahConcurrentWorkerSession worker_session(worker_id);
962965
ShenandoahSuspendibleThreadSetJoiner sts_join;
963966
{
964967
ShenandoahEvacOOMScope oom;
965968
// jni_roots and weak_roots are OopStorage backed roots, concurrent iteration
966969
// may race against OopStorage::release() calls.
967-
ShenandoahEvacUpdateCleanupOopStorageRootsClosure cl;
970+
ShenandoahEvacUpdateCleanupOopStorageRootsClosure cl(_generation);
968971
_vm_roots.oops_do(&cl, worker_id);
969972
}
970973

@@ -999,7 +1002,7 @@ void ShenandoahConcurrentGC::op_weak_roots() {
9991002
// Concurrent weak root processing
10001003
ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_weak_roots_work);
10011004
ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::conc_weak_roots_work);
1002-
ShenandoahConcurrentWeakRootsEvacUpdateTask task(ShenandoahPhaseTimings::conc_weak_roots_work);
1005+
ShenandoahConcurrentWeakRootsEvacUpdateTask task(_generation, ShenandoahPhaseTimings::conc_weak_roots_work);
10031006
heap->workers()->run_task(&task);
10041007
}
10051008

@@ -1105,19 +1108,19 @@ void ShenandoahConcurrentGC::op_cleanup_early() {
11051108
}
11061109

11071110
void ShenandoahConcurrentGC::op_evacuate() {
1108-
ShenandoahHeap::heap()->evacuate_collection_set(true /*concurrent*/);
1111+
ShenandoahHeap::heap()->evacuate_collection_set(_generation, true /*concurrent*/);
11091112
}
11101113

11111114
void ShenandoahConcurrentGC::op_init_update_refs() {
1112-
ShenandoahHeap* const heap = ShenandoahHeap::heap();
11131115
if (ShenandoahVerify) {
1116+
ShenandoahHeap* const heap = ShenandoahHeap::heap();
11141117
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::init_update_refs_verify);
1115-
heap->verifier()->verify_before_update_refs();
1118+
heap->verifier()->verify_before_update_refs(_generation);
11161119
}
11171120
}
11181121

11191122
void ShenandoahConcurrentGC::op_update_refs() {
1120-
ShenandoahHeap::heap()->update_heap_references(true /*concurrent*/);
1123+
ShenandoahHeap::heap()->update_heap_references(_generation, true /*concurrent*/);
11211124
}
11221125

11231126
class ShenandoahUpdateThreadHandshakeClosure : public HandshakeClosure {
@@ -1163,7 +1166,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() {
11631166

11641167
// Has to be done before cset is clear
11651168
if (ShenandoahVerify) {
1166-
heap->verifier()->verify_roots_in_to_space();
1169+
heap->verifier()->verify_roots_in_to_space(_generation);
11671170
}
11681171

11691172
// If we are running in generational mode and this is an aging cycle, this will also age active
@@ -1198,7 +1201,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() {
11981201

11991202
if (ShenandoahVerify) {
12001203
ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify);
1201-
heap->verifier()->verify_after_update_refs();
1204+
heap->verifier()->verify_after_update_refs(_generation);
12021205
}
12031206

12041207
if (VerifyAfterGC) {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class ShenandoahConcurrentGC : public ShenandoahGC {
4747

4848
protected:
4949
ShenandoahConcurrentMark _mark;
50-
ShenandoahGeneration* const _generation;
5150

5251
private:
5352
ShenandoahDegenPoint _degen_point;

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,11 @@ class ShenandoahConcurrentMarkingTask : public WorkerTask {
5656
}
5757

5858
void work(uint worker_id) {
59-
ShenandoahHeap* heap = ShenandoahHeap::heap();
6059
ShenandoahConcurrentWorkerSession worker_session(worker_id);
6160
ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::conc_mark, ShenandoahPhaseTimings::ParallelMark, worker_id, true);
6261
ShenandoahSuspendibleThreadSetJoiner stsj;
63-
// Do not use active_generation() : we must use the gc_generation() set by
64-
// ShenandoahGCScope on the ControllerThread's stack; no safepoint may
65-
// intervene to update active_generation, so we can't
66-
// shenandoah_assert_generations_reconciled() here.
67-
ShenandoahReferenceProcessor* rp = heap->gc_generation()->ref_processor();
68-
assert(rp != nullptr, "need reference processor");
6962
StringDedup::Requests requests;
70-
_cm->mark_loop(worker_id, _terminator, rp, GENERATION, true /*cancellable*/,
63+
_cm->mark_loop(worker_id, _terminator, GENERATION, true /*cancellable*/,
7164
ShenandoahStringDedup::is_enabled() ? ENQUEUE_DEDUP : NO_DEDUP,
7265
&requests);
7366
}
@@ -106,9 +99,6 @@ class ShenandoahFinalMarkingTask : public WorkerTask {
10699

107100
ShenandoahParallelWorkerSession worker_session(worker_id);
108101
StringDedup::Requests requests;
109-
ShenandoahReferenceProcessor* rp = heap->gc_generation()->ref_processor();
110-
shenandoah_assert_generations_reconciled();
111-
112102
// First drain remaining SATB buffers.
113103
{
114104
ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
@@ -122,7 +112,7 @@ class ShenandoahFinalMarkingTask : public WorkerTask {
122112
ShenandoahSATBAndRemarkThreadsClosure tc(satb_mq_set);
123113
Threads::possibly_parallel_threads_do(true /* is_par */, &tc);
124114
}
125-
_cm->mark_loop(worker_id, _terminator, rp, GENERATION, false /*not cancellable*/,
115+
_cm->mark_loop(worker_id, _terminator, GENERATION, false /*not cancellable*/,
126116
_dedup_string ? ENQUEUE_DEDUP : NO_DEDUP,
127117
&requests);
128118
assert(_cm->task_queues()->is_empty(), "Should be empty");

0 commit comments

Comments
 (0)