src/hotspot/share/memory/metaspace/chunkManager.cpp
changeset 53970 1ad7c590a6e7
parent 50811 f533eb5e7430
child 54623 1126f0607c70
equal deleted inserted replaced
53969:b342deab639f 53970:1ad7c590a6e7
    27 #include "logging/logStream.hpp"
    27 #include "logging/logStream.hpp"
    28 #include "memory/binaryTreeDictionary.inline.hpp"
    28 #include "memory/binaryTreeDictionary.inline.hpp"
    29 #include "memory/freeList.inline.hpp"
    29 #include "memory/freeList.inline.hpp"
    30 #include "memory/metaspace/chunkManager.hpp"
    30 #include "memory/metaspace/chunkManager.hpp"
    31 #include "memory/metaspace/metachunk.hpp"
    31 #include "memory/metaspace/metachunk.hpp"
       
    32 #include "memory/metaspace/metaDebug.hpp"
    32 #include "memory/metaspace/metaspaceCommon.hpp"
    33 #include "memory/metaspace/metaspaceCommon.hpp"
    33 #include "memory/metaspace/metaspaceStatistics.hpp"
    34 #include "memory/metaspace/metaspaceStatistics.hpp"
    34 #include "memory/metaspace/occupancyMap.hpp"
    35 #include "memory/metaspace/occupancyMap.hpp"
    35 #include "memory/metaspace/virtualSpaceNode.hpp"
    36 #include "memory/metaspace/virtualSpaceNode.hpp"
    36 #include "runtime/mutexLocker.hpp"
    37 #include "runtime/mutexLocker.hpp"
   138   // And adjust ChunkManager:: _free_chunks_count (_free_chunks_total
   139   // And adjust ChunkManager:: _free_chunks_count (_free_chunks_total
   139   // should not have changed, because the size of the space should be the same)
   140   // should not have changed, because the size of the space should be the same)
   140   _free_chunks_count -= num_chunks_removed;
   141   _free_chunks_count -= num_chunks_removed;
   141   _free_chunks_count ++;
   142   _free_chunks_count ++;
   142 
   143 
   143   // VirtualSpaceNode::container_count does not have to be modified:
   144   // VirtualSpaceNode::chunk_count does not have to be modified:
   144   // it means "number of active (non-free) chunks", so merging free chunks
   145   // it means "number of active (non-free) chunks", so merging free chunks
   145   // should not affect that count.
   146   // should not affect that count.
   146 
   147 
   147   // At the end of a chunk merge, run verification tests.
   148   // At the end of a chunk merge, run verification tests.
   148   if (VerifyMetaspace) {
   149 #ifdef ASSERT
   149     DEBUG_ONLY(this->locked_verify());
   150 
   150     DEBUG_ONLY(vsn->verify());
   151   EVERY_NTH(VerifyMetaspaceInterval)
   151   }
   152     locked_verify(true);
       
   153     vsn->verify(true);
       
   154   END_EVERY_NTH
       
   155 
       
   156   g_internal_statistics.num_chunk_merges ++;
       
   157 
       
   158 #endif
   152 
   159 
   153   return true;
   160   return true;
   154 }
   161 }
   155 
   162 
   156 // Remove all chunks in the given area - the chunks are supposed to be free -
   163 // Remove all chunks in the given area - the chunks are supposed to be free -
   187     cur = next;
   194     cur = next;
   188   }
   195   }
   189   return num_removed;
   196   return num_removed;
   190 }
   197 }
   191 
   198 
   192 size_t ChunkManager::free_chunks_total_words() {
       
   193   return _free_chunks_total;
       
   194 }
       
   195 
       
   196 size_t ChunkManager::free_chunks_total_bytes() {
       
   197   return free_chunks_total_words() * BytesPerWord;
       
   198 }
       
   199 
       
   200 // Update internal accounting after a chunk was added
   199 // Update internal accounting after a chunk was added
   201 void ChunkManager::account_for_added_chunk(const Metachunk* c) {
   200 void ChunkManager::account_for_added_chunk(const Metachunk* c) {
   202   assert_lock_strong(MetaspaceExpand_lock);
   201   assert_lock_strong(MetaspaceExpand_lock);
   203   _free_chunks_count ++;
   202   _free_chunks_count ++;
   204   _free_chunks_total += c->word_size();
   203   _free_chunks_total += c->word_size();
   214      "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, c->word_size());
   213      "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, c->word_size());
   215   _free_chunks_count --;
   214   _free_chunks_count --;
   216   _free_chunks_total -= c->word_size();
   215   _free_chunks_total -= c->word_size();
   217 }
   216 }
   218 
   217 
   219 size_t ChunkManager::free_chunks_count() {
       
   220 #ifdef ASSERT
       
   221   if (!UseConcMarkSweepGC && !MetaspaceExpand_lock->is_locked()) {
       
   222     MutexLockerEx cl(MetaspaceExpand_lock,
       
   223                      Mutex::_no_safepoint_check_flag);
       
   224     // This lock is only needed in debug because the verification
       
   225     // of the _free_chunks_totals walks the list of free chunks
       
   226     slow_locked_verify_free_chunks_count();
       
   227   }
       
   228 #endif
       
   229   return _free_chunks_count;
       
   230 }
       
   231 
       
   232 ChunkIndex ChunkManager::list_index(size_t size) {
   218 ChunkIndex ChunkManager::list_index(size_t size) {
   233   return get_chunk_type_by_size(size, is_class());
   219   return get_chunk_type_by_size(size, is_class());
   234 }
   220 }
   235 
   221 
   236 size_t ChunkManager::size_by_index(ChunkIndex index) const {
   222 size_t ChunkManager::size_by_index(ChunkIndex index) const {
   237   index_bounds_check(index);
   223   index_bounds_check(index);
   238   assert(index != HumongousIndex, "Do not call for humongous chunks.");
   224   assert(index != HumongousIndex, "Do not call for humongous chunks.");
   239   return get_size_for_nonhumongous_chunktype(index, is_class());
   225   return get_size_for_nonhumongous_chunktype(index, is_class());
   240 }
   226 }
   241 
   227 
   242 void ChunkManager::locked_verify_free_chunks_total() {
   228 #ifdef ASSERT
   243   assert_lock_strong(MetaspaceExpand_lock);
   229 void ChunkManager::verify(bool slow) const {
   244   assert(sum_free_chunks() == _free_chunks_total,
       
   245          "_free_chunks_total " SIZE_FORMAT " is not the"
       
   246          " same as sum " SIZE_FORMAT, _free_chunks_total,
       
   247          sum_free_chunks());
       
   248 }
       
   249 
       
   250 void ChunkManager::locked_verify_free_chunks_count() {
       
   251   assert_lock_strong(MetaspaceExpand_lock);
       
   252   assert(sum_free_chunks_count() == _free_chunks_count,
       
   253          "_free_chunks_count " SIZE_FORMAT " is not the"
       
   254          " same as sum " SIZE_FORMAT, _free_chunks_count,
       
   255          sum_free_chunks_count());
       
   256 }
       
   257 
       
   258 void ChunkManager::verify() {
       
   259   MutexLockerEx cl(MetaspaceExpand_lock,
   230   MutexLockerEx cl(MetaspaceExpand_lock,
   260                      Mutex::_no_safepoint_check_flag);
   231                      Mutex::_no_safepoint_check_flag);
   261   locked_verify();
   232   locked_verify(slow);
   262 }
   233 }
   263 
   234 
   264 void ChunkManager::locked_verify() {
   235 void ChunkManager::locked_verify(bool slow) const {
   265   locked_verify_free_chunks_count();
   236   log_trace(gc, metaspace, freelist)("verifying %s chunkmanager (%s).",
   266   locked_verify_free_chunks_total();
   237     (is_class() ? "class space" : "metaspace"), (slow ? "slow" : "quick"));
       
   238 
       
   239   assert_lock_strong(MetaspaceExpand_lock);
       
   240 
       
   241   size_t chunks_counted = 0;
       
   242   size_t wordsize_chunks_counted = 0;
   267   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
   243   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
   268     ChunkList* list = free_chunks(i);
   244     const ChunkList* list = _free_chunks + i;
   269     if (list != NULL) {
   245     if (list != NULL) {
   270       Metachunk* chunk = list->head();
   246       Metachunk* chunk = list->head();
   271       while (chunk) {
   247       while (chunk) {
   272         DEBUG_ONLY(do_verify_chunk(chunk);)
   248         if (slow) {
       
   249           do_verify_chunk(chunk);
       
   250         }
   273         assert(chunk->is_tagged_free(), "Chunk should be tagged as free.");
   251         assert(chunk->is_tagged_free(), "Chunk should be tagged as free.");
       
   252         chunks_counted ++;
       
   253         wordsize_chunks_counted += chunk->size();
   274         chunk = chunk->next();
   254         chunk = chunk->next();
   275       }
   255       }
   276     }
   256     }
   277   }
   257   }
   278 }
   258 
       
   259   chunks_counted += humongous_dictionary()->total_free_blocks();
       
   260   wordsize_chunks_counted += humongous_dictionary()->total_size();
       
   261 
       
   262   assert(chunks_counted == _free_chunks_count && wordsize_chunks_counted == _free_chunks_total,
       
   263          "freelist accounting mismatch: "
       
   264          "we think: " SIZE_FORMAT " chunks, total " SIZE_FORMAT " words, "
       
   265          "reality: " SIZE_FORMAT " chunks, total " SIZE_FORMAT " words.",
       
   266          _free_chunks_count, _free_chunks_total,
       
   267          chunks_counted, wordsize_chunks_counted);
       
   268 }
       
   269 #endif // ASSERT
   279 
   270 
   280 void ChunkManager::locked_print_free_chunks(outputStream* st) {
   271 void ChunkManager::locked_print_free_chunks(outputStream* st) {
   281   assert_lock_strong(MetaspaceExpand_lock);
   272   assert_lock_strong(MetaspaceExpand_lock);
   282   st->print_cr("Free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
   273   st->print_cr("Free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
   283                 _free_chunks_total, _free_chunks_count);
   274                 _free_chunks_total, _free_chunks_count);
   284 }
       
   285 
       
   286 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) {
       
   287   assert_lock_strong(MetaspaceExpand_lock);
       
   288   st->print_cr("Sum free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
       
   289                 sum_free_chunks(), sum_free_chunks_count());
       
   290 }
   275 }
   291 
   276 
   292 ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
   277 ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
   293   assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex,
   278   assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex,
   294          "Bad index: %d", (int)index);
   279          "Bad index: %d", (int)index);
   295 
       
   296   return &_free_chunks[index];
   280   return &_free_chunks[index];
   297 }
       
   298 
       
   299 // These methods that sum the free chunk lists are used in printing
       
   300 // methods that are used in product builds.
       
   301 size_t ChunkManager::sum_free_chunks() {
       
   302   assert_lock_strong(MetaspaceExpand_lock);
       
   303   size_t result = 0;
       
   304   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
       
   305     ChunkList* list = free_chunks(i);
       
   306 
       
   307     if (list == NULL) {
       
   308       continue;
       
   309     }
       
   310 
       
   311     result = result + list->count() * list->size();
       
   312   }
       
   313   result = result + humongous_dictionary()->total_size();
       
   314   return result;
       
   315 }
       
   316 
       
   317 size_t ChunkManager::sum_free_chunks_count() {
       
   318   assert_lock_strong(MetaspaceExpand_lock);
       
   319   size_t count = 0;
       
   320   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
       
   321     ChunkList* list = free_chunks(i);
       
   322     if (list == NULL) {
       
   323       continue;
       
   324     }
       
   325     count = count + list->count();
       
   326   }
       
   327   count = count + humongous_dictionary()->total_free_blocks();
       
   328   return count;
       
   329 }
   281 }
   330 
   282 
   331 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) {
   283 ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) {
   332   ChunkIndex index = list_index(word_size);
   284   ChunkIndex index = list_index(word_size);
   333   assert(index < HumongousIndex, "No humongous list");
   285   assert(index < HumongousIndex, "No humongous list");
   425 
   377 
   426     p += this_chunk_word_size;
   378     p += this_chunk_word_size;
   427 
   379 
   428   }
   380   }
   429 
   381 
       
   382   // Note: at this point, the VirtualSpaceNode is invalid since we split a chunk and
       
   383   // did not yet hand out part of that split; so, vsn->verify_free_chunks_are_ideally_merged()
       
   384   // would assert. Instead, do all verifications in the caller.
       
   385 
       
   386   DEBUG_ONLY(g_internal_statistics.num_chunk_splits ++);
       
   387 
   430   return target_chunk;
   388   return target_chunk;
   431 }
   389 }
   432 
   390 
   433 Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
   391 Metachunk* ChunkManager::free_chunks_get(size_t word_size) {
   434   assert_lock_strong(MetaspaceExpand_lock);
   392   assert_lock_strong(MetaspaceExpand_lock);
   435 
       
   436   slow_locked_verify();
       
   437 
   393 
   438   Metachunk* chunk = NULL;
   394   Metachunk* chunk = NULL;
   439   bool we_did_split_a_chunk = false;
   395   bool we_did_split_a_chunk = false;
   440 
   396 
   441   if (list_index(word_size) != HumongousIndex) {
   397   if (list_index(word_size) != HumongousIndex) {
   522   chunk->set_next(NULL);
   478   chunk->set_next(NULL);
   523   chunk->set_prev(NULL);
   479   chunk->set_prev(NULL);
   524 
   480 
   525   // Run some verifications (some more if we did a chunk split)
   481   // Run some verifications (some more if we did a chunk split)
   526 #ifdef ASSERT
   482 #ifdef ASSERT
   527   if (VerifyMetaspace) {
   483 
   528     locked_verify();
   484   EVERY_NTH(VerifyMetaspaceInterval)
       
   485     // Be extra verify-y when chunk split happened.
       
   486     locked_verify(true);
   529     VirtualSpaceNode* const vsn = chunk->container();
   487     VirtualSpaceNode* const vsn = chunk->container();
   530     vsn->verify();
   488     vsn->verify(true);
   531     if (we_did_split_a_chunk) {
   489     if (we_did_split_a_chunk) {
   532       vsn->verify_free_chunks_are_ideally_merged();
   490       vsn->verify_free_chunks_are_ideally_merged();
   533     }
   491     }
   534   }
   492   END_EVERY_NTH
       
   493 
       
   494   g_internal_statistics.num_chunks_removed_from_freelist ++;
       
   495 
   535 #endif
   496 #endif
   536 
   497 
   537   return chunk;
   498   return chunk;
   538 }
   499 }
   539 
   500 
   540 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
   501 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
   541   assert_lock_strong(MetaspaceExpand_lock);
   502   assert_lock_strong(MetaspaceExpand_lock);
   542   slow_locked_verify();
       
   543 
   503 
   544   // Take from the beginning of the list
   504   // Take from the beginning of the list
   545   Metachunk* chunk = free_chunks_get(word_size);
   505   Metachunk* chunk = free_chunks_get(word_size);
   546   if (chunk == NULL) {
   506   if (chunk == NULL) {
   547     return NULL;
   507     return NULL;
   568 
   528 
   569   return chunk;
   529   return chunk;
   570 }
   530 }
   571 
   531 
   572 void ChunkManager::return_single_chunk(Metachunk* chunk) {
   532 void ChunkManager::return_single_chunk(Metachunk* chunk) {
       
   533 
       
   534 #ifdef ASSERT
       
   535   EVERY_NTH(VerifyMetaspaceInterval)
       
   536     this->locked_verify(false);
       
   537     do_verify_chunk(chunk);
       
   538   END_EVERY_NTH
       
   539 #endif
       
   540 
   573   const ChunkIndex index = chunk->get_chunk_type();
   541   const ChunkIndex index = chunk->get_chunk_type();
   574   assert_lock_strong(MetaspaceExpand_lock);
   542   assert_lock_strong(MetaspaceExpand_lock);
   575   DEBUG_ONLY(do_verify_chunk(chunk);)
   543   DEBUG_ONLY(g_internal_statistics.num_chunks_added_to_freelist ++;)
   576   assert(chunk != NULL, "Expected chunk.");
   544   assert(chunk != NULL, "Expected chunk.");
   577   assert(chunk->container() != NULL, "Container should have been set.");
   545   assert(chunk->container() != NULL, "Container should have been set.");
   578   assert(chunk->is_tagged_free() == false, "Chunk should be in use.");
   546   assert(chunk->is_tagged_free() == false, "Chunk should be in use.");
   579   index_bounds_check(index);
   547   index_bounds_check(index);
   580 
   548 
   581   // Note: mangle *before* returning the chunk to the freelist or dictionary. It does not
   549   // Note: mangle *before* returning the chunk to the freelist or dictionary. It does not
   582   // matter for the freelist (non-humongous chunks), but the humongous chunk dictionary
   550   // matter for the freelist (non-humongous chunks), but the humongous chunk dictionary
   583   // keeps tree node pointers in the chunk payload area which mangle will overwrite.
   551   // keeps tree node pointers in the chunk payload area which mangle will overwrite.
   584   DEBUG_ONLY(chunk->mangle(badMetaWordVal);)
   552   DEBUG_ONLY(chunk->mangle(badMetaWordVal);)
       
   553 
       
   554   // may need node for verification later after chunk may have been merged away.
       
   555   DEBUG_ONLY(VirtualSpaceNode* vsn = chunk->container(); )
   585 
   556 
   586   if (index != HumongousIndex) {
   557   if (index != HumongousIndex) {
   587     // Return non-humongous chunk to freelist.
   558     // Return non-humongous chunk to freelist.
   588     ChunkList* list = free_chunks(index);
   559     ChunkList* list = free_chunks(index);
   589     assert(list->size() == chunk->word_size(), "Wrong chunk type.");
   560     assert(list->size() == chunk->word_size(), "Wrong chunk type.");
   616         }
   587         }
   617       }
   588       }
   618     }
   589     }
   619   }
   590   }
   620 
   591 
       
   592   // From here on do not access chunk anymore, it may have been merged with another chunk.
       
   593 
       
   594 #ifdef ASSERT
       
   595   EVERY_NTH(VerifyMetaspaceInterval)
       
   596     this->locked_verify(true);
       
   597     vsn->verify(true);
       
   598     vsn->verify_free_chunks_are_ideally_merged();
       
   599   END_EVERY_NTH
       
   600 #endif
       
   601 
   621 }
   602 }
   622 
   603 
   623 void ChunkManager::return_chunk_list(Metachunk* chunks) {
   604 void ChunkManager::return_chunk_list(Metachunk* chunks) {
   624   if (chunks == NULL) {
   605   if (chunks == NULL) {
   625     return;
   606     return;