diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp --- a/src/share/vm/code/codeCache.cpp +++ b/src/share/vm/code/codeCache.cpp @@ -31,6 +31,7 @@ #include "code/nmethod.hpp" #include "code/pcDesc.hpp" #include "gc_implementation/shared/markSweep.hpp" +#include "interpreter/abstractInterpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.hpp" #include "memory/iterator.hpp" @@ -78,7 +79,7 @@ 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%%])", + tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, data %d%%, pcs %d%%])", count, title, total() / K, @@ -928,30 +929,92 @@ FREE_C_HEAP_ARRAY(int, buckets, mtCode); } +#endif // PRODUCT + void CodeCache::print() { - CodeBlob_sizes live; - CodeBlob_sizes dead; + const int tiered_levels = 4; + CodeBlob_sizes live[4 + 1]; + CodeBlob_sizes dead[4 + 1]; + + CodeBlob_sizes runtime_stubs; + CodeBlob_sizes deoptimization_stubs; + CodeBlob_sizes uncommon_trap_stubs; + CodeBlob_sizes exception_stubs; + CodeBlob_sizes safepoint_stubs; + CodeBlob_sizes adapter_blobs; + CodeBlob_sizes method_handles_adapter_blobs; + CodeBlob_sizes other_stubs; FOR_ALL_BLOBS(p) { - if (!p->is_alive()) { - dead.add(p); + if (p->is_alive()) { + if (p->is_nmethod()) { + nmethod* nm = p->as_nmethod_or_null(); + const int comp_level = nm->comp_level(); + live[comp_level].add(nm); + } else { + if (p->is_runtime_stub()) { + runtime_stubs.add(p); + } else if (p->is_deoptimization_stub()) { + deoptimization_stubs.add(p); + } else if (p->is_uncommon_trap_stub()) { + uncommon_trap_stubs.add(p); + } else if (p->is_exception_stub()) { + exception_stubs.add(p); + } else if (p->is_safepoint_stub()) { + safepoint_stubs.add(p); + } else if (p->is_adapter_blob()) { + adapter_blobs.add(p); + } else if (p->is_method_handles_adapter_blob()) { + method_handles_adapter_blobs.add(p); + } else { + other_stubs.add(p); + tty->print_cr("name=%s, size=%d", p->name(), p->size()); + } + } } else { - live.add(p); + if (p->is_nmethod()) { + nmethod* nm = p->as_nmethod_or_null(); + const int comp_level = nm->comp_level(); + dead[comp_level].add(nm); + } } } tty->print_cr("CodeCache:"); +#ifndef PRODUCT tty->print_cr("nmethod dependency checking time %f", dependentCheckTime.seconds(), dependentCheckTime.seconds() / dependentCheckCount); +#endif - if (!live.is_empty()) { - live.print("live"); - } - if (!dead.is_empty()) { - dead.print("dead"); + // Tier 0 (interpreter) + { + StubQueue* code = AbstractInterpreter::code(); + tty->print_cr(" Tier 0:"); + tty->print_cr(" total=%dk, used=%dk", code->total_space() / K, code->used_space() / K); } + // Tier 1..n (compilers) + for (int i = 1; i <= tiered_levels; i++) { + tty->print_cr(" Tier %d:", i); + if (!live[i].is_empty()) { + live[i].print("live"); + } + if (!dead[i].is_empty()) { + dead[i].print("dead"); + } + } + + // Stubs + tty->print_cr(" Stubs:"); + runtime_stubs.print("runtime"); + deoptimization_stubs.print("deoptimization"); + uncommon_trap_stubs.print("uncommon trap"); + exception_stubs.print("exception"); + safepoint_stubs.print("safepoint"); + adapter_blobs.print("C2I/I2C adapter"); + method_handles_adapter_blobs.print("method handles adapter"); + other_stubs.print("other"); if (Verbose) { // print the oop_map usage @@ -976,11 +1039,8 @@ tty->print_cr(" #oop_maps = %d", number_of_oop_maps); tty->print_cr(" map size = %d", map_size); } - } -#endif // PRODUCT - void CodeCache::print_bounds(outputStream* st) { st->print_cr("Code Cache [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", _heap->low_boundary(), diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp --- a/src/share/vm/code/codeCache.hpp +++ b/src/share/vm/code/codeCache.hpp @@ -145,7 +145,7 @@ static void prune_scavenge_root_nmethods(); // Printing/debugging - static void print() PRODUCT_RETURN; // prints summary + static void print(); // prints summary static void print_internals(); static void verify(); // verifies the code cache static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; diff --git a/src/share/vm/interpreter/templateInterpreter.cpp b/src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp +++ b/src/share/vm/interpreter/templateInterpreter.cpp @@ -45,8 +45,7 @@ // generate interpreter { ResourceMark rm; TraceTime timer("Interpreter generation", TraceStartupTime); - int code_size = InterpreterCodeSize; - NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space + int code_size = InterpreterCodeSize NOT_PRODUCT(* 4); // debug uses extra interpreter code space _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, "Interpreter"); InterpreterGenerator g(_code); diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -929,11 +929,11 @@ "Starts debugger when an implicit OS (e.g., NULL) " \ "exception happens") \ \ - notproduct(bool, PrintCodeCache, false, \ - "Print the compiled_code cache when exiting") \ + diagnostic(bool, PrintCodeCache, false, \ + "Print the compiled code cache when exiting") \ \ develop(bool, PrintCodeCache2, false, \ - "Print detailed info on the compiled_code cache when exiting") \ + "Print detailed info on the compiled code cache when exiting") \ \ diagnostic(bool, PrintStubCode, false, \ "Print generated stub code") \ diff --git a/src/share/vm/runtime/java.cpp b/src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp +++ b/src/share/vm/runtime/java.cpp @@ -377,6 +377,11 @@ BiasedLocking::print_counters(); } + if (PrintCodeCache) { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::print(); + } + // Native memory tracking data if (PrintNMTStatistics) { if (MemTracker::is_on()) {