8064892: Non-methods code cache overflow is not handled correctly
authorthartmann
Fri, 19 Aug 2016 08:34:30 +0200
changeset 40863 f5fec6a2dc9e
parent 40862 3f9cd7a4bfa7
child 40864 d13474bd52db
child 40865 a3eb5d10e7ea
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
hotspot/src/share/vm/code/codeCache.cpp
hotspot/src/share/vm/code/codeCache.hpp
--- 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)