提交 c415363c 编写于 作者: B brutisso

7132678: G1: verify that the marking bitmaps have no marks for objects over TAMS

Reviewed-by: jmasa, tschatzl, ehelin
Contributed-by: tony.printezis@oracle.com, bengt.rutisson@oracle.com
上级 10f4e5bf
...@@ -1306,6 +1306,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { ...@@ -1306,6 +1306,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
Universe::verify(VerifyOption_G1UsePrevMarking, Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(before)"); " VerifyDuringGC:(before)");
} }
g1h->check_bitmaps("Remark Start");
G1CollectorPolicy* g1p = g1h->g1_policy(); G1CollectorPolicy* g1p = g1h->g1_policy();
g1p->record_concurrent_mark_remark_start(); g1p->record_concurrent_mark_remark_start();
...@@ -1354,6 +1355,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { ...@@ -1354,6 +1355,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
Universe::verify(VerifyOption_G1UseNextMarking, Universe::verify(VerifyOption_G1UseNextMarking,
" VerifyDuringGC:(after)"); " VerifyDuringGC:(after)");
} }
g1h->check_bitmaps("Remark End");
assert(!restart_for_overflow(), "sanity"); assert(!restart_for_overflow(), "sanity");
// Completely reset the marking state since marking completed // Completely reset the marking state since marking completed
set_non_marking_state(); set_non_marking_state();
...@@ -2003,6 +2005,7 @@ void ConcurrentMark::cleanup() { ...@@ -2003,6 +2005,7 @@ void ConcurrentMark::cleanup() {
Universe::verify(VerifyOption_G1UsePrevMarking, Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(before)"); " VerifyDuringGC:(before)");
} }
g1h->check_bitmaps("Cleanup Start");
G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy(); G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
g1p->record_concurrent_mark_cleanup_start(); g1p->record_concurrent_mark_cleanup_start();
...@@ -2149,6 +2152,7 @@ void ConcurrentMark::cleanup() { ...@@ -2149,6 +2152,7 @@ void ConcurrentMark::cleanup() {
Universe::verify(VerifyOption_G1UsePrevMarking, Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(after)"); " VerifyDuringGC:(after)");
} }
g1h->check_bitmaps("Cleanup End");
g1h->verify_region_sets_optional(); g1h->verify_region_sets_optional();
...@@ -3360,6 +3364,11 @@ void ConcurrentMark::print_stats() { ...@@ -3360,6 +3364,11 @@ void ConcurrentMark::print_stats() {
void ConcurrentMark::abort() { void ConcurrentMark::abort() {
// Clear all marks to force marking thread to do nothing // Clear all marks to force marking thread to do nothing
_nextMarkBitMap->clearAll(); _nextMarkBitMap->clearAll();
// Note we cannot clear the previous marking bitmap here
// since VerifyDuringGC verifies the objects marked during
// a full GC against the previous bitmap.
// Clear the liveness counting data // Clear the liveness counting data
clear_all_count_data(); clear_all_count_data();
// Empty mark stack // Empty mark stack
......
...@@ -771,6 +771,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, ...@@ -771,6 +771,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first,
// match new_top. // match new_top.
assert(hr == NULL || assert(hr == NULL ||
(hr->end() == new_end && hr->top() == new_top), "sanity"); (hr->end() == new_end && hr->top() == new_top), "sanity");
check_bitmaps("Humongous Region Allocation", first_hr);
assert(first_hr->used() == word_size * HeapWordSize, "invariant"); assert(first_hr->used() == word_size * HeapWordSize, "invariant");
_summary_bytes_used += first_hr->used(); _summary_bytes_used += first_hr->used();
...@@ -1329,6 +1330,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, ...@@ -1329,6 +1330,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
verify_before_gc(); verify_before_gc();
check_bitmaps("Full GC Start");
pre_full_gc_dump(gc_timer); pre_full_gc_dump(gc_timer);
COMPILER2_PRESENT(DerivedPointerTable::clear()); COMPILER2_PRESENT(DerivedPointerTable::clear());
...@@ -1502,6 +1504,18 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, ...@@ -1502,6 +1504,18 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
verify_after_gc(); verify_after_gc();
// Clear the previous marking bitmap, if needed for bitmap verification.
// Note we cannot do this when we clear the next marking bitmap in
// ConcurrentMark::abort() above since VerifyDuringGC verifies the
// objects marked during a full GC against the previous bitmap.
// But we need to clear it before calling check_bitmaps below since
// the full GC has compacted objects and updated TAMS but not updated
// the prev bitmap.
if (G1VerifyBitmaps) {
((CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll();
}
check_bitmaps("Full GC End");
// Start a new incremental collection set for the next pause // Start a new incremental collection set for the next pause
assert(g1_policy()->collection_set() == NULL, "must be"); assert(g1_policy()->collection_set() == NULL, "must be");
g1_policy()->start_incremental_cset_building(); g1_policy()->start_incremental_cset_building();
...@@ -3986,6 +4000,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { ...@@ -3986,6 +4000,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
increment_gc_time_stamp(); increment_gc_time_stamp();
verify_before_gc(); verify_before_gc();
check_bitmaps("GC Start");
COMPILER2_PRESENT(DerivedPointerTable::clear()); COMPILER2_PRESENT(DerivedPointerTable::clear());
...@@ -4231,6 +4246,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { ...@@ -4231,6 +4246,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
increment_gc_time_stamp(); increment_gc_time_stamp();
verify_after_gc(); verify_after_gc();
check_bitmaps("GC End");
assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); assert(!ref_processor_stw()->discovery_enabled(), "Postcondition");
ref_processor_stw()->verify_no_references_recorded(); ref_processor_stw()->verify_no_references_recorded();
...@@ -6086,6 +6102,11 @@ void G1CollectedHeap::free_region(HeapRegion* hr, ...@@ -6086,6 +6102,11 @@ void G1CollectedHeap::free_region(HeapRegion* hr,
assert(!hr->is_empty(), "the region should not be empty"); assert(!hr->is_empty(), "the region should not be empty");
assert(free_list != NULL, "pre-condition"); assert(free_list != NULL, "pre-condition");
if (G1VerifyBitmaps) {
MemRegion mr(hr->bottom(), hr->end());
concurrent_mark()->clearRangePrevBitmap(mr);
}
// Clear the card counts for this region. // Clear the card counts for this region.
// Note: we only need to do this if the region is not young // Note: we only need to do this if the region is not young
// (since we don't refine cards in young regions). // (since we don't refine cards in young regions).
...@@ -6220,7 +6241,87 @@ void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) { ...@@ -6220,7 +6241,87 @@ void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
void G1CollectedHeap::verify_dirty_young_regions() { void G1CollectedHeap::verify_dirty_young_regions() {
verify_dirty_young_list(_young_list->first_region()); verify_dirty_young_list(_young_list->first_region());
} }
#endif
bool G1CollectedHeap::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap,
HeapWord* tams, HeapWord* end) {
guarantee(tams <= end,
err_msg("tams: "PTR_FORMAT" end: "PTR_FORMAT, tams, end));
HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end);
if (result < end) {
gclog_or_tty->cr();
gclog_or_tty->print_cr("## wrong marked address on %s bitmap: "PTR_FORMAT,
bitmap_name, result);
gclog_or_tty->print_cr("## %s tams: "PTR_FORMAT" end: "PTR_FORMAT,
bitmap_name, tams, end);
return false;
}
return true;
}
bool G1CollectedHeap::verify_bitmaps(const char* caller, HeapRegion* hr) {
CMBitMapRO* prev_bitmap = concurrent_mark()->prevMarkBitMap();
CMBitMapRO* next_bitmap = (CMBitMapRO*) concurrent_mark()->nextMarkBitMap();
HeapWord* bottom = hr->bottom();
HeapWord* ptams = hr->prev_top_at_mark_start();
HeapWord* ntams = hr->next_top_at_mark_start();
HeapWord* end = hr->end();
bool res_p = verify_no_bits_over_tams("prev", prev_bitmap, ptams, end);
bool res_n = true;
// We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window
// we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap
// if we happen to be in that state.
if (mark_in_progress() || !_cmThread->in_progress()) {
res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
}
if (!res_p || !res_n) {
gclog_or_tty->print_cr("#### Bitmap verification failed for "HR_FORMAT,
HR_FORMAT_PARAMS(hr));
gclog_or_tty->print_cr("#### Caller: %s", caller);
return false;
}
return true;
}
void G1CollectedHeap::check_bitmaps(const char* caller, HeapRegion* hr) {
if (!G1VerifyBitmaps) return;
guarantee(verify_bitmaps(caller, hr), "bitmap verification");
}
class G1VerifyBitmapClosure : public HeapRegionClosure {
private:
const char* _caller;
G1CollectedHeap* _g1h;
bool _failures;
public:
G1VerifyBitmapClosure(const char* caller, G1CollectedHeap* g1h) :
_caller(caller), _g1h(g1h), _failures(false) { }
bool failures() { return _failures; }
virtual bool doHeapRegion(HeapRegion* hr) {
if (hr->continuesHumongous()) return false;
bool result = _g1h->verify_bitmaps(_caller, hr);
if (!result) {
_failures = true;
}
return false;
}
};
void G1CollectedHeap::check_bitmaps(const char* caller) {
if (!G1VerifyBitmaps) return;
G1VerifyBitmapClosure cl(caller, this);
heap_region_iterate(&cl);
guarantee(!cl.failures(), "bitmap verification");
}
#endif // PRODUCT
void G1CollectedHeap::cleanUpCardTable() { void G1CollectedHeap::cleanUpCardTable() {
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
...@@ -6609,6 +6710,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, ...@@ -6609,6 +6710,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size,
if (new_alloc_region != NULL) { if (new_alloc_region != NULL) {
set_region_short_lived_locked(new_alloc_region); set_region_short_lived_locked(new_alloc_region);
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Eden, young_list_full); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Eden, young_list_full);
check_bitmaps("Mutator Region Allocation", new_alloc_region);
return new_alloc_region; return new_alloc_region;
} }
} }
...@@ -6675,8 +6777,10 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, ...@@ -6675,8 +6777,10 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size,
if (survivor) { if (survivor) {
new_alloc_region->set_survivor(); new_alloc_region->set_survivor();
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor);
check_bitmaps("Survivor Region Allocation", new_alloc_region);
} else { } else {
_hr_printer.alloc(new_alloc_region, G1HRPrinter::Old); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Old);
check_bitmaps("Old Region Allocation", new_alloc_region);
} }
bool during_im = g1_policy()->during_initial_mark_pause(); bool during_im = g1_policy()->during_initial_mark_pause();
new_alloc_region->note_start_of_copying(during_im); new_alloc_region->note_start_of_copying(during_im);
......
...@@ -1190,6 +1190,30 @@ public: ...@@ -1190,6 +1190,30 @@ public:
void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN; void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN;
void verify_dirty_young_regions() PRODUCT_RETURN; void verify_dirty_young_regions() PRODUCT_RETURN;
#ifndef PRODUCT
// Make sure that the given bitmap has no marked objects in the
// range [from,limit). If it does, print an error message and return
// false. Otherwise, just return true. bitmap_name should be "prev"
// or "next".
bool verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap,
HeapWord* from, HeapWord* limit);
// Verify that the prev / next bitmap range [tams,end) for the given
// region has no marks. Return true if all is well, false if errors
// are detected.
bool verify_bitmaps(const char* caller, HeapRegion* hr);
#endif // PRODUCT
// If G1VerifyBitmaps is set, verify that the marking bitmaps for
// the given region do not have any spurious marks. If errors are
// detected, print appropriate error messages and crash.
void check_bitmaps(const char* caller, HeapRegion* hr) PRODUCT_RETURN;
// If G1VerifyBitmaps is set, verify that the marking bitmaps do not
// have any spurious marks. If errors are detected, print
// appropriate error messages and crash.
void check_bitmaps(const char* caller) PRODUCT_RETURN;
// verify_region_sets() performs verification over the region // verify_region_sets() performs verification over the region
// lists. It will be compiled in the product code to be used when // lists. It will be compiled in the product code to be used when
// necessary (i.e., during heap verification). // necessary (i.e., during heap verification).
......
...@@ -202,6 +202,7 @@ public: ...@@ -202,6 +202,7 @@ public:
hr->note_self_forwarding_removal_start(during_initial_mark, hr->note_self_forwarding_removal_start(during_initial_mark,
during_conc_mark); during_conc_mark);
_g1h->check_bitmaps("Self-Forwarding Ptr Removal", hr);
// In the common case (i.e. when there is no evacuation // In the common case (i.e. when there is no evacuation
// failure) we make sure that the following is done when // failure) we make sure that the following is done when
......
...@@ -329,7 +329,10 @@ ...@@ -329,7 +329,10 @@
"remembered set when verifying the heap during a full GC.") \ "remembered set when verifying the heap during a full GC.") \
\ \
diagnostic(bool, G1VerifyHeapRegionCodeRoots, false, \ diagnostic(bool, G1VerifyHeapRegionCodeRoots, false, \
"Verify the code root lists attached to each heap region.") "Verify the code root lists attached to each heap region.") \
\
develop(bool, G1VerifyBitmaps, false, \
"Verifies the consistency of the marking bitmaps")
G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册