src/share/vm/code/codeCache.cpp

Print this page

        

@@ -30,10 +30,11 @@
 #include "code/icBuffer.hpp"
 #include "code/nmethod.hpp"
 #include "code/pcDesc.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc_implementation/shared/markSweep.hpp"
+#include "interpreter/abstractInterpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/gcLocker.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"

@@ -50,20 +51,20 @@
 
 // Helper class for printing in CodeCache
 
 class CodeBlob_sizes {
  private:
-  int count;
-  int total_size;
-  int header_size;
-  int code_size;
-  int stub_size;
-  int relocation_size;
-  int scopes_oop_size;
-  int scopes_metadata_size;
-  int scopes_data_size;
-  int scopes_pcs_size;
+  size_t count;
+  size_t total_size;
+  size_t header_size;
+  size_t code_size;
+  size_t stub_size;
+  size_t relocation_size;
+  size_t scopes_oop_size;
+  size_t scopes_metadata_size;
+  size_t scopes_data_size;
+  size_t scopes_pcs_size;
 
  public:
   CodeBlob_sizes() {
     count            = 0;
     total_size       = 0;

@@ -75,27 +76,32 @@
     scopes_metadata_size  = 0;
     scopes_data_size = 0;
     scopes_pcs_size  = 0;
   }
 
-  int total()                                    { return total_size; }
+  size_t get_total_size()  { return total_size; }
+  size_t get_total_count() { return count; }
   bool is_empty()                                { return count == 0; }
 
   void print(const char* title) {
-    tty->print_cr(" #%d %s = %dK (hdr %d%%,  loc %d%%, code %d%%, stub %d%%, [oops %d%%, data %d%%, pcs %d%%])",
+    if (count == 0) {
+      tty->print_cr("  #%u %s", count, title);
+    } else {
+      tty->print_cr("  #%d %s = %dkB (hdr %u%%,  loc %u%%, code %u%%, stub %u%%, [oops %u%%, data %u%%, pcs %u%%])",
                   count,
                   title,
-                  total() / K,
+                    total_size / K,
                   header_size             * 100 / total_size,
                   relocation_size         * 100 / total_size,
                   code_size               * 100 / total_size,
                   stub_size               * 100 / total_size,
                   scopes_oop_size         * 100 / total_size,
                   scopes_metadata_size    * 100 / total_size,
                   scopes_data_size        * 100 / total_size,
                   scopes_pcs_size         * 100 / total_size);
   }
+  }
 
   void add(CodeBlob* cb) {
     count++;
     total_size       += cb->size();
     header_size      += cb->header_size();

@@ -856,148 +862,158 @@
     _heap->verify();
   }
 }
 
 void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
-  if (PrintCodeCache2) {  // Need to add a new flag
+  if (PrintCodeCacheAllocation) {  // Need to add a new flag
     ResourceMark rm;
     if (size == 0)  size = cb->size();
-    tty->print_cr("CodeCache %s:  addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size);
+    tty->print_cr("CodeCache %s:  addr: " INTPTR_FORMAT ", size: %dB", event, cb, size);
   }
 }
 
-void CodeCache::print_internals() {
-  int nmethodCount = 0;
-  int runtimeStubCount = 0;
-  int adapterCount = 0;
-  int deoptimizationStubCount = 0;
-  int uncommonTrapStubCount = 0;
-  int bufferBlobCount = 0;
-  int total = 0;
-  int nmethodAlive = 0;
-  int nmethodNotEntrant = 0;
-  int nmethodZombie = 0;
-  int nmethodUnloaded = 0;
-  int nmethodJava = 0;
-  int nmethodNative = 0;
-  int maxCodeSize = 0;
+void CodeCache::print_details() {
+  size_t total_entries = 0;
+  size_t max_code_size = 0;
+
+  CodeBlob_sizes runtime_stubs;
+  CodeBlob_sizes adapters;
+  CodeBlob_sizes deoptimization_stubs;
+  CodeBlob_sizes uncommon_trap_stubs;
+  CodeBlob_sizes buffer_blobs;
+  CodeBlob_sizes in_use;
+  CodeBlob_sizes not_entrant;
+  CodeBlob_sizes zombie;
+  CodeBlob_sizes unloaded;
+  CodeBlob_sizes java_methods;
+  CodeBlob_sizes native_methods;
+  CodeBlob_sizes other_entries;
+  CodeBlob_sizes tiers[CompLevel_full_optimization + 1];
+
   ResourceMark rm;
 
-  CodeBlob *cb;
-  for (cb = first(); cb != NULL; cb = next(cb)) {
-    total++;
+  FOR_ALL_BLOBS(cb) {
+    total_entries++;
     if (cb->is_nmethod()) {
       nmethod* nm = (nmethod*)cb;
 
       if (Verbose && nm->method() != NULL) {
         ResourceMark rm;
         char *method_name = nm->method()->name_and_sig_as_C_string();
         tty->print("%s", method_name);
-        if(nm->is_alive()) { tty->print_cr(" alive"); }
-        if(nm->is_not_entrant()) { tty->print_cr(" not-entrant"); }
-        if(nm->is_zombie()) { tty->print_cr(" zombie"); }
-      }
-
-      nmethodCount++;
-
-      if(nm->is_alive()) { nmethodAlive++; }
-      if(nm->is_not_entrant()) { nmethodNotEntrant++; }
-      if(nm->is_zombie()) { nmethodZombie++; }
-      if(nm->is_unloaded()) { nmethodUnloaded++; }
-      if(nm->is_native_method()) { nmethodNative++; }
-
-      if(nm->method() != NULL && nm->is_java_method()) {
-        nmethodJava++;
-        if (nm->insts_size() > maxCodeSize) {
-          maxCodeSize = nm->insts_size();
+        if (nm->is_in_use()) {
+          tty->print_cr(" in-use");
+        } else if (nm->is_not_entrant()) {
+          tty->print_cr(" not-entrant");
+        } else if (nm->is_zombie()) {
+          tty->print_cr(" zombie");
+        }
+      }
+
+      if (nm->is_in_use()) {
+        in_use.add(nm);
+      } else if (nm->is_not_entrant()) {
+        not_entrant.add(nm);
+      } else if (nm->is_zombie()) {
+        zombie.add(nm);
+      } else if (nm->is_unloaded()) {
+        unloaded.add(nm);
+      }
+
+      if(nm->is_native_method()) {
+        native_methods.add(nm);
+      }
+
+      // Native methods are Tier 0
+      tiers[nm->comp_level()].add(nm);
+
+      if (nm->method() != NULL && nm->is_java_method()) {
+        java_methods.add(nm);
+        if ((size_t)nm->insts_size() > max_code_size) {
+          max_code_size = nm->insts_size();
         }
       }
     } else if (cb->is_runtime_stub()) {
-      runtimeStubCount++;
+      runtime_stubs.add(cb);
     } else if (cb->is_deoptimization_stub()) {
-      deoptimizationStubCount++;
+      deoptimization_stubs.add(cb);
     } else if (cb->is_uncommon_trap_stub()) {
-      uncommonTrapStubCount++;
+      uncommon_trap_stubs.add(cb);
     } else if (cb->is_adapter_blob()) {
-      adapterCount++;
+      adapters.add(cb);
     } else if (cb->is_buffer_blob()) {
-      bufferBlobCount++;
+      buffer_blobs.add(cb);
+    } else {
+      other_entries.add(cb);
     }
   }
 
+  tty->print_cr("\nCode cache entries: (total of #%u)", total_entries);
+  size_t total_nm_count = tiers[0].get_total_count() + tiers[1].get_total_count() + tiers[2].get_total_count() +
+                                  tiers[3].get_total_count() + tiers[4].get_total_count();
+  size_t total_nm_size =  tiers[0].get_total_size() + tiers[1].get_total_size() + tiers[2].get_total_size() +
+                                  tiers[3].get_total_size() + tiers[4].get_total_size();
+  tty->print_cr("nmethods:\t#%u\t%ukB",  total_nm_count, total_nm_size / K);
+  tty->print_cr("  Java:\t\t#%u\t%ukB",  java_methods.get_total_count(), java_methods.get_total_size() / K);
+  tty->print_cr("   Tier 1:\t#%u\t%ukB", tiers[1].get_total_count(), tiers[1].get_total_size() / K);
+  tty->print_cr("   Tier 2:\t#%u\t%ukB", tiers[2].get_total_count(), tiers[2].get_total_size() / K);
+  tty->print_cr("   Tier 3:\t#%u\t%ukB", tiers[3].get_total_count(), tiers[3].get_total_size() / K);
+  tty->print_cr("   Tier 4:\t#%u\t%ukB", tiers[4].get_total_count(), tiers[4].get_total_size() / K);
+  tty->print_cr("  Native:\t#%u\t%ukB",  native_methods.get_total_count(), native_methods.get_total_size() / K);
+
+  tty->print_cr("runtime-stubs:\t#%u\t%ukB",  runtime_stubs.get_total_count(), runtime_stubs.get_total_size() / K);
+  tty->print_cr("adapters:\t#%u\t%ukB",       adapters.get_total_count(), adapters.get_total_size() / K);
+  tty->print_cr("buffer blobs:\t#%u\t%ukB",   buffer_blobs.get_total_count(), buffer_blobs.get_total_size() / K);
+  tty->print_cr("deopt-stubs:\t#%u\t%ukB",    deoptimization_stubs.get_total_count(), deoptimization_stubs.get_total_size() / K);
+  tty->print_cr("uncommon-traps:\t#%u\t%ukB", uncommon_trap_stubs.get_total_count(), uncommon_trap_stubs.get_total_size() / K);
+  tty->print_cr("others:\t\t#%u\t%ukB\n",     other_entries.get_total_count(), other_entries.get_total_size() / K);
+
+  tty->print_cr("nmethod state distribution");
+  tty->print_cr("  in-use:\t#%u\t%ukB",       in_use.get_total_count(), in_use.get_total_size() / K);
+  tty->print_cr("  not-entrant:\t#%u\t%ukB",  not_entrant.get_total_count(), not_entrant.get_total_size() / K);
+  tty->print_cr("  zombie:\t#%u\t%ukB",       zombie.get_total_count(), zombie.get_total_size() / K);
+  tty->print_cr("  unloaded:\t#%u\t%ukB",     unloaded.get_total_count(), unloaded.get_total_size() / K);
+
+  if (Verbose) {
+    tty->print_cr("\nnmethod size distribution (non-zombie java)");
+
   int bucketSize = 512;
-  int bucketLimit = maxCodeSize / bucketSize + 1;
+    int bucketLimit = max_code_size / bucketSize + 1;
   int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode);
-  memset(buckets,0,sizeof(int) * bucketLimit);
+    memset(buckets, 0, sizeof(int) * bucketLimit);
 
-  for (cb = first(); cb != NULL; cb = next(cb)) {
+    FOR_ALL_BLOBS(cb) {
     if (cb->is_nmethod()) {
       nmethod* nm = (nmethod*)cb;
       if(nm->is_java_method()) {
         buckets[nm->insts_size() / bucketSize]++;
       }
     }
   }
-  tty->print_cr("Code Cache Entries (total of %d)",total);
-  tty->print_cr("-------------------------------------------------");
-  tty->print_cr("nmethods: %d",nmethodCount);
-  tty->print_cr("\talive: %d",nmethodAlive);
-  tty->print_cr("\tnot_entrant: %d",nmethodNotEntrant);
-  tty->print_cr("\tzombie: %d",nmethodZombie);
-  tty->print_cr("\tunloaded: %d",nmethodUnloaded);
-  tty->print_cr("\tjava: %d",nmethodJava);
-  tty->print_cr("\tnative: %d",nmethodNative);
-  tty->print_cr("runtime_stubs: %d",runtimeStubCount);
-  tty->print_cr("adapters: %d",adapterCount);
-  tty->print_cr("buffer blobs: %d",bufferBlobCount);
-  tty->print_cr("deoptimization_stubs: %d",deoptimizationStubCount);
-  tty->print_cr("uncommon_traps: %d",uncommonTrapStubCount);
-  tty->print_cr("\nnmethod size distribution (non-zombie java)");
-  tty->print_cr("-------------------------------------------------");
 
   for(int i=0; i<bucketLimit; i++) {
-    if(buckets[i] != 0) {
+      if (buckets[i] != 0) {
       tty->print("%d - %d bytes",i*bucketSize,(i+1)*bucketSize);
       tty->fill_to(40);
       tty->print_cr("%d",buckets[i]);
     }
   }
 
   FREE_C_HEAP_ARRAY(int, buckets, mtCode);
-}
-
-#endif // !PRODUCT
-
-void CodeCache::print() {
-  print_summary(tty);
 
 #ifndef PRODUCT
-  if (!Verbose) return;
-
-  CodeBlob_sizes live;
-  CodeBlob_sizes dead;
-
-  FOR_ALL_BLOBS(p) {
-    if (!p->is_alive()) {
-      dead.add(p);
-    } else {
-      live.add(p);
-    }
-  }
-
-  tty->print_cr("CodeCache:");
-
   tty->print_cr("nmethod dependency checking time %f", dependentCheckTime.seconds(),
                 dependentCheckTime.seconds() / dependentCheckCount);
-
-  if (!live.is_empty()) {
-    live.print("live");
-  }
-  if (!dead.is_empty()) {
-    dead.print("dead");
+#endif
   }
 
+}
+
+#endif // !PRODUCT
+
+void CodeCache::print() {
+  print_summary(tty);
 
   if (WizardMode) {
      // print the oop_map usage
     int code_size = 0;
     int number_of_blobs = 0;

@@ -1018,29 +1034,56 @@
     tty->print_cr("  #blobs    = %d", number_of_blobs);
     tty->print_cr("  code size = %d", code_size);
     tty->print_cr("  #oop_maps = %d", number_of_oop_maps);
     tty->print_cr("  map size  = %d", map_size);
   }
-
-#endif // !PRODUCT
 }
 
 void CodeCache::print_summary(outputStream* st, bool detailed) {
   size_t total = (_heap->high_boundary() - _heap->low_boundary());
-  st->print_cr("CodeCache: size=" SIZE_FORMAT "Kb used=" SIZE_FORMAT
-               "Kb max_used=" SIZE_FORMAT "Kb free=" SIZE_FORMAT "Kb",
+  st->print_cr("CodeCache: size=" SIZE_FORMAT "kB used=" SIZE_FORMAT
+               "kB max_used=" SIZE_FORMAT "kB free=" SIZE_FORMAT "kB",
                total/K, (total - unallocated_capacity())/K,
                maxCodeCacheUsed/K, unallocated_capacity()/K);
 
+
   if (detailed) {
+    size_t interpreter_size = AbstractInterpreter::code()->total_space() / K;
+    CodeBlob_sizes live_nm;
+    CodeBlob_sizes dead_nm;
+    CodeBlob_sizes stubs;
+    CodeBlob_sizes adapters;
+    size_t total_size = 0;
+
+    FOR_ALL_BLOBS(p) {
+      total_size += p->size();
+      // live or not-entrant methods
+      if (p->is_nmethod()) {
+        if (p->is_alive()) {
+          live_nm.add(p);
+        } else {
+          dead_nm.add(p);
+        }
+      } else {
+        if (p->is_adapter_blob()) {
+          adapters.add(p);
+        } else {
+          stubs.add(p);
+        }
+      }
+    }
+    st->print_cr(" Interpreter=%ukB live_nmethods=%u(%ukB) dead_nmethods=%u(%ukB) stubs=%u(%ukB) adapters=%u(%ukB)",
+                       interpreter_size, live_nm.get_total_count(), live_nm.get_total_size() / K,
+                       dead_nm.get_total_count(), dead_nm.get_total_size() / K,
+                       stubs.get_total_count(), stubs.get_total_size() / K,
+                       adapters.get_total_count(), adapters.get_total_size() / K);
+
     st->print_cr(" bounds [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT "]",
                  _heap->low_boundary(),
                  _heap->high(),
                  _heap->high_boundary());
-    st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT
-                 " adapters=" UINT32_FORMAT,
-                 nof_blobs(), nof_nmethods(), nof_adapters());
+
     st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ?
                  "enabled" : Arguments::mode() == Arguments::_int ?
                  "disabled (interpreter mode)" :
                  "disabled (not enough contiguous free space left)");
   }