# HG changeset patch # User thartmann # Date 1447065344 -3600 # Node ID 1f8d643b02d5c6cfab6992f87ed50f17ac5c8c54 # Parent 5646275e80539ce4f48448bfb727f8ac2cce70bf 8067378: Add segmented code heaps info into jfr events: vm/code_cache/stats and vm/code_cache/config Summary: Added code heap specific information to code cache JFR events. Reviewed-by: twisti, mgronlun diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/code/codeCache.cpp Mon Nov 09 11:35:44 2015 +0100 @@ -133,13 +133,9 @@ address CodeCache::_low_bound = 0; address CodeCache::_high_bound = 0; -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; -int CodeCache::_codemem_full_count = 0; // Initialize array of CodeHeaps GrowableArray* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); @@ -420,42 +416,41 @@ } } print_trace("allocation", cb, size); - _number_of_blobs++; return cb; } void CodeCache::free(CodeBlob* cb) { assert_locked_or_safepoint(CodeCache_lock); - + CodeHeap* heap = get_code_heap(cb); print_trace("free", cb); if (cb->is_nmethod()) { - _number_of_nmethods--; + heap->set_nmethod_count(heap->nmethod_count() - 1); if (((nmethod *)cb)->has_dependencies()) { _number_of_nmethods_with_dependencies--; } } if (cb->is_adapter_blob()) { - _number_of_adapters--; + heap->set_adapter_count(heap->adapter_count() - 1); } - _number_of_blobs--; // Get heap for given CodeBlob and deallocate get_code_heap(cb)->deallocate(cb); - assert(_number_of_blobs >= 0, "sanity check"); + assert(heap->blob_count() >= 0, "sanity check"); } void CodeCache::commit(CodeBlob* cb) { // this is called by nmethod::nmethod, which must already own CodeCache_lock assert_locked_or_safepoint(CodeCache_lock); + CodeHeap* heap = get_code_heap(cb); if (cb->is_nmethod()) { - _number_of_nmethods++; + heap->set_nmethod_count(heap->nmethod_count() + 1); if (((nmethod *)cb)->has_dependencies()) { _number_of_nmethods_with_dependencies++; } } if (cb->is_adapter_blob()) { - _number_of_adapters++; + heap->set_adapter_count(heap->adapter_count() + 1); } // flush the hardware I-cache @@ -774,6 +769,55 @@ } } +int CodeCache::blob_count(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? heap->blob_count() : 0; +} + +int CodeCache::blob_count() { + int count = 0; + FOR_ALL_HEAPS(heap) { + count += (*heap)->blob_count(); + } + return count; +} + +int CodeCache::nmethod_count(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? heap->nmethod_count() : 0; +} + +int CodeCache::nmethod_count() { + int count = 0; + FOR_ALL_HEAPS(heap) { + count += (*heap)->nmethod_count(); + } + return count; +} + +int CodeCache::adapter_count(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? heap->adapter_count() : 0; +} + +int CodeCache::adapter_count() { + int count = 0; + FOR_ALL_HEAPS(heap) { + count += (*heap)->adapter_count(); + } + return count; +} + +address CodeCache::low_bound(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? (address)heap->low_boundary() : NULL; +} + +address CodeCache::high_bound(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? (address)heap->high_boundary() : NULL; +} + size_t CodeCache::capacity() { size_t cap = 0; FOR_ALL_HEAPS(heap) { @@ -863,6 +907,9 @@ initialize_heaps(); } else { // Use a single code heap + FLAG_SET_ERGO(uintx, NonNMethodCodeHeapSize, 0); + FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, 0); + FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, 0); ReservedCodeSpace rs = reserve_heap_memory(ReservedCodeCacheSize); add_heap(rs, "CodeCache", CodeBlobType::All); } @@ -1104,9 +1151,8 @@ CodeHeap* heap = get_code_heap(code_blob_type); assert(heap != NULL, "heap is null"); - if (!heap->was_full() || print) { + if ((heap->full_count() == 0) || print) { // Not yet reported for this heap, report - heap->report_full(); if (SegmentedCodeCache) { warning("%s is full. Compiler has been disabled.", get_code_heap_name(code_blob_type)); warning("Try increasing the code heap size using -XX:%s=", get_code_heap_flag_name(code_blob_type)); @@ -1125,18 +1171,19 @@ tty->print("%s", s.as_string()); } - _codemem_full_count++; + heap->report_full(); + EventCodeCacheFull event; if (event.should_commit()) { event.set_codeBlobType((u1)code_blob_type); event.set_startAddress((u8)heap->low_boundary()); event.set_commitedTopAddress((u8)heap->high()); event.set_reservedTopAddress((u8)heap->high_boundary()); - event.set_entryCount(nof_blobs()); - event.set_methodCount(nof_nmethods()); - event.set_adaptorCount(nof_adapters()); + event.set_entryCount(heap->blob_count()); + event.set_methodCount(heap->nmethod_count()); + event.set_adaptorCount(heap->adapter_count()); event.set_unallocatedCapacity(heap->unallocated_capacity()/K); - event.set_fullCount(_codemem_full_count); + event.set_fullCount(heap->full_count()); event.commit(); } } @@ -1360,7 +1407,7 @@ if (detailed) { st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT " adapters=" UINT32_FORMAT, - nof_blobs(), nof_nmethods(), nof_adapters()); + blob_count(), nmethod_count(), adapter_count()); st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ? "enabled" : Arguments::mode() == Arguments::_int ? "disabled (interpreter mode)" : @@ -1392,6 +1439,6 @@ 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(), + blob_count(), nmethod_count(), adapter_count(), unallocated_capacity()); } diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/code/codeCache.hpp --- a/hotspot/src/share/vm/code/codeCache.hpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/code/codeCache.hpp Mon Nov 09 11:35:44 2015 +0100 @@ -85,13 +85,9 @@ static address _low_bound; // Lower bound of CodeHeap addresses static address _high_bound; // Upper bound of CodeHeap addresses - static int _number_of_blobs; // Total number of CodeBlobs in the cache - static int _number_of_adapters; // Total number of Adapters in the cache - static int _number_of_nmethods; // Total number of nmethods in the cache static int _number_of_nmethods_with_dependencies; // Total number of nmethods with dependencies static bool _needs_cache_clean; // True if inline caches of the nmethods needs to be flushed static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link() - static int _codemem_full_count; // Number of times a CodeHeap in the cache was full static void mark_scavenge_root_nmethods() PRODUCT_RETURN; static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN; @@ -104,7 +100,6 @@ static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType // Returns the name of the VM option to set the size of the corresponding CodeHeap static const char* get_code_heap_flag_name(int code_blob_type); - static bool heap_available(int code_blob_type); // Returns true if an own CodeHeap for the given CodeBlobType is available static size_t heap_alignment(); // Returns the alignment of the CodeHeaps in bytes static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps @@ -139,9 +134,12 @@ static CodeBlob* find_blob_unsafe(void* start); // Same as find_blob but does not fail if looking up a zombie method static nmethod* find_nmethod(void* start); // Returns the nmethod containing the given address - static int nof_blobs() { return _number_of_blobs; } // Returns the total number of CodeBlobs in the cache - static int nof_adapters() { return _number_of_adapters; } // Returns the total number of Adapters in the cache - static int nof_nmethods() { return _number_of_nmethods; } // Returns the total number of nmethods in the cache + static int blob_count(); // Returns the total number of CodeBlobs in the cache + static int blob_count(int code_blob_type); + static int adapter_count(); // Returns the total number of Adapters in the cache + static int adapter_count(int code_blob_type); + static int nmethod_count(); // Returns the total number of nmethods in the cache + static int nmethod_count(int code_blob_type); // GC support static void gc_epilogue(); @@ -177,7 +175,9 @@ // The full limits of the codeCache static address low_bound() { return _low_bound; } + static address low_bound(int code_blob_type); static address high_bound() { return _high_bound; } + static address high_bound(int code_blob_type); // Profiling static size_t capacity(); @@ -191,6 +191,9 @@ static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; } static void clear_inline_caches(); // clear all inline caches + // Returns true if an own CodeHeap for the given CodeBlobType is available + static bool heap_available(int code_blob_type); + // Returns the CodeBlobType for the given nmethod static int get_code_blob_type(nmethod* nm) { return get_code_heap(nm)->code_blob_type(); @@ -239,7 +242,10 @@ // tells how many nmethods have dependencies static int number_of_nmethods_with_dependencies(); - static int get_codemem_full_count() { return _codemem_full_count; } + static int get_codemem_full_count(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? heap->full_count() : 0; + } }; diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Nov 09 11:35:44 2015 +0100 @@ -1547,7 +1547,7 @@ if (PrintMethodFlushing) { tty->print_cr("*flushing nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT "/Free CodeCache:" SIZE_FORMAT "Kb", - _compile_id, p2i(this), CodeCache::nof_blobs(), + _compile_id, p2i(this), CodeCache::blob_count(), CodeCache::unallocated_capacity(CodeCache::get_code_blob_type(this))/1024); } diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/memory/heap.cpp --- a/hotspot/src/share/vm/memory/heap.cpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/memory/heap.cpp Mon Nov 09 11:35:44 2015 +0100 @@ -47,7 +47,10 @@ _freelist_segments = 0; _freelist_length = 0; _max_allocated_capacity = 0; - _was_full = false; + _blob_count = 0; + _nmethod_count = 0; + _adapter_count = 0; + _full_count = 0; } @@ -185,6 +188,7 @@ assert(!block->free(), "must be marked free"); DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size)); _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); + _blob_count++; return block->allocated_space(); } @@ -198,6 +202,7 @@ _next_segment += number_of_segments; DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size)); _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); + _blob_count++; return b->allocated_space(); } else { return NULL; diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/memory/heap.hpp --- a/hotspot/src/share/vm/memory/heap.hpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/memory/heap.hpp Mon Nov 09 11:35:44 2015 +0100 @@ -100,7 +100,11 @@ const char* _name; // Name of the CodeHeap const int _code_blob_type; // CodeBlobType it contains - bool _was_full; // True if the code heap was full + int _blob_count; // Number of CodeBlobs + int _nmethod_count; // Number of nmethods + int _adapter_count; // Number of adapters + int _full_count; // Number of times the code heap was full + enum { free_sentinel = 0xFF }; @@ -179,8 +183,13 @@ // Debugging / Profiling const char* name() const { return _name; } - bool was_full() { return _was_full; } - void report_full() { _was_full = true; } + int blob_count() { return _blob_count; } + int nmethod_count() { return _nmethod_count; } + void set_nmethod_count(int count) { _nmethod_count = count; } + int adapter_count() { return _adapter_count; } + void set_adapter_count(int count) { _adapter_count = count; } + int full_count() { return _full_count; } + void report_full() { _full_count++; } private: size_t heap_unallocated_capacity() const; diff -r 5646275e8053 -r 1f8d643b02d5 hotspot/src/share/vm/runtime/sweeper.cpp --- a/hotspot/src/share/vm/runtime/sweeper.cpp Fri Nov 06 15:07:00 2015 +0300 +++ b/hotspot/src/share/vm/runtime/sweeper.cpp Mon Nov 09 11:35:44 2015 +0100 @@ -297,7 +297,7 @@ void NMethodSweeper::handle_safepoint_request() { if (SafepointSynchronize::is_synchronizing()) { if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Sweep at %d out of %d, yielding to safepoint", _seen, CodeCache::nof_nmethods()); + tty->print_cr("### Sweep at %d out of %d, yielding to safepoint", _seen, CodeCache::nmethod_count()); } MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); @@ -401,7 +401,7 @@ int flushed_c2_count = 0; if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Sweep at %d out of %d", _seen, CodeCache::nof_nmethods()); + tty->print_cr("### Sweep at %d out of %d", _seen, CodeCache::nmethod_count()); } int swept_count = 0;