--- old/src/share/vm/code/codeCache.cpp 2013-09-03 12:50:06.942442736 +0200 +++ new/src/share/vm/code/codeCache.cpp 2013-09-03 12:50:06.874442738 +0200 @@ -32,6 +32,7 @@ #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" @@ -65,34 +66,41 @@ public: CodeBlob_sizes() { - count = 0; - total_size = 0; - header_size = 0; - code_size = 0; - stub_size = 0; - relocation_size = 0; - scopes_oop_size = 0; - scopes_metadata_size = 0; - scopes_data_size = 0; - scopes_pcs_size = 0; + count = 0; + total_size = 0; + header_size = 0; + code_size = 0; + stub_size = 0; + relocation_size = 0; + scopes_oop_size = 0; + scopes_metadata_size = 0; + scopes_data_size = 0; + scopes_pcs_size = 0; } - int total() { return total_size; } - bool is_empty() { return count == 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) { - 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); + 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) { @@ -117,7 +125,7 @@ // CodeCache implementation -CodeHeap * CodeCache::_heap = new CodeHeap(); +CodeHeap* CodeCache::_heap = new CodeHeap(); int CodeCache::_number_of_blobs = 0; int CodeCache::_number_of_adapters = 0; int CodeCache::_number_of_nmethods = 0; @@ -127,6 +135,21 @@ 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); @@ -171,8 +194,6 @@ 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 @@ -197,7 +218,7 @@ (address)_heap->high() - (address)_heap->low_boundary()); } } - maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_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); @@ -681,12 +702,6 @@ } } -#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); @@ -846,9 +861,106 @@ } } +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() { @@ -858,198 +970,172 @@ } void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) { - if (PrintCodeCache2) { // Need to add a new flag + if (_print_trace) { ResourceMark rm; - if (size == 0) size = cb->size(); - tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size); + if (size == 0) { + size = 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() { ResourceMark rm; - CodeBlob *cb; - for (cb = first(); cb != NULL; cb = next(cb)) { - total++; + 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 (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"); } + 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); } - nmethodCount++; + if(nm->is_native_method()) { + native_methods.add(nm); + } + + // Native methods are Tier 0 + tiers[nm->comp_level()].add(nm); - 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->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()) { - 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); } } - int bucketSize = 512; - int bucketLimit = maxCodeSize / bucketSize + 1; - int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode); - memset(buckets,0,sizeof(int) * bucketLimit); + 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 (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]++; - } + 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("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; iprint("%d - %d bytes",i*bucketSize,(i+1)*bucketSize); tty->fill_to(40); - tty->print_cr("%d",buckets[i]); + tty->print_cr("%d", buckets[i]); } } - - FREE_C_HEAP_ARRAY(int, buckets, mtCode); + FREE_C_HEAP_ARRAY(int, buckets, mtInternal); } -#endif // !PRODUCT - -void CodeCache::print() { - print_summary(tty); - -#ifndef PRODUCT - if (!Verbose) return; - - CodeBlob_sizes live; - CodeBlob_sizes dead; - +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) { - 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) { - if (p->is_alive()) { - number_of_blobs++; - code_size += p->code_size(); - OopMapSet* set = p->oop_maps(); - if (set != NULL) { - number_of_oop_maps += set->size(); - map_size += set->heap_size(); - } + if (p->is_alive()) { + number_of_blobs++; + code_size += p->code_size(); + OopMapSet* set = p->oop_maps(); + if (set != NULL) { + number_of_oop_maps += set->size(); + map_size += set->heap_size(); } } - 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 + 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_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::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); } - -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()); -} - +#endif // !PRODUCT