8064892: Non-methods code cache overflow is not handled correctly
Summary: Should keep track of requested code blob type for error reporting. Added additional debug output.
Reviewed-by: kvn, dpochepk
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Aug 18 14:31:02 2016 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp Fri Aug 19 08:34:30 2016 +0200
@@ -437,7 +437,7 @@
* run the constructor for the CodeBlob subclass he is busy
* instantiating.
*/
-CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) {
+CodeBlob* CodeCache::allocate(int size, int code_blob_type, int orig_code_blob_type) {
// Possibly wakes up the sweeper thread.
NMethodSweeper::notify(code_blob_type);
assert_locked_or_safepoint(CodeCache_lock);
@@ -455,32 +455,41 @@
cb = (CodeBlob*)heap->allocate(size);
if (cb != NULL) break;
if (!heap->expand_by(CodeCacheExpansionSize)) {
+ // Save original type for error reporting
+ if (orig_code_blob_type == CodeBlobType::All) {
+ orig_code_blob_type = code_blob_type;
+ }
// Expansion failed
- if (SegmentedCodeCache && !strict) {
+ if (SegmentedCodeCache) {
// Fallback solution: Try to store code in another code heap.
+ // NonNMethod -> MethodNonProfiled -> MethodProfiled (-> MethodNonProfiled)
// Note that in the sweeper, we check the reverse_free_ratio of the code heap
// and force stack scanning if less than 10% of the code heap are free.
int type = code_blob_type;
switch (type) {
case CodeBlobType::NonNMethod:
type = CodeBlobType::MethodNonProfiled;
- strict = false; // Allow recursive search for other heaps
- break;
- case CodeBlobType::MethodProfiled:
- type = CodeBlobType::MethodNonProfiled;
- strict = true;
break;
case CodeBlobType::MethodNonProfiled:
type = CodeBlobType::MethodProfiled;
- strict = true;
+ break;
+ case CodeBlobType::MethodProfiled:
+ // Avoid loop if we already tried that code heap
+ if (type == orig_code_blob_type) {
+ type = CodeBlobType::MethodNonProfiled;
+ }
break;
}
- if (heap_available(type)) {
- return allocate(size, type, strict);
+ if (type != code_blob_type && type != orig_code_blob_type && heap_available(type)) {
+ if (PrintCodeCacheExtension) {
+ tty->print_cr("Extension of %s failed. Trying to allocate in %s.",
+ heap->name(), get_code_heap(type)->name());
+ }
+ return allocate(size, type, orig_code_blob_type);
}
}
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- CompileBroker::handle_full_code_cache(code_blob_type);
+ CompileBroker::handle_full_code_cache(orig_code_blob_type);
return NULL;
}
if (PrintCodeCacheExtension) {
--- a/hotspot/src/share/vm/code/codeCache.hpp Thu Aug 18 14:31:02 2016 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp Fri Aug 19 08:34:30 2016 +0200
@@ -126,7 +126,7 @@
static void initialize();
// Allocation/administration
- static CodeBlob* allocate(int size, int code_blob_type, bool strict = false); // allocates a new CodeBlob
+ static CodeBlob* allocate(int size, int code_blob_type, int orig_code_blob_type = CodeBlobType::All); // allocates a new CodeBlob
static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled
static int alignment_unit(); // guaranteed alignment of all CodeBlobs
static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)