8170520: Make Metaspace ChunkManager counters non-atomic
authorstuefe
Fri, 17 Mar 2017 19:05:45 +0100
changeset 46360 c753322134b0
parent 46359 76dd8f312458
child 46361 b4c026dd6128
child 46362 974737822190
8170520: Make Metaspace ChunkManager counters non-atomic Reviewed-by: mgerdin, coleenp
hotspot/src/share/vm/memory/metaspace.cpp
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Mon Nov 07 10:22:03 2016 +0100
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Fri Mar 17 19:05:45 2017 +0100
@@ -134,20 +134,14 @@
     return &_humongous_dictionary;
   }
 
-  // ChunkManager in all lists of this type
+  // Size, in metaspace words, of all chunks managed by this ChunkManager
   size_t _free_chunks_total;
+  // Number of chunks in this ChunkManager
   size_t _free_chunks_count;
 
-  void dec_free_chunks_total(size_t v) {
-    assert(_free_chunks_count > 0,
-      "ChunkManager::_free_chunks_count: about to go negative (" SIZE_FORMAT ").", _free_chunks_count);
-    assert(_free_chunks_total >= v,
-      "ChunkManager::_free_chunks_total: about to go negative"
-       "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, v);
-    Atomic::add_ptr(-1, &_free_chunks_count);
-    jlong minus_v = (jlong) - (jlong) v;
-    Atomic::add_ptr(minus_v, &_free_chunks_total);
-  }
+  // Update counters after a chunk was added or removed removed.
+  void account_for_added_chunk(const Metachunk* c);
+  void account_for_removed_chunk(const Metachunk* c);
 
   // Debug support
 
@@ -206,11 +200,6 @@
   // Number of chunks in the free chunks list
   size_t free_chunks_count();
 
-  void inc_free_chunks_total(size_t v, size_t count = 1) {
-    Atomic::add_ptr(count, &_free_chunks_count);
-    Atomic::add_ptr(v, &_free_chunks_total);
-  }
-
   // Remove from a list by size.  Selects list based on size of chunk.
   Metachunk* free_chunks_get(size_t chunk_word_size);
 
@@ -1186,8 +1175,8 @@
     humongous_dictionary()->remove_chunk(chunk);
   }
 
-  // Chunk is being removed from the chunks free list.
-  dec_free_chunks_total(chunk->word_size());
+  // Chunk has been removed from the chunks free list, update counters.
+  account_for_removed_chunk(chunk);
 }
 
 // Walk the list of VirtualSpaceNodes and delete
@@ -1278,7 +1267,6 @@
       assert(chunk != NULL, "allocation should have been successful");
 
       chunk_manager->return_single_chunk(index, chunk);
-      chunk_manager->inc_free_chunks_total(chunk_size);
     }
     DEBUG_ONLY(verify_container_count();)
   }
@@ -1755,6 +1743,25 @@
   return free_chunks_total_words() * BytesPerWord;
 }
 
+// Update internal accounting after a chunk was added
+void ChunkManager::account_for_added_chunk(const Metachunk* c) {
+  assert_lock_strong(SpaceManager::expand_lock());
+  _free_chunks_count ++;
+  _free_chunks_total += c->word_size();
+}
+
+// Update internal accounting after a chunk was removed
+void ChunkManager::account_for_removed_chunk(const Metachunk* c) {
+  assert_lock_strong(SpaceManager::expand_lock());
+  assert(_free_chunks_count >= 1,
+    "ChunkManager::_free_chunks_count: about to go negative (" SIZE_FORMAT ").", _free_chunks_count);
+  assert(_free_chunks_total >= c->word_size(),
+    "ChunkManager::_free_chunks_total: about to go negative"
+     "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, c->word_size());
+  _free_chunks_count --;
+  _free_chunks_total -= c->word_size();
+}
+
 size_t ChunkManager::free_chunks_count() {
 #ifdef ASSERT
   if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) {
@@ -1922,8 +1929,8 @@
                                     chunk->word_size(), word_size, chunk->word_size() - word_size);
   }
 
-  // Chunk is being removed from the chunks free list.
-  dec_free_chunks_total(chunk->word_size());
+  // Chunk has been removed from the chunk manager; update counters.
+  account_for_removed_chunk(chunk);
 
   // Remove it from the links to this freelist
   chunk->set_next(NULL);
@@ -2001,6 +2008,9 @@
   chunk->container()->dec_container_count();
   DEBUG_ONLY(chunk->set_is_tagged_free(true);)
 
+  // Chunk has been added; update counters.
+  account_for_added_chunk(chunk);
+
 }
 
 void ChunkManager::return_chunk_list(ChunkIndex index, Metachunk* chunks) {
@@ -2394,11 +2404,6 @@
   }
   }
 
-  // Have to update before the chunks_in_use lists are emptied
-  // below.
-  chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
-                                         sum_count_in_chunks_in_use());
-
   // Add all the chunks in use by this space manager
   // to the global list of free chunks.
 
@@ -4251,10 +4256,6 @@
     _cm.return_single_chunk(_cm.list_index(c->word_size()), c);
     _chunks_in_chunkmanager ++;
     _words_in_chunkmanager += c->word_size();
-    // (Note: until 8170520 is fixed, internal ChunkManager counters have to be updated
-    // by the caller - but only when returning chunks, ChunkManager->remove_chunk()
-    // already updates the counter.)
-    _cm.inc_free_chunks_total(c->word_size(), 1);
     assert(c->is_tagged_free() == true, "wrong chunk information");
     assert_counters();
     _cm.locked_verify();
@@ -4277,10 +4278,6 @@
     _cm.return_chunk_list(aChunkList.index, aChunkList.head);
     _chunks_in_chunkmanager += aChunkList.num;
     _words_in_chunkmanager += aChunkList.size;
-    // (Note: until 8170520 is fixed, internal ChunkManager counters have to be updated
-    // by the caller - but only when returning chunks, ChunkManager->remove_chunk()
-    // already updates the counter.)
-    _cm.inc_free_chunks_total(aChunkList.size, aChunkList.num);
     // After all chunks are returned, check that they are now tagged free.
     for (int i = 0; i < aChunkList.num; i ++) {
       assert(aChunkList.all[i]->is_tagged_free(), "chunk state mismatch.");