src/share/vm/code/codeCache.cpp
Print this page
*** 30,39 ****
--- 30,40 ----
#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"
*** 75,101 ****
scopes_metadata_size = 0;
scopes_data_size = 0;
scopes_pcs_size = 0;
}
! int total() { return total_size; }
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%%])",
! count,
title,
! total() / 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();
--- 76,109 ----
scopes_metadata_size = 0;
scopes_data_size = 0;
scopes_pcs_size = 0;
}
! int get_total_size() { return total_size; }
! int get_total_count() { return count; }
bool is_empty() { return count == 0; }
void print(const char* title) {
! const int len = strnlen(title, 25);
! if (count == 0) {
! tty->print_cr("%s%*d#", title, 25-len, count);
! } else {
! tty->print_cr("%s%*d#%7d kB\t(hdr %2u%%, loc %2u%%, code %2u%%, stub %2u%%, [oops %2u%%, data %2u%%, pcs %2u%%])",
title,
! 25-len,
! count,
! 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();
*** 115,134 ****
}
};
// CodeCache implementation
! CodeHeap * CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
int CodeCache::_number_of_adapters = 0;
int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
nmethod* CodeCache::_saved_nmethods = NULL;
int CodeCache::_codemem_full_count = 0;
CodeBlob* CodeCache::first() {
assert_locked_or_safepoint(CodeCache_lock);
return (CodeBlob*)_heap->first();
}
--- 123,157 ----
}
};
// CodeCache implementation
! CodeHeap* CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
int CodeCache::_number_of_adapters = 0;
int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
nmethod* CodeCache::_saved_nmethods = NULL;
int CodeCache::_codemem_full_count = 0;
+ static size_t _max_code_cache_used = 0;
+
+ // Code cache printing options
+ static bool _print_details = false;
+ static bool _print_trace = false;
+ static bool _print_content = false;
+ static bool _print_oop_map_usage = false;
+ static bool _print_dep_check_time = false;
+
+ #ifndef PRODUCT
+ // used to keep track of how much time is spent in mark_for_deoptimization
+ static elapsedTimer dependentCheckTime;
+ static int dependentCheckCount = 0;
+ #endif // PRODUCT
+
CodeBlob* CodeCache::first() {
assert_locked_or_safepoint(CodeCache_lock);
return (CodeBlob*)_heap->first();
}
*** 169,180 ****
cb = next(cb);
}
return (nmethod*)cb;
}
- static size_t maxCodeCacheUsed = 0;
-
CodeBlob* CodeCache::allocate(int size, bool is_critical) {
// Do not seize the CodeCache lock here--if the caller has not
// already done so, we are going to lose bigtime, since the code
// cache will contain a garbage CodeBlob until the caller can
// run the constructor for the CodeBlob subclass he is busy
--- 192,201 ----
*** 195,205 ****
tty->print_cr("code cache extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (%d bytes)",
(intptr_t)_heap->low_boundary(), (intptr_t)_heap->high(),
(address)_heap->high() - (address)_heap->low_boundary());
}
}
! maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_boundary() -
(address)_heap->low_boundary()) - unallocated_capacity());
verify_if_often();
print_trace("allocation", cb, size);
return cb;
}
--- 216,226 ----
tty->print_cr("code cache extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (%d bytes)",
(intptr_t)_heap->low_boundary(), (intptr_t)_heap->high(),
(address)_heap->high() - (address)_heap->low_boundary());
}
}
! _max_code_cache_used = MAX2(_max_code_cache_used, ((address)_heap->high_boundary() -
(address)_heap->low_boundary()) - unallocated_capacity());
verify_if_often();
print_trace("allocation", cb, size);
return cb;
}
*** 679,694 ****
FOR_ALL_ALIVE_NMETHODS(nm) {
nm->clear_inline_caches();
}
}
- #ifndef PRODUCT
- // used to keep track of how much time is spent in mark_for_deoptimization
- static elapsedTimer dependentCheckTime;
- static int dependentCheckCount = 0;
- #endif // PRODUCT
-
int CodeCache::mark_for_deoptimization(DepChange& changes) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
#ifndef PRODUCT
--- 700,709 ----
*** 844,1006 ****
event.set_fullCount(_codemem_full_count);
event.commit();
}
}
//------------------------------------------------------------------------------------------------
// Non-product version
-
#ifndef PRODUCT
void CodeCache::verify_if_often() {
if (VerifyCodeCacheOften) {
_heap->verify();
}
}
void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
! if (PrintCodeCache2) { // 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);
}
}
! 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;
ResourceMark rm;
! CodeBlob *cb;
! for (cb = first(); cb != NULL; cb = next(cb)) {
! total++;
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();
}
}
} else if (cb->is_runtime_stub()) {
! runtimeStubCount++;
} else if (cb->is_deoptimization_stub()) {
! deoptimizationStubCount++;
} else if (cb->is_uncommon_trap_stub()) {
! uncommonTrapStubCount++;
} else if (cb->is_adapter_blob()) {
! adapterCount++;
} else if (cb->is_buffer_blob()) {
! bufferBlobCount++;
}
}
! int bucketSize = 512;
! int bucketLimit = maxCodeSize / bucketSize + 1;
! int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode);
! memset(buckets,0,sizeof(int) * bucketLimit);
! for (cb = first(); cb != NULL; cb = next(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) {
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");
! }
!
!
! if (WizardMode) {
! // print the oop_map usage
int code_size = 0;
int number_of_blobs = 0;
int number_of_oop_maps = 0;
int map_size = 0;
FOR_ALL_BLOBS(p) {
--- 859,1119 ----
event.set_fullCount(_codemem_full_count);
event.commit();
}
}
+ void CodeCache::init_printing_options(const char* str) {
+ if (strcmp("on", str) == 0) {
+ _print_details = true;
+ } else if (strcmp("trace", str) == 0) {
+ _print_trace = true;
+ } else if (strcmp("content", str) == 0) {
+ _print_content = true;
+ } else if(strcmp("oop_map", str) == 0) {
+ _print_oop_map_usage = true;
+ } else if(strcmp("dep_check_time", str) == 0) {
+ _print_dep_check_time = true;
+ } else if (strcmp("all", str) == 0) {
+ _print_details = true;
+ _print_trace = true;
+ _print_content = true;
+ _print_oop_map_usage = true;
+ _print_dep_check_time = true;
+ } else if (strcmp("off", str) != 0) {
+ vm_exit_during_initialization("Syntax error, expecting -XX:PrintCodeCacheDetails=[off|on|all|trace|content|oop_map|dep_check_time]", NULL);
+ }
+ }
+
+ void CodeCache::print() {
+ print_summary(tty);
+
+ #ifndef PRODUCT
+ if (_print_details) {
+ print_details();
+ }
+ if (_print_content) {
+ print_content();
+ }
+ if (WizardMode || _print_oop_map_usage) {
+ print_oop_map_usage();
+ }
+ if (_print_dep_check_time) {
+ print_dependency_checking_time();
+ }
+ #endif
+ }
+
+ 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",
+ total/K, (total - unallocated_capacity())/K,
+ _max_code_cache_used/K, unallocated_capacity()/K);
+
+
+ if (detailed) {
+ int interpreter_size = AbstractInterpreter::code()->total_space() / K;
+ CodeBlob_sizes live_nm;
+ CodeBlob_sizes dead_nm;
+ CodeBlob_sizes stubs;
+ CodeBlob_sizes adapters;
+
+ FOR_ALL_BLOBS(p) {
+ // 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=%dkB 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(" compilation: %s", CompileBroker::should_compile_new_jobs() ?
+ "enabled" : Arguments::mode() == Arguments::_int ?
+ "disabled (interpreter mode)" :
+ "disabled (not enough contiguous free space left)");
+ }
+ }
+
+ void CodeCache::log_state(outputStream* st) {
+ st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ nof_blobs(), nof_nmethods(), nof_adapters(),
+ unallocated_capacity());
+ }
+
+
//------------------------------------------------------------------------------------------------
// Non-product version
#ifndef PRODUCT
void CodeCache::verify_if_often() {
if (VerifyCodeCacheOften) {
_heap->verify();
}
}
void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
! if (_print_trace) {
ResourceMark rm;
! if (size == 0) {
! size = cb->size();
! }
! tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: %dB", event, cb, size);
}
}
! void CodeCache::print_details() {
ResourceMark rm;
! 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];
!
! int total_entries = 0;
! int max_code_size = 0;
!
! FOR_ALL_BLOBS(cb) {
! total_entries++;
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
! 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 (nm->insts_size() > max_code_size) {
! max_code_size = nm->insts_size();
}
}
} else if (cb->is_runtime_stub()) {
! runtime_stubs.add(cb);
} else if (cb->is_deoptimization_stub()) {
! deoptimization_stubs.add(cb);
} else if (cb->is_uncommon_trap_stub()) {
! uncommon_trap_stubs.add(cb);
} else if (cb->is_adapter_blob()) {
! adapters.add(cb);
} else if (cb->is_buffer_blob()) {
! buffer_blobs.add(cb);
! } else {
! other_entries.add(cb);
}
}
! tty->print_cr("\nCode cache entries: (total of #%d)", total_entries);
! int 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();
! int 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%6d# 7%d kB", total_nm_count, total_nm_size / K);
! java_methods.print(" Java");
! tiers[1].print(" Tier 1");
! tiers[2].print(" Tier 2");
! tiers[3].print(" Tier 3");
! tiers[4].print(" Tier 4");
! native_methods.print(" Native");
!
! runtime_stubs.print("runtime stubs");
! adapters.print("adapters");
! buffer_blobs.print("buffer blobs");
! deoptimization_stubs.print("deoptimization stubs");
! uncommon_trap_stubs.print("uncommon trap stubs");
! other_entries.print("others");
!
! tty->print_cr("\nnmethod state distribution");
! in_use.print(" in-use");
! not_entrant.print(" not-entrant");
! zombie.print(" zombie");
! unloaded.print(" unloaded");
! }
!
! void CodeCache::print_content() {
! const int bucketSize = 512;
! const int bucketLimit = _max_code_cache_used / bucketSize + 1;
! int* buckets = NEW_C_HEAP_ARRAY_RETURN_NULL(int, bucketLimit, mtInternal);
! if (buckets == NULL) {
! return;
! }
! memset(buckets, 0, sizeof(int) * bucketLimit);
! FOR_ALL_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
+ if (nm->method() != NULL) {
+ ResourceMark rm;
+ const char *method_name = nm->method()->name_and_sig_as_C_string();
+ if (nm->is_in_use()) {
+ tty->print("in-use: ");
+ } else if (nm->is_not_entrant()) {
+ tty->print("not-entrant: ");
+ } else if (nm->is_zombie()) {
+ tty->print("zombie: ");
+ }
+ tty->print_cr("%s", method_name);
if(nm->is_java_method()) {
buckets[nm->insts_size() / bucketSize]++;
}
}
}
! }
!
tty->print_cr("\nnmethod size distribution (non-zombie java)");
! for (int i = 0; i < bucketLimit; i++) {
! 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, mtInternal);
}
! void CodeCache::print_oop_map_usage() {
int code_size = 0;
int number_of_blobs = 0;
int number_of_oop_maps = 0;
int map_size = 0;
FOR_ALL_BLOBS(p) {
*** 1017,1055 ****
tty->print_cr("OopMaps");
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",
- total/K, (total - unallocated_capacity())/K,
- maxCodeCacheUsed/K, unallocated_capacity()/K);
-
- if (detailed) {
- 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)");
- }
}
! void CodeCache::log_state(outputStream* st) {
! st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
! " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
! nof_blobs(), nof_nmethods(), nof_adapters(),
! unallocated_capacity());
}
!
--- 1130,1141 ----
tty->print_cr("OopMaps");
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);
}
! void CodeCache::print_dependency_checking_time() {
! tty->print_cr("total nmethod dependency checking time: %f[s]", dependentCheckTime.seconds());
! tty->print_cr("total number of dependency checks : %d", dependentCheckCount);
}
! #endif // !PRODUCT