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