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
--- 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<CodeHeap*>* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (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());
}
--- 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;
+ }
};
--- 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);
}
--- 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;
--- 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;
--- 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;