Merge
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index 5825a57..938e94e 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -6332,10 +6332,10 @@
   )
 }
 
-void CMSCollector::do_CMS_operation(CMS_op_type op) {
+void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-  TraceTime t("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
+  TraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
   TraceCollectorStats tcs(counters());
 
   switch (op) {
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
index a842538..ecc60cc 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
@@ -717,7 +717,7 @@
     CMS_op_checkpointRootsFinal
   };
 
-  void do_CMS_operation(CMS_op_type op);
+  void do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause);
   bool stop_world_and_do(CMS_op_type op);
 
   OopTaskQueueSet* task_queues() { return _task_queues; }
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
index c3b9d54..3b8d5aa 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
@@ -146,7 +146,7 @@
   VM_CMS_Operation::verify_before_gc();
 
   IsGCActiveMark x; // stop-world GC active
-  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial);
+  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());
 
   VM_CMS_Operation::verify_after_gc();
 #ifndef USDT2
@@ -178,7 +178,7 @@
   VM_CMS_Operation::verify_before_gc();
 
   IsGCActiveMark x; // stop-world GC active
-  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);
+  _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause());
 
   VM_CMS_Operation::verify_after_gc();
 #ifndef USDT2
diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index 270e52e..9d1f9d9 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -1252,10 +1252,7 @@
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
-    char verbose_str[128];
-    sprintf(verbose_str, "Full GC (%s)", GCCause::to_string(gc_cause()));
-    TraceTime t(verbose_str, G1Log::fine(), true, gclog_or_tty);
-
+    TraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, gclog_or_tty);
     TraceCollectorStats tcs(g1mm()->full_collection_counters());
     TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
 
@@ -3600,12 +3597,10 @@
     gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
-    char verbose_str[128];
-    sprintf(verbose_str, "GC pause (%s) (%s)%s",
-      GCCause::to_string(gc_cause()),
-      g1_policy()->gcs_are_young() ? "young" : "mixed",
-      g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
-    TraceTime t(verbose_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
+    GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
+      .append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)")
+      .append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
+    TraceTime t(gc_cause_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
     TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
@@ -5502,7 +5497,7 @@
   if (evacuation_failed()) {
     remove_self_forwarding_pointers();
     if (G1Log::finer()) {
-      gclog_or_tty->print(" (to-space overflow)");
+      gclog_or_tty->print(" (to-space exhausted)");
     } else if (G1Log::fine()) {
       gclog_or_tty->print("--");
     }
diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index a406061..2050f6f 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -886,9 +886,8 @@
                                                       size_t start_used) {
   if (G1Log::finer()) {
     gclog_or_tty->stamp(PrintGCTimeStamps);
-    gclog_or_tty->print("[GC pause (%s) (%s)",
-      GCCause::to_string(_g1->gc_cause()),
-      gcs_are_young() ? "young" : "mixed");
+    gclog_or_tty->print("[%s", (const char*)GCCauseString("GC pause", _g1->gc_cause())
+      .append(gcs_are_young() ? " (young)" : " (mixed)"));
   }
 
   // We only need to do this here as the policy will only be applied
@@ -1010,7 +1009,8 @@
 
 void G1CollectorPolicy::print_par_stats(int level,
                                         const char* str,
-                                        double* data) {
+                                        double* data,
+                                        bool showDecimals) {
   double min = data[0], max = data[0];
   double total = 0.0;
   LineBuffer buf(level);
@@ -1023,7 +1023,11 @@
       max = val;
     total += val;
     if (G1Log::finest()) {
-      buf.append("  %.1lf", val);
+      if (showDecimals) {
+        buf.append("  %.1lf", val);
+      } else {
+        buf.append("  %d", (int)val);
+      }
     }
   }
 
@@ -1031,36 +1035,26 @@
     buf.append_and_print_cr("");
   }
   double avg = total / (double) no_of_gc_threads();
-  buf.append_and_print_cr(" Avg: %.1lf Min: %.1lf Max: %.1lf Diff: %.1lf]",
-    avg, min, max, max - min);
-}
-
-void G1CollectorPolicy::print_par_sizes(int level,
-                                        const char* str,
-                                        double* data) {
-  double min = data[0], max = data[0];
-  double total = 0.0;
-  LineBuffer buf(level);
-  buf.append("[%s :", str);
-  for (uint i = 0; i < no_of_gc_threads(); ++i) {
-    double val = data[i];
-    if (val < min)
-      min = val;
-    if (val > max)
-      max = val;
-    total += val;
-    buf.append(" %d", (int) val);
+  if (showDecimals) {
+    buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]",
+      min, avg, max, max - min, total);
+  } else {
+    buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]",
+      (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total);
   }
-  buf.append_and_print_cr("");
-  double avg = total / (double) no_of_gc_threads();
-  buf.append_and_print_cr(" Sum: %d, Avg: %d, Min: %d, Max: %d, Diff: %d]",
-    (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
 }
 
 void G1CollectorPolicy::print_stats(int level,
                                     const char* str,
                                     double value) {
-  LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value);
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
+}
+
+void G1CollectorPolicy::print_stats(int level,
+                                    const char* str,
+                                    double value,
+                                    int workers) {
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
 }
 
 void G1CollectorPolicy::print_stats(int level,
@@ -1373,7 +1367,7 @@
       print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
     }
     if (parallel) {
-      print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
+      print_stats(1, "Parallel Time", _cur_collection_par_time_ms, no_of_gc_threads);
       print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
       print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
       if (print_marking_info) {
@@ -1381,13 +1375,15 @@
       }
       print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
       if (G1Log::finest()) {
-        print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
+        print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers,
+          false /* showDecimals */);
       }
       print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
       print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
       print_par_stats(2, "Termination", _par_last_termination_times_ms);
       if (G1Log::finest()) {
-        print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
+        print_par_stats(3, "Termination Attempts", _par_last_termination_attempts,
+          false /* showDecimals */);
       }
 
       for (int i = 0; i < _parallel_gc_threads; i++) {
@@ -1601,9 +1597,9 @@
   _collectionSetChooser->verify();
 }
 
-#define EXT_SIZE_FORMAT "%d%s"
+#define EXT_SIZE_FORMAT "%.1f%s"
 #define EXT_SIZE_PARAMS(bytes)                                  \
-  byte_size_in_proper_unit((bytes)),                            \
+  byte_size_in_proper_unit((double)(bytes)),                    \
   proper_unit_for_byte_size((bytes))
 
 void G1CollectorPolicy::print_heap_transition() {
diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index 7cdf79d..8806981 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -552,10 +552,10 @@
 
 private:
   void print_stats(int level, const char* str, double value);
+  void print_stats(int level, const char* str, double value, int workers);
   void print_stats(int level, const char* str, int value);
 
-  void print_par_stats(int level, const char* str, double* data);
-  void print_par_sizes(int level, const char* str, double* data);
+  void print_par_stats(int level, const char* str, double* data, bool showDecimals = true);
 
   void check_other_times(int level,
                          NumberSeq* other_times_ms,
diff --git a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
index 1a330ba..d880f55 100644
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
@@ -42,6 +42,7 @@
 
 void VM_G1CollectForAllocation::doit() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  GCCauseSetter x(g1h, _gc_cause);
   _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
   assert(_result == NULL || _pause_succeeded,
          "if we get back a result, the pause should have succeeded");
diff --git a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
index 4f64dff..96ae468 100644
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
@@ -916,7 +916,7 @@
     size_policy->minor_collection_begin();
   }
 
-  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
index ad599ae..0ef9752 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
@@ -160,16 +160,10 @@
 
   {
     HandleMark hm;
-    const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
-    // This is useful for debugging but don't change the output the
-    // the customer sees.
-    const char* gc_cause_str = "Full GC";
-    if (is_system_gc && PrintGCDetails) {
-      gc_cause_str = "Full GC (System)";
-    }
+
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
index 354b3d0..8e7c74e 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -2047,17 +2047,9 @@
     gc_task_manager()->task_idle_workers();
     heap->set_par_threads(gc_task_manager()->active_workers());
 
-    const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
-
-    // This is useful for debugging but don't change the output the
-    // the customer sees.
-    const char* gc_cause_str = "Full GC";
-    if (is_system_gc && PrintGCDetails) {
-      gc_cause_str = "Full GC (System)";
-    }
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
@@ -2090,7 +2082,8 @@
     }
 #endif  // #ifndef PRODUCT
 
-    bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc;
+    bool max_on_system_gc = UseMaximumCompactionOnSystemGC
+      && gc_cause == GCCause::_java_lang_system_gc;
     summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
 
     COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
index 984b1a4..65ece05 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
@@ -325,7 +325,7 @@
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t1("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
+    TraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(false /* not full GC */,gc_cause);
 
diff --git a/src/share/vm/gc_implementation/shared/gcUtil.cpp b/src/share/vm/gc_implementation/shared/gcUtil.cpp
index 5325fee..3b9fd7a 100644
--- a/src/share/vm/gc_implementation/shared/gcUtil.cpp
+++ b/src/share/vm/gc_implementation/shared/gcUtil.cpp
@@ -31,9 +31,15 @@
                                                         float average) {
   // We smooth the samples by not using weight() directly until we've
   // had enough data to make it meaningful. We'd like the first weight
-  // used to be 1, the second to be 1/2, etc until we have 100/weight
-  // samples.
-  unsigned count_weight = 100/count();
+  // used to be 1, the second to be 1/2, etc until we have
+  // OLD_THRESHOLD/weight samples.
+  unsigned count_weight = 0;
+
+  // Avoid division by zero if the counter wraps (7158457)
+  if (!is_old()) {
+    count_weight = OLD_THRESHOLD/count();
+  }
+
   unsigned adaptive_weight = (MAX2(weight(), count_weight));
 
   float new_avg = exp_avg(average, new_sample, adaptive_weight);
@@ -43,8 +49,6 @@
 
 void AdaptiveWeightedAverage::sample(float new_sample) {
   increment_count();
-  assert(count() != 0,
-         "Wraparound -- history would be incorrectly discarded");
 
   // Compute the new weighted average
   float new_avg = compute_adaptive_average(new_sample, average());
diff --git a/src/share/vm/gc_implementation/shared/gcUtil.hpp b/src/share/vm/gc_implementation/shared/gcUtil.hpp
index 8dd3258..86daba6 100644
--- a/src/share/vm/gc_implementation/shared/gcUtil.hpp
+++ b/src/share/vm/gc_implementation/shared/gcUtil.hpp
@@ -50,11 +50,20 @@
   unsigned         _weight;         // The weight used to smooth the averages
                                     //   A higher weight favors the most
                                     //   recent data.
+  bool             _is_old;         // Has enough historical data
+
+  const static unsigned OLD_THRESHOLD = 100;
 
  protected:
   float            _last_sample;    // The last value sampled.
 
-  void  increment_count()       { _sample_count++;       }
+  void  increment_count() {
+    _sample_count++;
+    if (!_is_old && _sample_count > OLD_THRESHOLD) {
+      _is_old = true;
+    }
+  }
+
   void  set_average(float avg)  { _average = avg;        }
 
   // Helper function, computes an adaptive weighted average
@@ -64,13 +73,15 @@
  public:
   // Input weight must be between 0 and 100
   AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) :
-    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0) {
+    _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0),
+    _is_old(false) {
   }
 
   void clear() {
     _average = 0;
     _sample_count = 0;
     _last_sample = 0;
+    _is_old = false;
   }
 
   // Useful for modifying static structures after startup.
@@ -84,7 +95,8 @@
   float    average() const       { return _average;       }
   unsigned weight()  const       { return _weight;        }
   unsigned count()   const       { return _sample_count;  }
-  float    last_sample() const   { return _last_sample; }
+  float    last_sample() const   { return _last_sample;   }
+  bool     is_old()  const       { return _is_old;        }
 
   // Update data with a new sample.
   void sample(float new_sample);
diff --git a/src/share/vm/gc_interface/gcCause.hpp b/src/share/vm/gc_interface/gcCause.hpp
index ae14115..8866d76 100644
--- a/src/share/vm/gc_interface/gcCause.hpp
+++ b/src/share/vm/gc_interface/gcCause.hpp
@@ -88,4 +88,36 @@
   static const char* to_string(GCCause::Cause cause);
 };
 
+// Helper class for doing logging that includes the GC Cause
+// as a string.
+class GCCauseString : StackObj {
+ private:
+   static const int _length = 128;
+   char _buffer[_length];
+   int _position;
+
+ public:
+   GCCauseString(const char* prefix, GCCause::Cause cause) {
+     if (PrintGCCause) {
+      _position = jio_snprintf(_buffer, _length, "%s (%s)", prefix, GCCause::to_string(cause));
+     } else {
+      _position = jio_snprintf(_buffer, _length, "%s", prefix);
+     }
+     assert(_position >= 0 && _position <= _length,
+       err_msg("Need to increase the buffer size in GCCauseString? %d", _position));
+   }
+
+   GCCauseString& append(const char* str) {
+     int res = jio_snprintf(_buffer + _position, _length - _position, "%s", str);
+     _position += res;
+     assert(res >= 0 && _position <= _length,
+       err_msg("Need to increase the buffer size in GCCauseString? %d", res));
+     return *this;
+   }
+
+   operator const char*() {
+     return _buffer;
+   }
+};
+
 #endif // SHARE_VM_GC_INTERFACE_GCCAUSE_HPP
diff --git a/src/share/vm/memory/defNewGeneration.cpp b/src/share/vm/memory/defNewGeneration.cpp
index 315a382..452f630 100644
--- a/src/share/vm/memory/defNewGeneration.cpp
+++ b/src/share/vm/memory/defNewGeneration.cpp
@@ -548,7 +548,7 @@
 
   init_assuming_no_promotion_failure();
 
-  TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp
index 10c3274..40f5afd 100644
--- a/src/share/vm/memory/genCollectedHeap.cpp
+++ b/src/share/vm/memory/genCollectedHeap.cpp
@@ -480,26 +480,15 @@
   const size_t perm_prev_used = perm_gen()->used();
 
   print_heap_before_gc();
-  if (Verbose) {
-    gclog_or_tty->print_cr("GC Cause: %s", GCCause::to_string(gc_cause()));
-  }
 
   {
     FlagSetting fl(_is_gc_active, true);
 
     bool complete = full && (max_level == (n_gens()-1));
-    const char* gc_cause_str = "GC ";
-    if (complete) {
-      GCCause::Cause cause = gc_cause();
-      if (cause == GCCause::_java_lang_system_gc) {
-        gc_cause_str = "Full GC (System) ";
-      } else {
-        gc_cause_str = "Full GC ";
-      }
-    }
+    const char* gc_cause_prefix = complete ? "Full GC" : "GC";
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t(gc_cause_str, PrintGCDetails, false, gclog_or_tty);
+    TraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, gclog_or_tty);
 
     gc_prologue(complete);
     increment_total_collections(complete);
diff --git a/src/share/vm/memory/genMarkSweep.cpp b/src/share/vm/memory/genMarkSweep.cpp
index d5cf4dc..4d13fbb 100644
--- a/src/share/vm/memory/genMarkSweep.cpp
+++ b/src/share/vm/memory/genMarkSweep.cpp
@@ -76,7 +76,7 @@
   _ref_processor = rp;
   rp->setup_policy(clear_all_softrefs);
 
-  TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
+  TraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
 
   // When collecting the permanent generation methodOops may be moving,
   // so we either have to flush all bcp data or convert it into bci.
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
index 5b257b3..d319fdd 100644
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
@@ -3092,6 +3092,14 @@
     PrintGC = true;
   }
 
+  if (!JDK_Version::is_gte_jdk18x_version()) {
+    // To avoid changing the log format for 7 updates this flag is only
+    // true by default in JDK8 and above.
+    if (FLAG_IS_DEFAULT(PrintGCCause)) {
+      FLAG_SET_DEFAULT(PrintGCCause, false);
+    }
+  }
+
   // Set object alignment values.
   set_object_alignment();
 
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
index 7ad4f9a..d030b4f 100644
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
@@ -3902,7 +3902,10 @@
           " of this flag is true for JDK 6 and earlier")                    \
                                                                             \
   diagnostic(bool, WhiteBoxAPI, false,                                      \
-          "Enable internal testing APIs")
+          "Enable internal testing APIs")                                   \
+                                                                            \
+  product(bool, PrintGCCause, true,                                         \
+          "Include GC cause in GC logging")
 
 /*
  *  Macros for factoring of globals
diff --git a/src/share/vm/runtime/java.hpp b/src/share/vm/runtime/java.hpp
index 307fcc2..102fd6b 100644
--- a/src/share/vm/runtime/java.hpp
+++ b/src/share/vm/runtime/java.hpp
@@ -206,6 +206,10 @@
     return current().compare_major(7) == 0;
   }
 
+  static bool is_jdk18x_version() {
+    return current().compare_major(8) == 0;
+  }
+
   static bool is_gte_jdk13x_version() {
     return current().compare_major(3) >= 0;
   }
@@ -225,6 +229,10 @@
   static bool is_gte_jdk17x_version() {
     return current().compare_major(7) >= 0;
   }
+
+  static bool is_gte_jdk18x_version() {
+    return current().compare_major(8) >= 0;
+  }
 };
 
 #endif // SHARE_VM_RUNTIME_JAVA_HPP
diff --git a/src/share/vm/utilities/globalDefinitions.hpp b/src/share/vm/utilities/globalDefinitions.hpp
index 89201f6..82a9333 100644
--- a/src/share/vm/utilities/globalDefinitions.hpp
+++ b/src/share/vm/utilities/globalDefinitions.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -179,6 +179,11 @@
 const jint  NANOSECS_PER_MILLISEC = 1000000;
 
 inline const char* proper_unit_for_byte_size(size_t s) {
+#ifdef _LP64
+  if (s >= 10*G) {
+    return "G";
+  }
+#endif
   if (s >= 10*M) {
     return "M";
   } else if (s >= 10*K) {
@@ -188,17 +193,22 @@
   }
 }
 
-inline size_t byte_size_in_proper_unit(size_t s) {
+template <class T>
+inline T byte_size_in_proper_unit(T s) {
+#ifdef _LP64
+  if (s >= 10*G) {
+    return (T)(s/G);
+  }
+#endif
   if (s >= 10*M) {
-    return s/M;
+    return (T)(s/M);
   } else if (s >= 10*K) {
-    return s/K;
+    return (T)(s/K);
   } else {
     return s;
   }
 }
 
-
 //----------------------------------------------------------------------------------------------------
 // VM type definitions