hotspot/src/share/vm/code/codeCache.cpp
changeset 42650 1f304d0c888b
parent 42062 473286891dd8
child 43407 f6dc40ed6ce9
child 46269 7e725659ea12
--- a/hotspot/src/share/vm/code/codeCache.cpp	Sun Dec 11 12:05:57 2016 -0800
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Sun Dec 11 19:07:04 2016 -0800
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "aot/aotLoader.hpp"
 #include "code/codeBlob.hpp"
 #include "code/codeCache.hpp"
 #include "code/compiledIC.hpp"
@@ -128,6 +129,8 @@
 
 // Iterate over all CodeHeaps
 #define FOR_ALL_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _heaps->begin(); heap != _heaps->end(); ++heap)
+#define FOR_ALL_NMETHOD_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _nmethod_heaps->begin(); heap != _nmethod_heaps->end(); ++heap)
+
 // Iterate over all CodeBlobs (cb) on the given CodeHeap
 #define FOR_ALL_BLOBS(cb, heap) for (CodeBlob* cb = first_blob(heap); cb != NULL; cb = next_blob(heap, cb))
 
@@ -139,6 +142,8 @@
 
 // Initialize array of CodeHeaps
 GrowableArray<CodeHeap*>* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+GrowableArray<CodeHeap*>* CodeCache::_compiled_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+GrowableArray<CodeHeap*>* CodeCache::_nmethod_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
 
 void CodeCache::check_heap_sizes(size_t non_nmethod_size, size_t profiled_size, size_t non_profiled_size, size_t cache_size, bool all_set) {
   size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
@@ -365,6 +370,28 @@
   return NULL;
 }
 
+int CodeCache::code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs) {
+  if (lhs->code_blob_type() == rhs->code_blob_type()) {
+    return (lhs > rhs) ? 1 : ((lhs < rhs) ? -1 : 0);
+  } else {
+    return lhs->code_blob_type() - rhs->code_blob_type();
+  }
+}
+
+void CodeCache::add_heap(CodeHeap* heap) {
+  assert(!Universe::is_fully_initialized(), "late heap addition?");
+
+  _heaps->insert_sorted<code_heap_compare>(heap);
+
+  int type = heap->code_blob_type();
+  if (code_blob_type_accepts_compiled(type)) {
+    _compiled_heaps->insert_sorted<code_heap_compare>(heap);
+  }
+  if (code_blob_type_accepts_nmethod(type)) {
+    _nmethod_heaps->insert_sorted<code_heap_compare>(heap);
+  }
+}
+
 void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) {
   // Check if heap is needed
   if (!heap_available(code_blob_type)) {
@@ -373,7 +400,7 @@
 
   // Create CodeHeap
   CodeHeap* heap = new CodeHeap(name, code_blob_type);
-  _heaps->append(heap);
+  add_heap(heap);
 
   // Reserve Space
   size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
@@ -389,7 +416,7 @@
 CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
   assert(cb != NULL, "CodeBlob is null");
   FOR_ALL_HEAPS(heap) {
-    if ((*heap)->contains(cb)) {
+    if ((*heap)->contains(cb->code_begin())) {
       return *heap;
     }
   }
@@ -426,10 +453,6 @@
   return (CodeBlob*)heap->next(cb);
 }
 
-CodeBlob* CodeCache::next_blob(CodeBlob* cb) {
-  return next_blob(get_code_heap(cb), cb);
-}
-
 /**
  * Do not seize the CodeCache lock here--if the caller has not
  * already done so, we are going to lose bigtime, since the code
@@ -494,7 +517,7 @@
     }
     if (PrintCodeCacheExtension) {
       ResourceMark rm;
-      if (_heaps->length() >= 1) {
+      if (_nmethod_heaps->length() >= 1) {
         tty->print("%s", heap->name());
       } else {
         tty->print("CodeCache");
@@ -559,6 +582,10 @@
   return false;
 }
 
+bool CodeCache::contains(nmethod *nm) {
+  return contains((void *)nm);
+}
+
 // This method is safe to call without holding the CodeCache_lock, as long as a dead CodeBlob is not
 // looked up (i.e., one that has been marked for deletion). It only depends on the _segmap to contain
 // valid indices, which it will always do, as long as the CodeBlob is not in the process of being recycled.
@@ -575,8 +602,8 @@
   // NMT can walk the stack before code cache is created
   if (_heaps != NULL && !_heaps->is_empty()) {
     FOR_ALL_HEAPS(heap) {
-      CodeBlob* result = (CodeBlob*) (*heap)->find_start(start);
-      if (result != NULL && result->blob_contains((address)start)) {
+      CodeBlob* result = (*heap)->find_blob_unsafe(start);
+      if (result != NULL) {
         return result;
       }
     }
@@ -592,7 +619,7 @@
 
 void CodeCache::blobs_do(void f(CodeBlob* nm)) {
   assert_locked_or_safepoint(CodeCache_lock);
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       f(cb);
     }
@@ -613,6 +640,7 @@
   while(iter.next_alive()) {
     iter.method()->metadata_do(f);
   }
+  AOTLoader::metadata_do(f);
 }
 
 int CodeCache::alignment_unit() {
@@ -634,11 +662,10 @@
 
 void CodeCache::blobs_do(CodeBlobClosure* f) {
   assert_locked_or_safepoint(CodeCache_lock);
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       if (cb->is_alive()) {
         f->do_code_blob(cb);
-
 #ifdef ASSERT
         if (cb->is_nmethod())
         ((nmethod*)cb)->verify_scavenge_root_oops();
@@ -835,13 +862,12 @@
   int count = 0;
   FOR_ALL_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
-      if (cb->is_nmethod()) {
-        nmethod* nm = (nmethod*)cb;
+      CompiledMethod *nm = cb->as_compiled_method_or_null();
+      if (nm != NULL) {
         count += nm->verify_icholder_relocations();
       }
     }
   }
-
   assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
          CompiledICHolder::live_count(), "must agree");
 #endif
@@ -902,7 +928,7 @@
 
 int CodeCache::nmethod_count() {
   int count = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     count += (*heap)->nmethod_count();
   }
   return count;
@@ -933,7 +959,7 @@
 
 size_t CodeCache::capacity() {
   size_t cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     cap += (*heap)->capacity();
   }
   return cap;
@@ -946,7 +972,7 @@
 
 size_t CodeCache::unallocated_capacity() {
   size_t unallocated_cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     unallocated_cap += (*heap)->unallocated_capacity();
   }
   return unallocated_cap;
@@ -954,7 +980,7 @@
 
 size_t CodeCache::max_capacity() {
   size_t max_cap = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     max_cap += (*heap)->max_capacity();
   }
   return max_cap;
@@ -980,7 +1006,7 @@
 
 size_t CodeCache::bytes_allocated_in_freelists() {
   size_t allocated_bytes = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     allocated_bytes += (*heap)->allocated_in_freelist();
   }
   return allocated_bytes;
@@ -988,7 +1014,7 @@
 
 int CodeCache::allocated_segments() {
   int number_of_segments = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     number_of_segments += (*heap)->allocated_segments();
   }
   return number_of_segments;
@@ -996,7 +1022,7 @@
 
 size_t CodeCache::freelists_length() {
   size_t length = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     length += (*heap)->freelist_length();
   }
   return length;
@@ -1039,6 +1065,8 @@
 
 void codeCache_init() {
   CodeCache::initialize();
+  // Load AOT libraries and add AOT code heaps.
+  AOTLoader::initialize();
 }
 
 //------------------------------------------------------------------------------------------------
@@ -1102,6 +1130,15 @@
   return (CompiledMethod*)cb;
 }
 
+bool CodeCache::is_far_target(address target) {
+#if INCLUDE_AOT
+  return NativeCall::is_far_call(_low_bound,  target) ||
+         NativeCall::is_far_call(_high_bound, target);
+#else
+  return false;
+#endif
+}
+
 #ifdef HOTSWAP
 int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -1204,7 +1241,7 @@
 void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
   // --- Compile_lock is not held. However we are at a safepoint.
   assert_locked_or_safepoint(Compile_lock);
-  if (number_of_nmethods_with_dependencies() == 0) return;
+  if (number_of_nmethods_with_dependencies() == 0 && !UseAOT) return;
 
   // CodeCache can only be updated by a thread_in_VM and they will all be
   // stopped during the safepoint so CodeCache will be safe to update without
@@ -1316,7 +1353,7 @@
 
 void CodeCache::print_memory_overhead() {
   size_t wasted_bytes = 0;
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
       CodeHeap* curr_heap = *heap;
       for (CodeBlob* cb = (CodeBlob*)curr_heap->first(); cb != NULL; cb = (CodeBlob*)curr_heap->next(cb)) {
         HeapBlock* heap_block = ((HeapBlock*)cb) - 1;
@@ -1362,8 +1399,8 @@
   ResourceMark rm;
 
   int i = 0;
-  FOR_ALL_HEAPS(heap) {
-    if ((_heaps->length() >= 1) && Verbose) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
+    if ((_nmethod_heaps->length() >= 1) && Verbose) {
       tty->print_cr("-- %s --", (*heap)->name());
     }
     FOR_ALL_BLOBS(cb, *heap) {
@@ -1459,7 +1496,7 @@
   CodeBlob_sizes live;
   CodeBlob_sizes dead;
 
-  FOR_ALL_HEAPS(heap) {
+  FOR_ALL_NMETHOD_HEAPS(heap) {
     FOR_ALL_BLOBS(cb, *heap) {
       if (!cb->is_alive()) {
         dead.add(cb);
@@ -1485,7 +1522,7 @@
     int number_of_blobs = 0;
     int number_of_oop_maps = 0;
     int map_size = 0;
-    FOR_ALL_HEAPS(heap) {
+    FOR_ALL_NMETHOD_HEAPS(heap) {
       FOR_ALL_BLOBS(cb, *heap) {
         if (cb->is_alive()) {
           number_of_blobs++;
@@ -1568,35 +1605,3 @@
             unallocated_capacity());
 }
 
-// Initialize iterator to given compiled method
-void CompiledMethodIterator::initialize(CompiledMethod* cm) {
-  _code_blob = (CodeBlob*)cm;
-  if (!SegmentedCodeCache) {
-    // Iterate over all CodeBlobs
-    _code_blob_type = CodeBlobType::All;
-  } else if (cm != NULL) {
-    _code_blob_type = CodeCache::get_code_blob_type(cm);
-  } else {
-    // Only iterate over method code heaps, starting with non-profiled
-    _code_blob_type = CodeBlobType::MethodNonProfiled;
-  }
-}
-
-// Advance iterator to the next compiled method in the current code heap
-bool CompiledMethodIterator::next_compiled_method() {
-  // Get first method CodeBlob
-  if (_code_blob == NULL) {
-    _code_blob = CodeCache::first_blob(_code_blob_type);
-    if (_code_blob == NULL) {
-      return false;
-    } else if (_code_blob->is_nmethod()) {
-      return true;
-    }
-  }
-  // Search for next method CodeBlob
-  _code_blob = CodeCache::next_blob(_code_blob);
-  while (_code_blob != NULL && !_code_blob->is_compiled()) {
-    _code_blob = CodeCache::next_blob(_code_blob);
-  }
-  return _code_blob != NULL;
-}