diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index a32945eb7157cdfd465c92cb0fe364d6b2578ffc..c609f10f6206f458cf1577895c5f6b41410b561d 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -2809,6 +2809,23 @@ bool CMSCollector::is_cms_reachable(HeapWord* addr) { } } + +void +CMSCollector::print_on_error(outputStream* st) { + CMSCollector* collector = ConcurrentMarkSweepGeneration::_collector; + if (collector != NULL) { + CMSBitMap* bitmap = &collector->_markBitMap; + st->print_cr("Marking Bits: (CMSBitMap*) " PTR_FORMAT, bitmap); + bitmap->print_on_error(st, " Bits: "); + + st->cr(); + + CMSBitMap* mut_bitmap = &collector->_modUnionTable; + st->print_cr("Mod Union Table: (CMSBitMap*) " PTR_FORMAT, mut_bitmap); + mut_bitmap->print_on_error(st, " Bits: "); + } +} + //////////////////////////////////////////////////////// // CMS Verification Support //////////////////////////////////////////////////////// @@ -6531,6 +6548,10 @@ void CMSBitMap::dirty_range_iterate_clear(MemRegion mr, MemRegionClosure* cl) { } } +void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + #ifndef PRODUCT void CMSBitMap::assert_locked() const { CMSLockVerifier::assert_locked(lock()); diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index edb97487f25a8810067a2bc917f06abacc00d65d..aa84d7166701eba8add19290251214dfcaa801c3 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -151,6 +151,8 @@ class CMSBitMap VALUE_OBJ_CLASS_SPEC { size_t heapWordToOffset(HeapWord* addr) const; size_t heapWordDiffToOffsetDiff(size_t diff) const; + void print_on_error(outputStream* st, const char* prefix) const; + // debugging // is this address range covered by the bit-map? NOT_PRODUCT( @@ -984,6 +986,8 @@ class CMSCollector: public CHeapObj { CMSAdaptiveSizePolicy* size_policy(); CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters(); + static void print_on_error(outputStream* st); + // debugging void verify(); bool verify_after_remark(); diff --git a/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/src/share/vm/gc_implementation/g1/concurrentMark.cpp index d9d70620e4776bb223ce862a1840490ac301e1ca..03086a3bfb692e8199d8cf880847e68658c714d8 100644 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -101,6 +101,10 @@ bool CMBitMapRO::covers(ReservedSpace heap_rs) const { } #endif +void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + bool CMBitMap::allocate(ReservedSpace heap_rs) { _bmStartWord = (HeapWord*)(heap_rs.base()); _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes @@ -3277,6 +3281,13 @@ void ConcurrentMark::print_worker_threads_on(outputStream* st) const { } } +void ConcurrentMark::print_on_error(outputStream* st) const { + st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, + _prevMarkBitMap, _nextMarkBitMap); + _prevMarkBitMap->print_on_error(st, " Prev Bits: "); + _nextMarkBitMap->print_on_error(st, " Next Bits: "); +} + // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { if (should_yield()) { diff --git a/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 43554a5c991f57b10aa67376646047046f2dee5b..211a728e23e783897af43804a12f0ed2c1ccbdb7 100644 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -113,6 +113,8 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { return res; } + void print_on_error(outputStream* st, const char* prefix) const; + // debugging NOT_PRODUCT(bool covers(ReservedSpace rs) const;) }; @@ -829,6 +831,8 @@ public: void print_worker_threads_on(outputStream* st) const; + void print_on_error(outputStream* st) const; + // The following indicate whether a given verbose level has been // set. Notice that anything above stats is conditional to // _MARKING_VERBOSE_ having been set to 1 diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 610942585e7014748a7a64c8f9719bfc59295fc6..fdb602e7012a15227e222f673a34d7fe2c8ad724 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3427,6 +3427,15 @@ void G1CollectedHeap::print_extended_on(outputStream* st) const { heap_region_iterate(&blk); } +void G1CollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (_cm != NULL) { + st->cr(); + _cm->print_on_error(st); + } +} + void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { if (G1CollectedHeap::use_parallel_gc_threads()) { workers()->print_worker_threads_on(st); diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 557daf85eead73a6f6d7bf122f00322c319ee9e5..4fbf0ff367a183da5f5edbd53579e82c33448d76 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1575,6 +1575,7 @@ public: virtual void verify(bool silent); virtual void print_on(outputStream* st) const; virtual void print_extended_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; diff --git a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp index 38061a9dfc54962a70e7fe2d885d80b84d6c5fd1..fdc0febfa2130c954b5986c7547a1879f39c19a0 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp @@ -173,6 +173,12 @@ public: void reset_counters(); #endif // #ifndef PRODUCT + void print_on_error(outputStream* st) const { + st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this); + _beg_bits.print_on_error(st, " Begin Bits: "); + _end_bits.print_on_error(st, " End Bits: "); + } + #ifdef ASSERT void verify_clear() const; inline void verify_bit(idx_t bit) const; diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 5d77e31b6c8a8a6be078da6b03455b3741a8072e..9ea2fa856c339ad9cd73d3e3ebcebcfdc41efc9d 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -648,6 +648,15 @@ void ParallelScavengeHeap::print_on(outputStream* st) const { MetaspaceAux::print_on(st); } +void ParallelScavengeHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (UseParallelOldGC) { + st->cr(); + PSParallelCompact::print_on_error(st); + } +} + void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const { PSScavenge::gc_task_manager()->threads_do(tc); } diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index ebf554ac52cce5f0ce062b69adab0ef3db44065e..c0933fe16c6c536b9bdcf2e744e6b3e94d22cf89 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -220,6 +220,7 @@ class ParallelScavengeHeap : public CollectedHeap { void prepare_for_verify(); virtual void print_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; diff --git a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index d3d29aaf9f40d424226a6e82f054bbd693c1f0ab..487a4e565534a767644348f4469a74118d1ee136 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -165,6 +165,10 @@ void SplitInfo::verify_clear() #endif // #ifdef ASSERT +void PSParallelCompact::print_on_error(outputStream* st) { + _mark_bitmap.print_on_error(st); +} + #ifndef PRODUCT const char* PSParallelCompact::space_names[] = { "old ", "eden", "from", "to " diff --git a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp index d26f5b0b72e704345e59cf827bb057a93158df5b..68b54fb9b135c153c3751e7ba266ae2d9c570cd0 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp @@ -1163,6 +1163,8 @@ class PSParallelCompact : AllStatic { // Time since last full gc (in milliseconds). static jlong millis_since_last_gc(); + static void print_on_error(outputStream* st); + #ifndef PRODUCT // Debugging support. static const char* space_names[last_space_id]; diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp index 7c63f8916b8db397a0d72bb562ffa914b4ceff60..88929343c08f99fda3c89046482448ecd741d02f 100644 --- a/src/share/vm/gc_interface/collectedHeap.hpp +++ b/src/share/vm/gc_interface/collectedHeap.hpp @@ -567,6 +567,14 @@ class CollectedHeap : public CHeapObj { print_on(st); } + virtual void print_on_error(outputStream* st) const { + st->print_cr("Heap:"); + print_extended_on(st); + st->cr(); + + _barrier_set->print_on(st); + } + // Print all GC threads (other than the VM thread) // used by this heap. virtual void print_gc_threads_on(outputStream* st) const = 0; diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp index 60f577a2cea22f147896db5cfc659f4723000cd9..f39631ae00b7c0665799fc5804d34ccfe7f97bc6 100644 --- a/src/share/vm/memory/genCollectedHeap.cpp +++ b/src/share/vm/memory/genCollectedHeap.cpp @@ -1133,6 +1133,17 @@ void GenCollectedHeap::print_gc_threads_on(outputStream* st) const { #endif // INCLUDE_ALL_GCS } +void GenCollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + st->cr(); + CMSCollector::print_on_error(st); + } +#endif // INCLUDE_ALL_GCS +} + void GenCollectedHeap::print_tracing_info() const { if (TraceGen0Time) { get_gen(0)->print_summary_info(); diff --git a/src/share/vm/memory/genCollectedHeap.hpp b/src/share/vm/memory/genCollectedHeap.hpp index 4d79e24893c8cfa8add06854f7546e77cecf8adf..034511b9b556a0a7f9514562aa5f14149b1dbb1b 100644 --- a/src/share/vm/memory/genCollectedHeap.hpp +++ b/src/share/vm/memory/genCollectedHeap.hpp @@ -344,6 +344,7 @@ public: virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; + virtual void print_on_error(outputStream* st) const; // PrintGC, PrintGCDetails support void print_heap_change(size_t prev_used) const; diff --git a/src/share/vm/utilities/bitMap.cpp b/src/share/vm/utilities/bitMap.cpp index 0b12b1180792b086535404ee5e65db76c162aaab..152b40d39c1f49827ec605b84fa4227a3fb65816 100644 --- a/src/share/vm/utilities/bitMap.cpp +++ b/src/share/vm/utilities/bitMap.cpp @@ -516,6 +516,10 @@ BitMap::idx_t BitMap::count_one_bits() const { return sum; } +void BitMap::print_on_error(outputStream* st, const char* prefix) const { + st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")", + prefix, map(), (char*)map() + (size() >> LogBitsPerByte)); +} #ifndef PRODUCT diff --git a/src/share/vm/utilities/bitMap.hpp b/src/share/vm/utilities/bitMap.hpp index 2c0975f6728bf932edebb2a611f2ce3f442bb8b1..2486533ab86d9c878b056b4ea53db776dcc89cbc 100644 --- a/src/share/vm/utilities/bitMap.hpp +++ b/src/share/vm/utilities/bitMap.hpp @@ -262,6 +262,7 @@ class BitMap VALUE_OBJ_CLASS_SPEC { bool is_full() const; bool is_empty() const; + void print_on_error(outputStream* st, const char* prefix) const; #ifndef PRODUCT public: diff --git a/src/share/vm/utilities/vmError.cpp b/src/share/vm/utilities/vmError.cpp index d8fe93b64f373823e8b8e5ecde5b77b71c2e5e4f..e1608cae9deea661a0070d839cbcef4831fff303 100644 --- a/src/share/vm/utilities/vmError.cpp +++ b/src/share/vm/utilities/vmError.cpp @@ -685,13 +685,7 @@ void VMError::report(outputStream* st) { STEP(190, "(printing heap information)" ) if (_verbose && Universe::is_fully_initialized()) { - // Print heap information before vm abort. As we'd like as much - // information as possible in the report we ask for the - // extended (i.e., more detailed) version. - Universe::print_on(st, true /* extended */); - st->cr(); - - Universe::heap()->barrier_set()->print_on(st); + Universe::heap()->print_on_error(st); st->cr(); st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());