--- old/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2013-03-16 11:20:16.331378685 +0100 +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp 2013-03-16 11:20:16.271378686 +0100 @@ -4906,10 +4906,12 @@ Mutex::_no_safepoint_check_flag); assert(!init_mark_was_synchronous, "but that's impossible!"); checkpointRootsFinalWork(asynch, clear_all_soft_refs, false); + _gc_tracer_cm->report_class_count_after_gc(&_is_alive_closure); } else { // already have all the locks checkpointRootsFinalWork(asynch, clear_all_soft_refs, init_mark_was_synchronous); + _gc_tracer_cm->report_class_count_after_gc(&_is_alive_closure); } verify_work_stacks_empty(); verify_overflow_empty(); --- old/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp 2013-03-16 11:20:16.755378679 +0100 +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp 2013-03-16 11:20:16.695378680 +0100 @@ -27,6 +27,7 @@ #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" #include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/isGCActiveMark.hpp" #include "memory/gcLocker.inline.hpp" --- old/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2013-03-16 11:20:17.083378675 +0100 +++ new/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2013-03-16 11:20:17.023378676 +0100 @@ -37,6 +37,7 @@ #include "gc_implementation/g1/heapRegionSeq.inline.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" #include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/referencePolicy.hpp" @@ -1201,6 +1202,9 @@ _remark_times.add((now - start) * 1000.0); g1p->record_concurrent_mark_remark_end(); + + G1CMIsAliveClosure is_alive(g1h); + g1h->gc_tracer_cm()->report_class_count_after_gc(&is_alive); } // Base class of the closures that finalize and verify the --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-03-16 11:20:17.487378669 +0100 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-03-16 11:20:17.423378671 +0100 @@ -34,6 +34,7 @@ #include "gc_implementation/g1/heapRegionSeq.hpp" #include "gc_implementation/g1/heapRegionSets.hpp" #include "gc_implementation/shared/hSpaceCounters.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/barrierSet.hpp" #include "memory/memRegion.hpp" @@ -1178,6 +1179,7 @@ ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } + G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } virtual size_t capacity() const; virtual size_t used() const; --- old/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp 2013-03-16 11:20:17.875378664 +0100 +++ new/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp 2013-03-16 11:20:17.811378666 +0100 @@ -91,6 +91,8 @@ mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); + gc_tracer()->report_class_count_after_gc(&GenMarkSweep::is_alive); + mark_sweep_phase2(); // Don't add any more derived pointers during phase3 --- old/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp 2013-03-16 11:20:18.219378660 +0100 +++ new/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp 2013-03-16 11:20:18.159378660 +0100 @@ -206,6 +206,8 @@ mark_sweep_phase1(clear_all_softrefs); + _gc_tracer->report_class_count_after_gc(is_alive_closure()); + mark_sweep_phase2(); // Don't add any more derived pointers during phase3 --- old/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp 2013-03-16 11:20:18.579378655 +0100 +++ new/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp 2013-03-16 11:20:18.511378656 +0100 @@ -2088,6 +2088,8 @@ marking_start.update(); marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer); + _gc_tracer.report_class_count_after_gc(is_alive_closure()); + #ifndef PRODUCT if (TraceParallelOldGCMarkingPhase) { gclog_or_tty->print_cr("marking_phase: cas_tries %d cas_retries %d " --- old/src/share/vm/gc_implementation/shared/gcTrace.hpp 2013-03-16 11:20:19.015378649 +0100 +++ new/src/share/vm/gc_implementation/shared/gcTrace.hpp 2013-03-16 11:20:18.951378650 +0100 @@ -41,6 +41,7 @@ class PSHeapSummary; class ReferenceProcessorStats; class TimePartitions; +class BoolObjectClosure; class SharedGCInfo VALUE_OBJ_CLASS_SPEC { static const jlong UNSET_TIMESTAMP = -1; @@ -126,6 +127,7 @@ void report_gc_end(jlong timestamp, TimePartitions* time_partitions); void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const PermGenSummary& perm_gen_summary) const; void report_gc_reference_processing(const ReferenceProcessorStats& rp) const; + void report_class_count_after_gc(BoolObjectClosure* object_filter); bool has_reported_gc_start() const; --- old/src/share/vm/gc_implementation/shared/gcTraceSend.cpp 2013-03-16 11:20:19.371378644 +0100 +++ new/src/share/vm/gc_implementation/shared/gcTraceSend.cpp 2013-03-16 11:20:19.299378645 +0100 @@ -27,7 +27,11 @@ #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcWhen.hpp" +#include "memory/heapInspection.hpp" +#include "memory/iterator.hpp" +#include "trace/traceBackend.hpp" #include "trace/tracing.hpp" +#include "utilities/globalDefinitions.hpp" #ifndef SERIALGC #include "gc_implementation/g1/g1YCTypes.hpp" #endif @@ -60,6 +64,43 @@ } } +#if INCLUDE_TRACE +static void send_class_count_event(GCId gc_id, + const char* class_name, + jlong count, + julong total_size) { + EventClassCountAfterGC e; + if (e.should_commit()) { + e.set_gcId(gc_id); + e.set_class(class_name); + e.set_count(count); + e.set_totalSize(total_size); + e.commit(); + } +} + +class ClassCountEventSenderClosure : public KlassInfoClosure { + GCId _gc_id; + public: + ClassCountEventSenderClosure(GCId gc_id) : _gc_id(gc_id) {} + private: + void do_cinfo(KlassInfoEntry* entry) { + const char *class_name = entry->klass()->klass_part()->external_name(); + size_t size = entry->words() * BytesPerWord; + send_class_count_event(_gc_id, class_name ,entry->count(), size); + } +}; +#endif + +void GCTracer::report_class_count_after_gc(BoolObjectClosure *object_filter) { +#if INCLUDE_TRACE + if (Tracing::enabled(EventClassCountAfterGC::eventId)) { + ClassCountEventSenderClosure event_sender(_shared_gc_info.id()); + HeapInspection::instance_inspection(object_filter, &event_sender); + } +#endif +} + void ParallelOldTracer::send_parallel_old_event() const { EventGCParallelOld e(UNTIMED); if (e.should_commit()) { --- old/src/share/vm/memory/genMarkSweep.cpp 2013-03-16 11:20:19.719378640 +0100 +++ new/src/share/vm/memory/genMarkSweep.cpp 2013-03-16 11:20:19.655378640 +0100 @@ -110,6 +110,8 @@ mark_sweep_phase1(level, clear_all_softrefs); + gc_tracer()->report_class_count_after_gc(&is_alive); + mark_sweep_phase2(); // Don't add any more derived pointers during phase3 --- old/src/share/vm/memory/heapInspection.cpp 2013-03-16 11:20:20.071378635 +0100 +++ new/src/share/vm/memory/heapInspection.cpp 2013-03-16 11:20:20.007378636 +0100 @@ -228,59 +228,84 @@ private: KlassInfoTable* _cit; size_t _missed_count; + BoolObjectClosure* _filter; public: - RecordInstanceClosure(KlassInfoTable* cit) : - _cit(cit), _missed_count(0) {} + RecordInstanceClosure(BoolObjectClosure* filter, KlassInfoTable* cit) : + _cit(cit), _missed_count(0), _filter(filter) {} void do_object(oop obj) { - if (!_cit->record_instance(obj)) { - _missed_count++; + if (should_visit(obj)) { + if (!_cit->record_instance(obj)) { + _missed_count++; + } } } size_t missed_count() { return _missed_count; } + + private: + bool should_visit(oop obj) { + return _filter == NULL || _filter->do_object_b(obj); + } }; -void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { +size_t HeapInspection::iterate_over_heap(KlassInfoTable* cit) { + return iterate_over_heap(NULL, cit); +} + +size_t HeapInspection::iterate_over_heap(BoolObjectClosure* object_filter, KlassInfoTable* cit) { + RecordInstanceClosure ric(object_filter, cit); + Universe::heap()->object_iterate(&ric); + return ric.missed_count(); +} + +void HeapInspection::instance_inspection(KlassInfoClosure* closure) { + return instance_inspection(NULL, closure); +} + +void HeapInspection::instance_inspection(BoolObjectClosure* object_filter, + KlassInfoClosure* closure) { ResourceMark rm; - HeapWord* ref; - CollectedHeap* heap = Universe::heap(); - bool is_shared_heap = false; - switch (heap->kind()) { - case CollectedHeap::G1CollectedHeap: - case CollectedHeap::GenCollectedHeap: { - is_shared_heap = true; - SharedHeap* sh = (SharedHeap*)heap; - if (need_prologue) { - sh->gc_prologue(false /* !full */); // get any necessary locks, etc. - } - ref = sh->perm_gen()->used_region().start(); - break; - } + KlassInfoTable cit(KlassInfoTable::cit_size, create_random_seed()); + + if (!cit.allocation_failed()) { + iterate_over_heap(object_filter, &cit); + cit.iterate(closure); + } +} + +HeapWord* HeapInspection::create_random_seed() { + if (is_shared_heap()) { + SharedHeap* sh = (SharedHeap*)Universe::heap(); + return sh->perm_gen()->used_region().start(); + } #ifndef SERIALGC - case CollectedHeap::ParallelScavengeHeap: { - ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap; - ref = psh->perm_gen()->object_space()->used_region().start(); - break; - } + ParallelScavengeHeap* psh = (ParallelScavengeHeap*)Universe::heap(); + return psh->perm_gen()->object_space()->used_region().start(); #endif // SERIALGC - default: - ShouldNotReachHere(); // Unexpected heap kind for this op + ShouldNotReachHere(); + return NULL; +} + +bool HeapInspection::is_shared_heap() { + CollectedHeap* heap = Universe::heap(); + return heap->kind() == CollectedHeap::G1CollectedHeap || + heap->kind() == CollectedHeap::GenCollectedHeap; +} + +void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { + ResourceMark rm; + + if (need_prologue && is_shared_heap()) { + SharedHeap* sh = (SharedHeap*)Universe::heap(); + sh->gc_prologue(false /* !full */); // get any necessary locks, etc. } + // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(KlassInfoTable::cit_size, create_random_seed()); if (!cit.allocation_failed()) { - // Iterate over objects in the heap - RecordInstanceClosure ric(&cit); - // If this operation encounters a bad object when using CMS, - // consider using safe_object_iterate() which avoids perm gen - // objects that may contain bad references. - Universe::heap()->object_iterate(&ric); - - // Report if certain classes are not counted because of - // running out of C-heap for the histogram. - size_t missed_count = ric.missed_count(); + size_t missed_count = iterate_over_heap(&cit); if (missed_count != 0) { st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT " total instances in data below", @@ -300,8 +325,8 @@ } st->flush(); - if (need_prologue && is_shared_heap) { - SharedHeap* sh = (SharedHeap*)heap; + if (need_prologue && is_shared_heap()) { + SharedHeap* sh = (SharedHeap*)Universe::heap(); sh->gc_epilogue(false /* !full */); // release all acquired locks, etc. } } --- old/src/share/vm/memory/heapInspection.hpp 2013-03-16 11:20:20.419378630 +0100 +++ new/src/share/vm/memory/heapInspection.hpp 2013-03-16 11:20:20.355378632 +0100 @@ -132,6 +132,15 @@ public: static void heap_inspection(outputStream* st, bool need_prologue); static void find_instances_at_safepoint(klassOop k, GrowableArray* result); + static void instance_inspection(KlassInfoClosure* closure); + static void instance_inspection(BoolObjectClosure* object_filter, + KlassInfoClosure* closure); + static HeapWord* create_random_seed(); + + private: + static bool is_shared_heap(); + static size_t iterate_over_heap(KlassInfoTable* cit); + static size_t iterate_over_heap(BoolObjectClosure* object_filter, KlassInfoTable* cit); }; #endif // SHARE_VM_MEMORY_HEAPINSPECTION_HPP --- old/src/share/vm/trace/trace.xml 2013-03-16 11:20:20.767378626 +0100 +++ new/src/share/vm/trace/trace.xml 2013-03-16 11:20:20.703378626 +0100 @@ -191,6 +191,13 @@ + + + + + + +