changeset 17772:7d175751ef7f

Merge
author ehelin
date Mon, 24 Mar 2014 15:34:10 -0700
parents a007d73f3fdc (current diff) 9fdaa79b0c27 (diff)
children be3bc91182f5 9ab9f254cfe2
files
diffstat 15 files changed, 557 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -2496,7 +2496,8 @@
 }
 
 void CMSCollector::report_heap_summary(GCWhen::Type when) {
-  _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_metaspace_summary);
+  _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary);
+  _gc_tracer_cm->report_metaspace_summary(when, _last_metaspace_summary);
 }
 
 void CMSCollector::collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause) {
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -669,8 +669,10 @@
 
 void ParallelScavengeHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) {
   const PSHeapSummary& heap_summary = create_ps_heap_summary();
+  gc_tracer->report_gc_heap_summary(when, heap_summary);
+
   const MetaspaceSummary& metaspace_summary = create_metaspace_summary();
-  gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary);
+  gc_tracer->report_metaspace_summary(when, metaspace_summary);
 }
 
 ParallelScavengeHeap* ParallelScavengeHeap::heap() {
--- a/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP
 
 #include "memory/allocation.hpp"
+#include "memory/metaspaceChunkFreeListSummary.hpp"
 
 class VirtualSpaceSummary : public StackObj {
   HeapWord* _start;
@@ -125,18 +126,49 @@
 };
 
 class MetaspaceSummary : public StackObj {
+  size_t _capacity_until_GC;
   MetaspaceSizes _meta_space;
   MetaspaceSizes _data_space;
   MetaspaceSizes _class_space;
+  MetaspaceChunkFreeListSummary _metaspace_chunk_free_list_summary;
+  MetaspaceChunkFreeListSummary _class_chunk_free_list_summary;
 
  public:
-  MetaspaceSummary() : _meta_space(), _data_space(), _class_space() {}
-  MetaspaceSummary(const MetaspaceSizes& meta_space, const MetaspaceSizes& data_space, const MetaspaceSizes& class_space) :
-       _meta_space(meta_space), _data_space(data_space), _class_space(class_space) { }
+  MetaspaceSummary() :
+    _capacity_until_GC(0),
+    _meta_space(),
+    _data_space(),
+    _class_space(),
+    _metaspace_chunk_free_list_summary(),
+    _class_chunk_free_list_summary()
+  {}
+  MetaspaceSummary(size_t capacity_until_GC,
+                   const MetaspaceSizes& meta_space,
+                   const MetaspaceSizes& data_space,
+                   const MetaspaceSizes& class_space,
+                   const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary,
+                   const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary) :
+    _capacity_until_GC(capacity_until_GC),
+    _meta_space(meta_space),
+    _data_space(data_space),
+    _class_space(class_space),
+    _metaspace_chunk_free_list_summary(metaspace_chunk_free_list_summary),
+    _class_chunk_free_list_summary(class_chunk_free_list_summary)
+  {}
 
+  size_t capacity_until_GC() const { return _capacity_until_GC; }
   const MetaspaceSizes& meta_space() const { return _meta_space; }
   const MetaspaceSizes& data_space() const { return _data_space; }
   const MetaspaceSizes& class_space() const { return _class_space; }
+
+  const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary() const {
+    return _metaspace_chunk_free_list_summary;
+  }
+
+  const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary() const {
+    return _class_chunk_free_list_summary;
+  }
+
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP
--- a/src/share/vm/gc_implementation/shared/gcTrace.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -139,11 +139,21 @@
 }
 #endif // INCLUDE_SERVICES
 
-void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const {
+void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const {
   assert_set_gc_id();
 
   send_gc_heap_summary_event(when, heap_summary);
-  send_meta_space_summary_event(when, meta_space_summary);
+}
+
+void GCTracer::report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& summary) const {
+  assert_set_gc_id();
+
+  send_meta_space_summary_event(when, summary);
+
+  send_metaspace_chunk_free_list_summary(when, Metaspace::NonClassType, summary.metaspace_chunk_free_list_summary());
+  if (UseCompressedClassPointers) {
+    send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary());
+  }
 }
 
 void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
--- a/src/share/vm/gc_implementation/shared/gcTrace.hpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -30,6 +30,7 @@
 #include "gc_implementation/shared/gcWhen.hpp"
 #include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "memory/allocation.hpp"
+#include "memory/metaspace.hpp"
 #include "memory/referenceType.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/g1YCTypes.hpp"
@@ -41,6 +42,7 @@
 
 class EvacuationInfo;
 class GCHeapSummary;
+class MetaspaceChunkFreeListSummary;
 class MetaspaceSummary;
 class PSHeapSummary;
 class ReferenceProcessorStats;
@@ -124,7 +126,8 @@
  public:
   void report_gc_start(GCCause::Cause cause, const Ticks& timestamp);
   void report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions);
-  void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const;
+  void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const;
+  void report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& metaspace_summary) const;
   void report_gc_reference_stats(const ReferenceProcessorStats& rp) const;
   void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN;
   bool has_reported_gc_start() const;
@@ -138,6 +141,7 @@
   void send_garbage_collection_event() const;
   void send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const;
   void send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const;
+  void send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype, const MetaspaceChunkFreeListSummary& summary) const;
   void send_reference_stats_event(ReferenceType type, size_t count) const;
   void send_phase_events(TimePartitions* time_partitions) const;
 };
--- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -64,6 +64,30 @@
   }
 }
 
+void GCTracer::send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype,
+                                                      const MetaspaceChunkFreeListSummary& summary) const {
+  EventMetaspaceChunkFreeListSummary e;
+  if (e.should_commit()) {
+    e.set_gcId(_shared_gc_info.id());
+    e.set_when(when);
+    e.set_metadataType(mdtype);
+
+    e.set_specializedChunks(summary.num_specialized_chunks());
+    e.set_specializedChunksTotalSize(summary.specialized_chunks_size_in_bytes());
+
+    e.set_smallChunks(summary.num_small_chunks());
+    e.set_smallChunksTotalSize(summary.small_chunks_size_in_bytes());
+
+    e.set_mediumChunks(summary.num_medium_chunks());
+    e.set_mediumChunksTotalSize(summary.medium_chunks_size_in_bytes());
+
+    e.set_humongousChunks(summary.num_humongous_chunks());
+    e.set_humongousChunksTotalSize(summary.humongous_chunks_size_in_bytes());
+
+    e.commit();
+  }
+}
+
 void ParallelOldTracer::send_parallel_old_event() const {
   EventGCParallelOld e(UNTIMED);
   if (e.should_commit()) {
@@ -246,6 +270,7 @@
   if (e.should_commit()) {
     e.set_gcId(_shared_gc_info.id());
     e.set_when((u1) when);
+    e.set_gcThreshold(meta_space_summary.capacity_until_GC());
     e.set_metaspace(to_trace_struct(meta_space_summary.meta_space()));
     e.set_dataSpace(to_trace_struct(meta_space_summary.data_space()));
     e.set_classSpace(to_trace_struct(meta_space_summary.class_space()));
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -97,7 +97,13 @@
       MetaspaceAux::allocated_used_bytes(Metaspace::ClassType),
       MetaspaceAux::reserved_bytes(Metaspace::ClassType));
 
-  return MetaspaceSummary(meta_space, data_space, class_space);
+  const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary =
+    MetaspaceAux::chunk_free_list_summary(Metaspace::NonClassType);
+  const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary =
+    MetaspaceAux::chunk_free_list_summary(Metaspace::ClassType);
+
+  return MetaspaceSummary(MetaspaceGC::capacity_until_GC(), meta_space, data_space, class_space,
+                          ms_chunk_free_list_summary, class_chunk_free_list_summary);
 }
 
 void CollectedHeap::print_heap_before_gc() {
@@ -128,8 +134,10 @@
 
 void CollectedHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) {
   const GCHeapSummary& heap_summary = create_heap_summary();
+  gc_tracer->report_gc_heap_summary(when, heap_summary);
+
   const MetaspaceSummary& metaspace_summary = create_metaspace_summary();
-  gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary);
+  gc_tracer->report_metaspace_summary(when, metaspace_summary);
 }
 
 void CollectedHeap::trace_heap_before_gc(GCTracer* gc_tracer) {
--- a/src/share/vm/memory/metaspace.cpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/memory/metaspace.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -32,7 +32,9 @@
 #include "memory/gcLocker.hpp"
 #include "memory/metachunk.hpp"
 #include "memory/metaspace.hpp"
+#include "memory/metaspaceGCThresholdUpdater.hpp"
 #include "memory/metaspaceShared.hpp"
+#include "memory/metaspaceTracer.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "runtime/atomic.inline.hpp"
@@ -57,6 +59,7 @@
 MetaWord* last_allocated = 0;
 
 size_t Metaspace::_compressed_class_space_size;
+const MetaspaceTracer* Metaspace::_tracer = NULL;
 
 // Used in declarations in SpaceManager and ChunkManager
 enum ChunkIndex {
@@ -182,6 +185,48 @@
   // Remove from a list by size.  Selects list based on size of chunk.
   Metachunk* free_chunks_get(size_t chunk_word_size);
 
+#define index_bounds_check(index)                                         \
+  assert(index == SpecializedIndex ||                                     \
+         index == SmallIndex ||                                           \
+         index == MediumIndex ||                                          \
+         index == HumongousIndex, err_msg("Bad index: %d", (int) index))
+
+  size_t num_free_chunks(ChunkIndex index) const {
+    index_bounds_check(index);
+
+    if (index == HumongousIndex) {
+      return _humongous_dictionary.total_free_blocks();
+    }
+
+    ssize_t count = _free_chunks[index].count();
+    return count == -1 ? 0 : (size_t) count;
+  }
+
+  size_t size_free_chunks_in_bytes(ChunkIndex index) const {
+    index_bounds_check(index);
+
+    size_t word_size = 0;
+    if (index == HumongousIndex) {
+      word_size = _humongous_dictionary.total_size();
+    } else {
+      const size_t size_per_chunk_in_words = _free_chunks[index].size();
+      word_size = size_per_chunk_in_words * num_free_chunks(index);
+    }
+
+    return word_size * BytesPerWord;
+  }
+
+  MetaspaceChunkFreeListSummary chunk_free_list_summary() const {
+    return MetaspaceChunkFreeListSummary(num_free_chunks(SpecializedIndex),
+                                         num_free_chunks(SmallIndex),
+                                         num_free_chunks(MediumIndex),
+                                         num_free_chunks(HumongousIndex),
+                                         size_free_chunks_in_bytes(SpecializedIndex),
+                                         size_free_chunks_in_bytes(SmallIndex),
+                                         size_free_chunks_in_bytes(MediumIndex),
+                                         size_free_chunks_in_bytes(HumongousIndex));
+  }
+
   // Debug support
   void verify();
   void slow_verify() {
@@ -1436,19 +1481,21 @@
     expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment());
     // Don't expand unless it's significant
     if (expand_bytes >= MinMetaspaceExpansion) {
-      MetaspaceGC::inc_capacity_until_GC(expand_bytes);
-    }
-    if (PrintGCDetails && Verbose) {
-      size_t new_capacity_until_GC = capacity_until_GC;
-      gclog_or_tty->print_cr("    expanding:"
-                    "  minimum_desired_capacity: %6.1fKB"
-                    "  expand_bytes: %6.1fKB"
-                    "  MinMetaspaceExpansion: %6.1fKB"
-                    "  new metaspace HWM:  %6.1fKB",
-                    minimum_desired_capacity / (double) K,
-                    expand_bytes / (double) K,
-                    MinMetaspaceExpansion / (double) K,
-                    new_capacity_until_GC / (double) K);
+      size_t new_capacity_until_GC = MetaspaceGC::inc_capacity_until_GC(expand_bytes);
+      Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
+                                               new_capacity_until_GC,
+                                               MetaspaceGCThresholdUpdater::ComputeNewSize);
+      if (PrintGCDetails && Verbose) {
+        gclog_or_tty->print_cr("    expanding:"
+                      "  minimum_desired_capacity: %6.1fKB"
+                      "  expand_bytes: %6.1fKB"
+                      "  MinMetaspaceExpansion: %6.1fKB"
+                      "  new metaspace HWM:  %6.1fKB",
+                      minimum_desired_capacity / (double) K,
+                      expand_bytes / (double) K,
+                      MinMetaspaceExpansion / (double) K,
+                      new_capacity_until_GC / (double) K);
+      }
     }
     return;
   }
@@ -1527,7 +1574,10 @@
   // Don't shrink unless it's significant
   if (shrink_bytes >= MinMetaspaceExpansion &&
       ((capacity_until_GC - shrink_bytes) >= MetaspaceSize)) {
-    MetaspaceGC::dec_capacity_until_GC(shrink_bytes);
+    size_t new_capacity_until_GC = MetaspaceGC::dec_capacity_until_GC(shrink_bytes);
+    Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
+                                             new_capacity_until_GC,
+                                             MetaspaceGCThresholdUpdater::ComputeNewSize);
   }
 }
 
@@ -2628,6 +2678,19 @@
   return free_chunks_total_words() * BytesPerWord;
 }
 
+bool MetaspaceAux::has_chunk_free_list(Metaspace::MetadataType mdtype) {
+  return Metaspace::get_chunk_manager(mdtype) != NULL;
+}
+
+MetaspaceChunkFreeListSummary MetaspaceAux::chunk_free_list_summary(Metaspace::MetadataType mdtype) {
+  if (!has_chunk_free_list(mdtype)) {
+    return MetaspaceChunkFreeListSummary();
+  }
+
+  const ChunkManager* cm = Metaspace::get_chunk_manager(mdtype);
+  return cm->chunk_free_list_summary();
+}
+
 void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) {
   gclog_or_tty->print(", [Metaspace:");
   if (PrintGCDetails && Verbose) {
@@ -3131,6 +3194,7 @@
   }
 
   MetaspaceGC::initialize();
+  _tracer = new MetaspaceTracer();
 }
 
 Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype,
@@ -3219,8 +3283,12 @@
   assert(delta_bytes > 0, "Must be");
 
   size_t after_inc = MetaspaceGC::inc_capacity_until_GC(delta_bytes);
+
+  // capacity_until_GC might be updated concurrently, must calculate previous value.
   size_t before_inc = after_inc - delta_bytes;
 
+  tracer()->report_gc_threshold(before_inc, after_inc,
+                                MetaspaceGCThresholdUpdater::ExpandAndAllocate);
   if (PrintGCDetails && Verbose) {
     gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
         " to " SIZE_FORMAT, before_inc, after_inc);
@@ -3344,6 +3412,8 @@
   MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
 
   if (result == NULL) {
+    tracer()->report_metaspace_allocation_failure(loader_data, word_size, type, mdtype);
+
     // Allocation failed.
     if (is_init_completed()) {
       // Only start a GC if the bootstrapping has completed.
@@ -3355,7 +3425,7 @@
   }
 
   if (result == NULL) {
-    report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
+    report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
   }
 
   // Zero initialize.
@@ -3369,7 +3439,9 @@
   return class_vsm()->calc_chunk_size(word_size);
 }
 
-void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) {
+void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetaspaceObj::Type type, MetadataType mdtype, TRAPS) {
+  tracer()->report_metadata_oom(loader_data, word_size, type, mdtype);
+
   // If result is still null, we are out of memory.
   if (Verbose && TraceMetadataChunkAllocation) {
     gclog_or_tty->print_cr("Metaspace allocation failed for size "
@@ -3412,6 +3484,16 @@
   }
 }
 
+const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) {
+  switch (mdtype) {
+    case Metaspace::ClassType: return "Class";
+    case Metaspace::NonClassType: return "Metadata";
+    default:
+      assert(false, err_msg("Got bad mdtype: %d", (int) mdtype));
+      return NULL;
+  }
+}
+
 void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) {
   assert(DumpSharedSpaces, "sanity");
 
--- a/src/share/vm/memory/metaspace.hpp	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/memory/metaspace.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -26,6 +26,7 @@
 
 #include "memory/allocation.hpp"
 #include "memory/memRegion.hpp"
+#include "memory/metaspaceChunkFreeListSummary.hpp"
 #include "runtime/virtualspace.hpp"
 #include "utilities/exceptions.hpp"
 
@@ -60,6 +61,7 @@
 class ClassLoaderData;
 class Metablock;
 class Metachunk;
+class MetaspaceTracer;
 class MetaWord;
 class Mutex;
 class outputStream;
@@ -148,6 +150,8 @@
   static ChunkManager* _chunk_manager_metadata;
   static ChunkManager* _chunk_manager_class;
 
+  static const MetaspaceTracer* _tracer;
+
  public:
   static VirtualSpaceList* space_list()       { return _space_list; }
   static VirtualSpaceList* class_space_list() { return _class_space_list; }
@@ -163,6 +167,8 @@
     return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata();
   }
 
+  static const MetaspaceTracer* tracer() { return _tracer; }
+
  private:
   // This is used by DumpSharedSpaces only, where only _vsm is used. So we will
   // maintain a single list for now.
@@ -233,7 +239,9 @@
   static void purge();
 
   static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size,
-                                   MetadataType mdtype, TRAPS);
+                                   MetaspaceObj::Type type, MetadataType mdtype, TRAPS);
+
+  static const char* metadata_type_name(Metaspace::MetadataType mdtype);
 
   void print_on(outputStream* st) const;
   // Debugging support
@@ -347,6 +355,9 @@
     return min_chunk_size_words() * BytesPerWord;
   }
 
+  static bool has_chunk_free_list(Metaspace::MetadataType mdtype);
+  static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype);
+
   // Print change in used metadata.
   static void print_metaspace_change(size_t prev_metadata_used);
   static void print_on(outputStream * out);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#ifndef SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+
+#include "memory/allocation.hpp"
+
+class MetaspaceChunkFreeListSummary VALUE_OBJ_CLASS_SPEC {
+  size_t _num_specialized_chunks;
+  size_t _num_small_chunks;
+  size_t _num_medium_chunks;
+  size_t _num_humongous_chunks;
+
+  size_t _specialized_chunks_size_in_bytes;
+  size_t _small_chunks_size_in_bytes;
+  size_t _medium_chunks_size_in_bytes;
+  size_t _humongous_chunks_size_in_bytes;
+
+ public:
+  MetaspaceChunkFreeListSummary() :
+    _num_specialized_chunks(0),
+    _num_small_chunks(0),
+    _num_medium_chunks(0),
+    _num_humongous_chunks(0),
+    _specialized_chunks_size_in_bytes(0),
+    _small_chunks_size_in_bytes(0),
+    _medium_chunks_size_in_bytes(0),
+    _humongous_chunks_size_in_bytes(0)
+  {}
+
+  MetaspaceChunkFreeListSummary(size_t num_specialized_chunks,
+                                size_t num_small_chunks,
+                                size_t num_medium_chunks,
+                                size_t num_humongous_chunks,
+                                size_t specialized_chunks_size_in_bytes,
+                                size_t small_chunks_size_in_bytes,
+                                size_t medium_chunks_size_in_bytes,
+                                size_t humongous_chunks_size_in_bytes) :
+    _num_specialized_chunks(num_specialized_chunks),
+    _num_small_chunks(num_small_chunks),
+    _num_medium_chunks(num_medium_chunks),
+    _num_humongous_chunks(num_humongous_chunks),
+    _specialized_chunks_size_in_bytes(specialized_chunks_size_in_bytes),
+    _small_chunks_size_in_bytes(small_chunks_size_in_bytes),
+    _medium_chunks_size_in_bytes(medium_chunks_size_in_bytes),
+    _humongous_chunks_size_in_bytes(humongous_chunks_size_in_bytes)
+  {}
+
+  size_t num_specialized_chunks() const {
+    return _num_specialized_chunks;
+  }
+
+  size_t num_small_chunks() const {
+    return _num_small_chunks;
+  }
+
+  size_t num_medium_chunks() const {
+    return _num_medium_chunks;
+  }
+
+  size_t num_humongous_chunks() const {
+    return _num_humongous_chunks;
+  }
+
+  size_t specialized_chunks_size_in_bytes() const {
+    return _specialized_chunks_size_in_bytes;
+  }
+
+  size_t small_chunks_size_in_bytes() const {
+    return _small_chunks_size_in_bytes;
+  }
+
+  size_t medium_chunks_size_in_bytes() const {
+    return _medium_chunks_size_in_bytes;
+  }
+
+  size_t humongous_chunks_size_in_bytes() const {
+    return _humongous_chunks_size_in_bytes;
+  }
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+class MetaspaceGCThresholdUpdater : public AllStatic {
+ public:
+  enum Type {
+    ComputeNewSize,
+    ExpandAndAllocate,
+    Last
+  };
+
+  static const char* to_string(MetaspaceGCThresholdUpdater::Type updater) {
+    switch (updater) {
+      case ComputeNewSize:
+        return "compute_new_size";
+      case ExpandAndAllocate:
+        return "expand_and_allocate";
+      default:
+        assert(false, err_msg("Got bad updater: %d", (int) updater));
+        return NULL;
+    };
+  }
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/metaspaceTracer.cpp	Mon Mar 24 15:34:10 2014 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
+#include "memory/metaspaceTracer.hpp"
+#include "trace/tracing.hpp"
+#include "trace/traceBackend.hpp"
+
+void MetaspaceTracer::report_gc_threshold(size_t old_val,
+                                          size_t new_val,
+                                          MetaspaceGCThresholdUpdater::Type updater) const {
+  EventMetaspaceGCThreshold event;
+  if (event.should_commit()) {
+    event.set_oldValue(old_val);
+    event.set_newValue(new_val);
+    event.set_updater((u1)updater);
+    event.commit();
+  }
+}
+
+void MetaspaceTracer::report_metaspace_allocation_failure(ClassLoaderData *cld,
+                                                          size_t word_size,
+                                                          MetaspaceObj::Type objtype,
+                                                          Metaspace::MetadataType mdtype) const {
+  send_allocation_failure_event<EventMetaspaceAllocationFailure>(cld, word_size, objtype, mdtype);
+}
+
+void MetaspaceTracer::report_metadata_oom(ClassLoaderData *cld,
+                                         size_t word_size,
+                                         MetaspaceObj::Type objtype,
+                                         Metaspace::MetadataType mdtype) const {
+  send_allocation_failure_event<EventMetaspaceOOM>(cld, word_size, objtype, mdtype);
+}
+
+template <typename E>
+void MetaspaceTracer::send_allocation_failure_event(ClassLoaderData *cld,
+                                                    size_t word_size,
+                                                    MetaspaceObj::Type objtype,
+                                                    Metaspace::MetadataType mdtype) const {
+  E event;
+  if (event.should_commit()) {
+    if (cld->is_anonymous()) {
+      event.set_classLoader(NULL);
+      event.set_anonymousClassLoader(true);
+    } else {
+      if (cld->is_the_null_class_loader_data()) {
+        event.set_classLoader((Klass*) NULL);
+      } else {
+        event.set_classLoader(cld->class_loader()->klass());
+      }
+      event.set_anonymousClassLoader(false);
+    }
+
+    event.set_size(word_size * BytesPerWord);
+    event.set_metadataType((u1) mdtype);
+    event.set_metaspaceObjectType((u1) objtype);
+    event.commit();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/metaspaceTracer.hpp	Mon Mar 24 15:34:10 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/metaspace.hpp"
+#include "memory/metaspaceGCThresholdUpdater.hpp"
+
+class ClassLoaderData;
+
+class MetaspaceTracer : public CHeapObj<mtTracing> {
+  template <typename E>
+  void send_allocation_failure_event(ClassLoaderData *cld,
+                                     size_t word_size,
+                                     MetaspaceObj::Type objtype,
+                                     Metaspace::MetadataType mdtype) const;
+ public:
+  void report_gc_threshold(size_t old_val,
+                           size_t new_val,
+                           MetaspaceGCThresholdUpdater::Type updater) const;
+  void report_metaspace_allocation_failure(ClassLoaderData *cld,
+                                           size_t word_size,
+                                           MetaspaceObj::Type objtype,
+                                           Metaspace::MetadataType mdtype) const;
+  void report_metadata_oom(ClassLoaderData *cld,
+                           size_t word_size,
+                           MetaspaceObj::Type objtype,
+                           Metaspace::MetadataType mdtype) const;
+
+};
+
+#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP
--- a/src/share/vm/trace/trace.xml	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/trace/trace.xml	Mon Mar 24 15:34:10 2014 -0700
@@ -193,11 +193,48 @@
     <event id="MetaspaceSummary" path="vm/gc/heap/metaspace_summary" label="Metaspace Summary" is_instant="true">
       <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
       <value type="GCWHEN" field="when" label="When" />
+      <value type="BYTES64" field="gcThreshold" label="GC Threshold" />
       <structvalue type="MetaspaceSizes" field="metaspace" label="Total"/>
       <structvalue type="MetaspaceSizes" field="dataSpace" label="Data"/>
       <structvalue type="MetaspaceSizes" field="classSpace" label="Class"/>
     </event>
 
+    <event id="MetaspaceGCThreshold" path="vm/gc/metaspace/gc_threshold" label="Metaspace GC Threshold" is_instant="true">
+      <value type="BYTES64" field="oldValue" label="Old Value" />
+      <value type="BYTES64" field="newValue" label="New Value" />
+      <value type="GCTHRESHOLDUPDATER" field="updater" label="Updater" />
+    </event>
+
+    <event id="MetaspaceAllocationFailure" path="vm/gc/metaspace/allocation_failure" label="Metaspace Allocation Failure" is_instant="true" has_stacktrace="true">
+      <value type="CLASS" field="classLoader" label="Class Loader" />
+      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+      <value type="BYTES64" field="size" label="Size" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+    </event>
+
+    <event id="MetaspaceOOM" path="vm/gc/metaspace/out_of_memory" label="Metaspace Out of Memory" is_instant="true" has_stacktrace="true">
+      <value type="CLASS" field="classLoader" label="Class Loader" />
+      <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
+      <value type="BYTES64" field="size" label="Size" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="METASPACEOBJTYPE" field="metaspaceObjectType" label="Metaspace Object Type" />
+    </event>
+
+    <event id="MetaspaceChunkFreeListSummary" path="vm/gc/metaspace/chunk_free_list_summary" label="Metaspace Chunk Free List Summary" is_instant="true">
+      <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+      <value type="GCWHEN" field="when" label="When" />
+      <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
+      <value type="ULONG" field="specializedChunks" label="Specialized Chunks" />
+      <value type="BYTES64" field="specializedChunksTotalSize" label="Specialized Chunks Total Size" />
+      <value type="ULONG" field="smallChunks" label="Small Chunks" />
+      <value type="BYTES64" field="smallChunksTotalSize" label="Small Chunks Total Size" />
+      <value type="ULONG" field="mediumChunks" label="Medium Chunks" />
+      <value type="BYTES64" field="mediumChunksTotalSize" label="Medium Chunks Total Size" />
+      <value type="ULONG" field="humongousChunks" label="Humongous Chunks" />
+      <value type="BYTES64" field="humongousChunksTotalSize" label="Humongous Chunks Total Size" />
+    </event>
+
     <event id="PSHeapSummary" path="vm/gc/heap/ps_summary" label="Parallel Scavenge Heap Summary" is_instant="true">
       <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
       <value type="GCWHEN" field="when" label="When" />
--- a/src/share/vm/trace/tracetypes.xml	Mon Mar 24 14:20:49 2014 -0700
+++ b/src/share/vm/trace/tracetypes.xml	Mon Mar 24 15:34:10 2014 -0700
@@ -130,11 +130,26 @@
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="GCThresholdUpdater" hr_name="GC Treshold Updater"
+                  type="U1" jvm_type="GCTHRESHOLDUPDATER">
+      <value type="UTF8" field="updater" label="updater" />
+    </content_type>
+
     <content_type id="ReferenceType" hr_name="Reference Type"
                   type="U1" jvm_type="REFERENCETYPE">
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="MetadataType" hr_name="Metadata Type"
+                  type="U1" jvm_type="METADATATYPE">
+      <value type="UTF8" field="type" label="type" />
+    </content_type>
+
+    <content_type id="MetaspaceObjectType" hr_name="Metaspace Object Type"
+                  type="U1" jvm_type="METASPACEOBJTYPE">
+      <value type="UTF8" field="type" label="type" />
+    </content_type>
+
     <content_type id="NARROW_OOP_MODE" hr_name="Narrow Oop Mode"
                   type="U1" jvm_type="NARROWOOPMODE">
       <value type="UTF8" field="mode" label="mode" />
@@ -324,10 +339,22 @@
     <primary_type symbol="G1YCTYPE" datatype="U1" contenttype="G1YCTYPE"
                   type="u1" sizeop="sizeof(u1)" />
 
+    <!-- GCTHRESHOLDUPDATER -->
+    <primary_type symbol="GCTHRESHOLDUPDATER" datatype="U1" contenttype="GCTHRESHOLDUPDATER"
+                  type="u1" sizeop="sizeof(u1)" />
+
     <!-- REFERENCETYPE -->
     <primary_type symbol="REFERENCETYPE" datatype="U1"
                   contenttype="REFERENCETYPE" type="u1" sizeop="sizeof(u1)" />
 
+    <!-- METADATATYPE -->
+    <primary_type symbol="METADATATYPE" datatype="U1"
+                  contenttype="METADATATYPE" type="u1" sizeop="sizeof(u1)" />
+
+    <!-- METADATAOBJTYPE -->
+    <primary_type symbol="METASPACEOBJTYPE" datatype="U1"
+                  contenttype="METASPACEOBJTYPE" type="u1" sizeop="sizeof(u1)" />
+
     <!-- NARROWOOPMODE -->
     <primary_type symbol="NARROWOOPMODE" datatype="U1"
                   contenttype="NARROWOOPMODE" type="u1" sizeop="sizeof(u1)" />