8064892: Non-methods code cache overflow is not handled correctly

Should keep track of requested code blob type for error reporting. Added additional debug output.

Reviewed-by: kvn, dpochepk
This commit is contained in:
Tobias Hartmann 2016-08-19 08:34:30 +02:00
parent c6d82df571
commit ebb0356d35
2 changed files with 21 additions and 12 deletions

View File

@ -437,7 +437,7 @@ CodeBlob* CodeCache::next_blob(CodeBlob* cb) {
* 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 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) {
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) {

View File

@ -126,7 +126,7 @@ class CodeCache : AllStatic {
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)