hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
changeset 18025 b7bcf7497f93
parent 15215 048f775ae371
child 19286 48394008c803
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Fri Jun 07 09:33:01 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Mon Jun 10 11:30:51 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
 #include "gc_implementation/shared/adaptiveSizePolicy.hpp"
 #include "gc_implementation/shared/ageTable.hpp"
 #include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/gcHeapSummary.hpp"
+#include "gc_implementation/shared/gcTimer.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
+#include "gc_implementation/shared/gcTraceTime.hpp"
+#include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "memory/defNewGeneration.inline.hpp"
 #include "memory/genCollectedHeap.hpp"
@@ -75,7 +80,6 @@
                       work_queue_set_, &term_),
   _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
   _keep_alive_closure(&_scan_weak_ref_closure),
-  _promotion_failure_size(0),
   _strong_roots_time(0.0), _term_time(0.0)
 {
   #if TASKQUEUE_STATS
@@ -279,13 +283,10 @@
   }
 }
 
-void ParScanThreadState::print_and_clear_promotion_failure_size() {
-  if (_promotion_failure_size != 0) {
-    if (PrintPromotionFailure) {
-      gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
-        _thread_num, _promotion_failure_size);
-    }
-    _promotion_failure_size = 0;
+void ParScanThreadState::print_promotion_failure_size() {
+  if (_promotion_failed_info.has_failed() && PrintPromotionFailure) {
+    gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
+                        _thread_num, _promotion_failed_info.first_size());
   }
 }
 
@@ -305,6 +306,7 @@
 
   inline ParScanThreadState& thread_state(int i);
 
+  void trace_promotion_failed(YoungGCTracer& gc_tracer);
   void reset(int active_workers, bool promotion_failed);
   void flush();
 
@@ -353,13 +355,21 @@
   return ((ParScanThreadState*)_data)[i];
 }
 
+void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
+  for (int i = 0; i < length(); ++i) {
+    if (thread_state(i).promotion_failed()) {
+      gc_tracer.report_promotion_failed(thread_state(i).promotion_failed_info());
+      thread_state(i).promotion_failed_info().reset();
+    }
+  }
+}
 
 void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
 {
   _term.reset_for_reuse(active_threads);
   if (promotion_failed) {
     for (int i = 0; i < length(); ++i) {
-      thread_state(i).print_and_clear_promotion_failure_size();
+      thread_state(i).print_promotion_failure_size();
     }
   }
 }
@@ -583,14 +593,6 @@
   gch->set_n_termination(active_workers);
 }
 
-// The "i" passed to this method is the part of the work for
-// this thread.  It is not the worker ID.  The "i" is derived
-// from _started_workers which is incremented in internal_note_start()
-// called in GangWorker loop() and which is called under the
-// which is  called under the protection of the gang monitor and is
-// called after a task is started.  So "i" is based on
-// first-come-first-served.
-
 void ParNewGenTask::work(uint worker_id) {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   // Since this is being done in a separate thread, need new resource
@@ -876,16 +878,45 @@
 }
 
 
+// A Generation that does parallel young-gen collection.
+
 bool ParNewGeneration::_avoid_promotion_undo = false;
 
-// A Generation that does parallel young-gen collection.
+void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) {
+  assert(_promo_failure_scan_stack.is_empty(), "post condition");
+  _promo_failure_scan_stack.clear(true); // Clear cached segments.
+
+  remove_forwarding_pointers();
+  if (PrintGCDetails) {
+    gclog_or_tty->print(" (promotion failed)");
+  }
+  // All the spaces are in play for mark-sweep.
+  swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
+  from()->set_next_compaction_space(to());
+  gch->set_incremental_collection_failed();
+  // Inform the next generation that a promotion failure occurred.
+  _next_gen->promotion_failure_occurred();
+
+  // Trace promotion failure in the parallel GC threads
+  thread_state_set.trace_promotion_failed(gc_tracer);
+  // Single threaded code may have reported promotion failure to the global state
+  if (_promotion_failed_info.has_failed()) {
+    gc_tracer.report_promotion_failed(_promotion_failed_info);
+  }
+  // Reset the PromotionFailureALot counters.
+  NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
+}
 
 void ParNewGeneration::collect(bool   full,
                                bool   clear_all_soft_refs,
                                size_t size,
                                bool   is_tlab) {
   assert(full || size > 0, "otherwise we don't want to collect");
+
   GenCollectedHeap* gch = GenCollectedHeap::heap();
+
+  _gc_timer->register_gc_start(os::elapsed_counter());
+
   assert(gch->kind() == CollectedHeap::GenCollectedHeap,
     "not a CMS generational heap");
   AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
@@ -906,7 +937,7 @@
     set_avoid_promotion_undo(true);
   }
 
-  // If the next generation is too full to accomodate worst-case promotion
+  // If the next generation is too full to accommodate worst-case promotion
   // from this generation, pass on collection; let the next generation
   // do it.
   if (!collection_attempt_is_safe()) {
@@ -915,6 +946,10 @@
   }
   assert(to()->is_empty(), "Else not collection_attempt_is_safe");
 
+  ParNewTracer gc_tracer;
+  gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
+  gch->trace_heap_before_gc(&gc_tracer);
+
   init_assuming_no_promotion_failure();
 
   if (UseAdaptiveSizePolicy) {
@@ -922,7 +957,7 @@
     size_policy->minor_collection_begin();
   }
 
-  TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
@@ -975,17 +1010,21 @@
   rp->setup_policy(clear_all_soft_refs);
   // Can  the mt_degree be set later (at run_task() time would be best)?
   rp->set_active_mt_degree(active_workers);
+  ReferenceProcessorStats stats;
   if (rp->processing_is_mt()) {
     ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
-    rp->process_discovered_references(&is_alive, &keep_alive,
-                                      &evacuate_followers, &task_executor);
+    stats = rp->process_discovered_references(&is_alive, &keep_alive,
+                                              &evacuate_followers, &task_executor,
+                                              _gc_timer);
   } else {
     thread_state_set.flush();
     gch->set_par_threads(0);  // 0 ==> non-parallel.
     gch->save_marks();
-    rp->process_discovered_references(&is_alive, &keep_alive,
-                                      &evacuate_followers, NULL);
+    stats = rp->process_discovered_references(&is_alive, &keep_alive,
+                                              &evacuate_followers, NULL,
+                                              _gc_timer);
   }
+  gc_tracer.report_gc_reference_stats(stats);
   if (!promotion_failed()) {
     // Swap the survivor spaces.
     eden()->clear(SpaceDecorator::Mangle);
@@ -1010,22 +1049,7 @@
 
     adjust_desired_tenuring_threshold();
   } else {
-    assert(_promo_failure_scan_stack.is_empty(), "post condition");
-    _promo_failure_scan_stack.clear(true); // Clear cached segments.
-
-    remove_forwarding_pointers();
-    if (PrintGCDetails) {
-      gclog_or_tty->print(" (promotion failed)");
-    }
-    // All the spaces are in play for mark-sweep.
-    swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
-    from()->set_next_compaction_space(to());
-    gch->set_incremental_collection_failed();
-    // Inform the next generation that a promotion failure occurred.
-    _next_gen->promotion_failure_occurred();
-
-    // Reset the PromotionFailureALot counters.
-    NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
+    handle_promotion_failed(gch, thread_state_set, gc_tracer);
   }
   // set new iteration safe limit for the survivor spaces
   from()->set_concurrent_iteration_safe_limit(from()->top());
@@ -1065,6 +1089,13 @@
     rp->enqueue_discovered_references(NULL);
   }
   rp->verify_no_references_recorded();
+
+  gch->trace_heap_after_gc(&gc_tracer);
+  gc_tracer.report_tenuring_threshold(tenuring_threshold());
+
+  _gc_timer->register_gc_end(os::elapsed_counter());
+
+  gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
 }
 
 static int sum;
@@ -1174,8 +1205,7 @@
       new_obj = old;
 
       preserve_mark_if_necessary(old, m);
-      // Log the size of the maiden promotion failure
-      par_scan_state->log_promotion_failure(sz);
+      par_scan_state->register_promotion_failure(sz);
     }
 
     old->forward_to(new_obj);
@@ -1300,8 +1330,7 @@
       failed_to_promote = true;
 
       preserve_mark_if_necessary(old, m);
-      // Log the size of the maiden promotion failure
-      par_scan_state->log_promotion_failure(sz);
+      par_scan_state->register_promotion_failure(sz);
     }
   } else {
     // Is in to-space; do copying ourselves.
@@ -1599,8 +1628,7 @@
 }
 #undef BUSY
 
-void ParNewGeneration::ref_processor_init()
-{
+void ParNewGeneration::ref_processor_init() {
   if (_ref_processor == NULL) {
     // Allocate and initialize a reference processor
     _ref_processor =