changeset 4532:47b5859d4634

8008790: Promotion failed tracing event for all GCs Summary: Implemented promotion failed event for ParNew and Serial GC Reviewed-by: brutisso, ehelin
author jwilhelm
date Tue, 19 Mar 2013 23:14:19 +0100
parents 0a5dbad3cd92
children 99d14be80708
files src/share/vm/gc_implementation/parNew/parNewGeneration.cpp src/share/vm/gc_implementation/parNew/parNewGeneration.hpp src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp src/share/vm/gc_implementation/shared/gcTrace.cpp src/share/vm/gc_implementation/shared/gcTrace.hpp src/share/vm/gc_implementation/shared/gcTraceSend.cpp src/share/vm/gc_implementation/shared/promotionFailedInfo.hpp src/share/vm/memory/defNewGeneration.cpp src/share/vm/memory/defNewGeneration.hpp src/share/vm/trace/trace.xml
diffstat 12 files changed, 124 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -33,6 +33,7 @@
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "memory/defNewGeneration.inline.hpp"
 #include "memory/genCollectedHeap.hpp"
@@ -79,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
@@ -283,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.promotion_failed() && PrintPromotionFailure) {
+    gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
+                        _thread_num, _promotion_failed_info.first_size());
   }
 }
 
@@ -309,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();
 
@@ -357,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();
     }
   }
 }
@@ -874,6 +880,8 @@
 }
 
 
+// A Generation that does parallel young-gen collection.
+
 bool ParNewGeneration::_avoid_promotion_undo = false;
 
 void ParNewGeneration::adjust_desired_tenuring_threshold() {
@@ -882,7 +890,30 @@
     age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
 }
 
-// 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.promotion_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,
@@ -914,7 +945,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()) {
@@ -1024,22 +1055,7 @@
 
     assert(to()->is_empty(), "to space should be empty now");
   } 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());
@@ -1195,8 +1211,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);
@@ -1311,8 +1326,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.
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp	Tue Mar 19 23:14:19 2013 +0100
@@ -25,7 +25,9 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP
 
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/defNewGeneration.hpp"
 #include "utilities/taskqueue.hpp"
 
@@ -105,7 +107,7 @@
 #endif // TASKQUEUE_STATS
 
   // Stats for promotion failure
-  size_t _promotion_failure_size;
+  PromotionFailedInfo _promotion_failed_info;
 
   // Timing numbers.
   double _start;
@@ -180,13 +182,16 @@
   void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz);
 
   // Promotion failure stats
-  size_t promotion_failure_size() { return promotion_failure_size(); }
-  void log_promotion_failure(size_t sz) {
-    if (_promotion_failure_size == 0) {
-      _promotion_failure_size = sz;
-    }
+  void register_promotion_failure(size_t sz) {
+    _promotion_failed_info.register_promotion_failed(sz);
   }
-  void print_and_clear_promotion_failure_size();
+  PromotionFailedInfo& promotion_failed_info() {
+    return _promotion_failed_info;
+  }
+  bool promotion_failed() {
+    return _promotion_failed_info.promotion_failed();
+  }
+  void print_promotion_failure_size();
 
 #if TASKQUEUE_STATS
   TaskQueueStats & taskqueue_stats() const { return _work_queue->stats; }
@@ -337,6 +342,8 @@
   // word being overwritten with a self-forwarding-pointer.
   void preserve_mark_if_necessary(oop obj, markOop m);
 
+  void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer);
+
  protected:
 
   bool _survivor_overflow;
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -27,8 +27,8 @@
 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
-#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/memRegion.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.psgc.inline.hpp"
@@ -87,24 +87,20 @@
   }
 }
 
-PromotionFailedInfo PSPromotionManager::post_scavenge() {
-  size_t promotion_failed_size = 0;
-  uint   promotion_failed_count = 0;
-  PromotionFailedInfo pfi;
+bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) {
+  bool promotion_failure_occurred = false;
 
   TASKQUEUE_STATS_ONLY(if (PrintGCDetails && ParallelGCVerbose) print_stats());
   for (uint i = 0; i < ParallelGCThreads + 1; i++) {
     PSPromotionManager* manager = manager_array(i);
     assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
     if (manager->_promotion_failed_info.promotion_failed()) {
-        promotion_failed_size += manager->_promotion_failed_info.promotion_failed_size();
-        promotion_failed_count += manager->_promotion_failed_info.promotion_failed_count();
+      gc_tracer.report_promotion_failed(manager->_promotion_failed_info);
+      promotion_failure_occurred = true;
     }
     manager->flush_labs();
   }
-
-  pfi.set_promotion_failed(promotion_failed_size, promotion_failed_count);
-  return pfi;
+  return promotion_failure_occurred;
 }
 
 #if TASKQUEUE_STATS
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Tue Mar 19 23:14:19 2013 +0100
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_HPP
 
 #include "gc_implementation/parallelScavenge/psPromotionLAB.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/taskqueue.hpp"
@@ -152,7 +153,7 @@
   static void initialize();
 
   static void pre_scavenge();
-  static PromotionFailedInfo post_scavenge();
+  static bool post_scavenge(YoungGCTracer& gc_tracer);
 
   static PSPromotionManager* gc_thread_promotion_manager(int index);
   static PSPromotionManager* vm_thread_promotion_manager();
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -332,7 +332,6 @@
   {
     ResourceMark rm;
     HandleMark hm;
-    PromotionFailedInfo promotion_failed_info;
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
@@ -481,12 +480,8 @@
     }
 
     // Finally, flush the promotion_manager's labs, and deallocate its stacks.
-    promotion_failed_info = PSPromotionManager::post_scavenge();
-
-    promotion_failure_occurred = promotion_failed_info.promotion_failed();
+    promotion_failure_occurred = PSPromotionManager::post_scavenge(_gc_tracer);
     if (promotion_failure_occurred) {
-      _gc_tracer.report_promotion_failed(promotion_failed_info.promotion_failed_size(),
-                                         promotion_failed_info.promotion_failed_count());
       clean_up_failed_promotion();
       if (PrintGC) {
         gclog_or_tty->print("--");
@@ -500,8 +495,6 @@
 
     if (!promotion_failure_occurred) {
       // Swap the survivor spaces.
-
-
       young_gen->eden_space()->clear(SpaceDecorator::Mangle);
       young_gen->from_space()->clear(SpaceDecorator::Mangle);
       young_gen->swap_spaces();
--- a/src/share/vm/gc_implementation/shared/gcTrace.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -26,6 +26,7 @@
 #include "gc_implementation/shared/gcHeapSummary.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/referenceProcessorStats.hpp"
 #include "utilities/globalDefinitions.hpp"
 
@@ -98,10 +99,10 @@
   send_young_gc_event();
 }
 
-void YoungGCTracer::report_promotion_failed(size_t size, uint count) {
+void YoungGCTracer::report_promotion_failed(const PromotionFailedInfo& pf_info) {
   assert_set_gc_id();
 
-  send_promotion_failed_event(size, count);
+  send_promotion_failed_event(pf_info);
 }
 
 
--- a/src/share/vm/gc_implementation/shared/gcTrace.hpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp	Tue Mar 19 23:14:19 2013 +0100
@@ -28,6 +28,7 @@
 #include "gc_interface/gcCause.hpp"
 #include "gc_interface/gcName.hpp"
 #include "gc_implementation/shared/gcWhen.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/allocation.hpp"
 #include "memory/referenceType.hpp"
 #ifndef SERIALGC
@@ -137,14 +138,14 @@
   YoungGCTracer(GCName name) : GCTracer(name) {}
 
  public:
-  virtual void report_promotion_failed(size_t size, uint count);
+  virtual void report_promotion_failed(const PromotionFailedInfo& pf_info);
 
  protected:
   virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
 
  private:
   void send_young_gc_event() const;
-  void send_promotion_failed_event(size_t size, uint count) const;
+  void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const;
 };
 
 class OldGCTracer : public GCTracer {
--- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -27,6 +27,7 @@
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcWhen.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "trace/tracing.hpp"
 #ifndef SERIALGC
 #include "gc_implementation/g1/g1YCTypes.hpp"
@@ -91,12 +92,15 @@
   }
 }
 
-void YoungGCTracer::send_promotion_failed_event(size_t size, uint count) const {
+void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_info) const {
   EventPromotionFailed e;
   if (e.should_commit()) {
     e.set_gcId(_shared_gc_info.id());
-    e.set_objectCount(count);
-    e.set_totalSize(size);
+    e.set_objectCount(pf_info.promotion_failed_count());
+    e.set_firstSize(pf_info.first_size());
+    e.set_smallestSize(pf_info.smallest_size());
+    e.set_totalSize(pf_info.total_size());
+    e.set_thread(pf_info.thread()->thread_id());
     e.commit();
   }
 }
--- a/src/share/vm/gc_implementation/shared/promotionFailedInfo.hpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/gc_implementation/shared/promotionFailedInfo.hpp	Tue Mar 19 23:14:19 2013 +0100
@@ -25,34 +25,46 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PROMOTIONFAILEDINFO_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_PROMOTIONFAILEDINFO_HPP
 
+#include "runtime/thread.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 class PromotionFailedInfo VALUE_OBJ_CLASS_SPEC {
-  uint   _promotion_failed_count;
-  size_t _promotion_failed_size;
+  size_t    _first_size;
+  size_t    _smallest_size;
+  size_t    _total_size;
+  uint      _count;
+  OSThread* _thread;
+
  public:
-  PromotionFailedInfo() : _promotion_failed_count(0), _promotion_failed_size(0) {}
+  PromotionFailedInfo() : _first_size(0), _smallest_size(0), _total_size(0), _count(0), _thread(NULL) {}
 
   void register_promotion_failed(size_t size) {
-    _promotion_failed_size += size;
-    _promotion_failed_count++;
-  }
-
-  void set_promotion_failed(size_t size, uint count) {
-    _promotion_failed_size = size;
-    _promotion_failed_count = count;
+    if (_first_size == 0) {
+      _first_size = size;
+      _smallest_size = size;
+      _thread = Thread::current()->osthread();
+    } else if (size < _smallest_size) {
+      _smallest_size = size;
+    }
+    _total_size += size;
+    _count++;
+    assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local.");
   }
 
   void reset() {
-    _promotion_failed_size = 0;
-    _promotion_failed_count = 0;
+    _first_size = 0;
+    _smallest_size = 0;
+    _total_size = 0;
+    _count = 0;
+    _thread = NULL;
   }
 
-  bool promotion_failed() const { return _promotion_failed_size > 0; }
-  size_t promotion_failed_size() const { return _promotion_failed_size; }
-  uint promotion_failed_count() const { return _promotion_failed_count; }
+  bool promotion_failed() const { return _count != 0; }
+  size_t first_size() const { return _first_size; }
+  size_t smallest_size() const { return _smallest_size; }
+  size_t total_size() const { return _total_size; }
+  uint promotion_failed_count() const { return _count; }
+  OSThread* thread() const { return _thread; }
 };
 
-
 #endif /* SHARE_VM_GC_IMPLEMENTATION_SHARED_PROMOTIONFAILEDINFO_HPP */
-
--- a/src/share/vm/memory/defNewGeneration.cpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/memory/defNewGeneration.cpp	Tue Mar 19 23:14:19 2013 +0100
@@ -546,7 +546,7 @@
   assert(_next_gen != NULL,
     "This must be the youngest gen, and not the only gen");
 
-  // If the next generation is too full to accomodate promotion
+  // If the next generation is too full to accommodate promotion
   // from this generation, pass on collection; let the next generation
   // do it.
   if (!collection_attempt_is_safe()) {
@@ -614,7 +614,7 @@
     rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
                                       NULL, _gc_timer);
   gc_tracer.report_gc_reference_stats(stats);
-  if (!promotion_failed()) {
+  if (!_promotion_failed) {
     // Swap the survivor spaces.
     eden()->clear(SpaceDecorator::Mangle);
     from()->clear(SpaceDecorator::Mangle);
@@ -663,6 +663,7 @@
 
     // Inform the next generation that a promotion failure occurred.
     _next_gen->promotion_failure_occurred();
+    gc_tracer.report_promotion_failed(_promotion_failed_info);
 
     // Reset the PromotionFailureALot counters.
     NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
@@ -672,7 +673,7 @@
   to()->set_concurrent_iteration_safe_limit(to()->top());
   SpecializationStats::print();
 
-  // We need to use a monotonically non-deccreasing time in ms
+  // We need to use a monotonically non-decreasing time in ms
   // or we will see time-warp warnings and os::javaTimeMillis()
   // does not guarantee monotonicity.
   jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
@@ -694,6 +695,7 @@
 
 void DefNewGeneration::init_assuming_no_promotion_failure() {
   _promotion_failed = false;
+  _promotion_failed_info.reset();
   from()->set_next_compaction_space(NULL);
 }
 
@@ -715,7 +717,7 @@
 }
 
 void DefNewGeneration::preserve_mark(oop obj, markOop m) {
-  assert(promotion_failed() && m->must_be_preserved_for_promotion_failure(obj),
+  assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj),
          "Oversaving!");
   _objs_with_preserved_marks.push(obj);
   _preserved_marks_of_objs.push(m);
@@ -733,6 +735,7 @@
                         old->size());
   }
   _promotion_failed = true;
+  _promotion_failed_info.register_promotion_failed(old->size());
   preserve_mark_if_necessary(old, old->mark());
   // forward to self
   old->forward_to(old);
--- a/src/share/vm/memory/defNewGeneration.hpp	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/memory/defNewGeneration.hpp	Tue Mar 19 23:14:19 2013 +0100
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/ageTable.hpp"
 #include "gc_implementation/shared/cSpaceCounters.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
+#include "gc_implementation/shared/promotionFailedInfo.hpp"
 #include "memory/generation.inline.hpp"
 #include "utilities/stack.hpp"
 
@@ -47,15 +48,17 @@
   int         _tenuring_threshold;   // Tenuring threshold for next collection.
   ageTable    _age_table;
   // Size of object to pretenure in words; command line provides bytes
-  size_t        _pretenure_size_threshold_words;
+  size_t      _pretenure_size_threshold_words;
 
   ageTable*   age_table() { return &_age_table; }
+
   // Initialize state to optimistically assume no promotion failure will
   // happen.
   void   init_assuming_no_promotion_failure();
   // True iff a promotion has failed in the current collection.
   bool   _promotion_failed;
   bool   promotion_failed() { return _promotion_failed; }
+  PromotionFailedInfo _promotion_failed_info;
 
   // Handling promotion failure.  A young generation collection
   // can fail if a live object cannot be copied out of its
--- a/src/share/vm/trace/trace.xml	Tue Mar 19 18:32:16 2013 +0100
+++ b/src/share/vm/trace/trace.xml	Tue Mar 19 23:14:19 2013 +0100
@@ -193,7 +193,10 @@
            description="Promotion of an object failed">
       <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/>
       <value type="BYTES64" field="objectCount" label="Object Count"/>
+      <value type="BYTES64" field="firstSize" label="First Failed Object Size"/>
+      <value type="BYTES64" field="smallestSize" label="Smallest Failed Object Size"/>
       <value type="BYTES64" field="totalSize" label="Total Object Size"/>
+      <value type="OSTHREAD" field="thread" label="Running thread"/>
     </event>
 
     <event id="GCPhasePause" path="vm/gc/phases/pause" label="GC Phase Pause">