< prev index next >

src/share/vm/memory/metaspace.cpp

Print this page




  94 typedef class FreeList<Metachunk> ChunkList;
  95 
  96 // Manages the global free lists of chunks.
  97 class ChunkManager : public CHeapObj<mtInternal> {
  98   friend class TestVirtualSpaceNodeTest;
  99 
 100   // Free list of chunks of different sizes.
 101   //   SpecializedChunk
 102   //   SmallChunk
 103   //   MediumChunk
 104   //   HumongousChunk
 105   ChunkList _free_chunks[NumberOfFreeLists];
 106 
 107   //   HumongousChunk
 108   ChunkTreeDictionary _humongous_dictionary;
 109 
 110   // ChunkManager in all lists of this type
 111   size_t _free_chunks_total;
 112   size_t _free_chunks_count;
 113 



 114   void dec_free_chunks_total(size_t v) {
 115     assert(_free_chunks_count > 0 &&
 116              _free_chunks_total > 0,
 117              "About to go negative");
 118     Atomic::add_ptr(-1, &_free_chunks_count);
 119     jlong minus_v = (jlong) - (jlong) v;
 120     Atomic::add_ptr(minus_v, &_free_chunks_total);
 121   }
 122 
 123   // Debug support
 124 
 125   size_t sum_free_chunks();
 126   size_t sum_free_chunks_count();
 127 
 128   void locked_verify_free_chunks_total();
 129   void slow_locked_verify_free_chunks_total() {
 130     if (metaspace_slow_verify) {
 131       locked_verify_free_chunks_total();
 132     }
 133   }


 136     if (metaspace_slow_verify) {
 137       locked_verify_free_chunks_count();
 138     }
 139   }
 140   void verify_free_chunks_count();
 141 
 142  public:
 143 
 144   ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
 145       : _free_chunks_total(0), _free_chunks_count(0) {
 146     _free_chunks[SpecializedIndex].set_size(specialized_size);
 147     _free_chunks[SmallIndex].set_size(small_size);
 148     _free_chunks[MediumIndex].set_size(medium_size);
 149   }
 150 
 151   // add or delete (return) a chunk to the global freelist.
 152   Metachunk* chunk_freelist_allocate(size_t word_size);
 153 
 154   // Map a size to a list index assuming that there are lists
 155   // for special, small, medium, and humongous chunks.
 156   static ChunkIndex list_index(size_t size);
 157 
 158   // Remove the chunk from its freelist.  It is
 159   // expected to be on one of the _free_chunks[] lists.
 160   void remove_chunk(Metachunk* chunk);
 161 
 162   // Add the simple linked list of chunks to the freelist of chunks
 163   // of type index.
 164   void return_chunks(ChunkIndex index, Metachunk* chunks);
 165 
 166   // Total of the space in the free chunks list
 167   size_t free_chunks_total_words();
 168   size_t free_chunks_total_bytes();
 169 
 170   // Number of chunks in the free chunks list
 171   size_t free_chunks_count();
 172 
 173   void inc_free_chunks_total(size_t v, size_t count = 1) {
 174     Atomic::add_ptr(count, &_free_chunks_count);
 175     Atomic::add_ptr(v, &_free_chunks_total);
 176   }


 232   void verify();
 233   void slow_verify() {
 234     if (metaspace_slow_verify) {
 235       verify();
 236     }
 237   }
 238   void locked_verify();
 239   void slow_locked_verify() {
 240     if (metaspace_slow_verify) {
 241       locked_verify();
 242     }
 243   }
 244   void verify_free_chunks_total();
 245 
 246   void locked_print_free_chunks(outputStream* st);
 247   void locked_print_sum_free_chunks(outputStream* st);
 248 
 249   void print_on(outputStream* st) const;
 250 };
 251 


































 252 class SmallBlocks : public CHeapObj<mtClass> {
 253   const static uint _small_block_max_size = sizeof(TreeChunk<Metablock,  FreeList<Metablock> >)/HeapWordSize;
 254   const static uint _small_block_min_size = sizeof(Metablock)/HeapWordSize;
 255 
 256  private:
 257   FreeList<Metablock> _small_lists[_small_block_max_size - _small_block_min_size];
 258 
 259   FreeList<Metablock>& list_at(size_t word_size) {
 260     assert(word_size >= _small_block_min_size, "There are no metaspace objects less than %u words", _small_block_min_size);
 261     return _small_lists[word_size - _small_block_min_size];
 262   }
 263 
 264  public:
 265   SmallBlocks() {
 266     for (uint i = _small_block_min_size; i < _small_block_max_size; i++) {
 267       uint k = i - _small_block_min_size;
 268       _small_lists[k].set_size(i);
 269     }
 270   }
 271 


2320   if (_block_freelists != NULL) {
2321     delete _block_freelists;
2322   }
2323 }
2324 
2325 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
2326   switch (index) {
2327     case SpecializedIndex:
2328       return "Specialized";
2329     case SmallIndex:
2330       return "Small";
2331     case MediumIndex:
2332       return "Medium";
2333     case HumongousIndex:
2334       return "Humongous";
2335     default:
2336       return NULL;
2337   }
2338 }
2339 
2340 ChunkIndex ChunkManager::list_index(size_t size) {
2341   switch (size) {
2342     case SpecializedChunk:
2343       assert(SpecializedChunk == ClassSpecializedChunk,
2344              "Need branch for ClassSpecializedChunk");




2345       return SpecializedIndex;
2346     case SmallChunk:
2347     case ClassSmallChunk:
2348       return SmallIndex;
2349     case MediumChunk:
2350     case ClassMediumChunk:
2351       return MediumIndex;
2352     default:
2353       assert(size > MediumChunk || size > ClassMediumChunk,
2354              "Not a humongous chunk");
2355       return HumongousIndex;
2356   }



2357 }
2358 
2359 void SpaceManager::deallocate(MetaWord* p, size_t word_size) {
2360   assert_lock_strong(_lock);
2361   // Allocations and deallocations are in raw_word_size
2362   size_t raw_word_size = get_allocation_word_size(word_size);
2363   // Lazily create a block_freelist
2364   if (block_freelists() == NULL) {
2365     _block_freelists = new BlockFreelist();
2366   }
2367   block_freelists()->return_block(p, raw_word_size);
2368 }
2369 
2370 // Adds a chunk to the list of chunks in use.
2371 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
2372 
2373   assert(new_chunk != NULL, "Should not be NULL");
2374   assert(new_chunk->next() == NULL, "Should not be on a list");
2375 
2376   new_chunk->reset_empty();
2377 
2378   // Find the correct list and and set the current
2379   // chunk for that list.
2380   ChunkIndex index = ChunkManager::list_index(new_chunk->word_size());
2381 
2382   if (index != HumongousIndex) {
2383     retire_current_chunk();
2384     set_current_chunk(new_chunk);
2385     new_chunk->set_next(chunks_in_use(index));
2386     set_chunks_in_use(index, new_chunk);
2387   } else {
2388     // For null class loader data and DumpSharedSpaces, the first chunk isn't
2389     // small, so small will be null.  Link this first chunk as the current
2390     // chunk.
2391     if (make_current) {
2392       // Set as the current chunk but otherwise treat as a humongous chunk.
2393       set_current_chunk(new_chunk);
2394     }
2395     // Link at head.  The _current_chunk only points to a humongous chunk for
2396     // the null class loader metaspace (class and data virtual space managers)
2397     // any humongous chunks so will not point to the tail
2398     // of the humongous chunks list.
2399     new_chunk->set_next(chunks_in_use(HumongousIndex));
2400     set_chunks_in_use(HumongousIndex, new_chunk);




  94 typedef class FreeList<Metachunk> ChunkList;
  95 
  96 // Manages the global free lists of chunks.
  97 class ChunkManager : public CHeapObj<mtInternal> {
  98   friend class TestVirtualSpaceNodeTest;
  99 
 100   // Free list of chunks of different sizes.
 101   //   SpecializedChunk
 102   //   SmallChunk
 103   //   MediumChunk
 104   //   HumongousChunk
 105   ChunkList _free_chunks[NumberOfFreeLists];
 106 
 107   //   HumongousChunk
 108   ChunkTreeDictionary _humongous_dictionary;
 109 
 110   // ChunkManager in all lists of this type
 111   size_t _free_chunks_total;
 112   size_t _free_chunks_count;
 113 
 114   // Return the fixed chunk size for the given list index
 115   size_t list_chunk_size(ChunkIndex index) const;
 116 
 117   void dec_free_chunks_total(size_t v) {
 118     assert(_free_chunks_count > 0 &&
 119              _free_chunks_total > 0,
 120              "About to go negative");
 121     Atomic::add_ptr(-1, &_free_chunks_count);
 122     jlong minus_v = (jlong) - (jlong) v;
 123     Atomic::add_ptr(minus_v, &_free_chunks_total);
 124   }
 125 
 126   // Debug support
 127 
 128   size_t sum_free_chunks();
 129   size_t sum_free_chunks_count();
 130 
 131   void locked_verify_free_chunks_total();
 132   void slow_locked_verify_free_chunks_total() {
 133     if (metaspace_slow_verify) {
 134       locked_verify_free_chunks_total();
 135     }
 136   }


 139     if (metaspace_slow_verify) {
 140       locked_verify_free_chunks_count();
 141     }
 142   }
 143   void verify_free_chunks_count();
 144 
 145  public:
 146 
 147   ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size)
 148       : _free_chunks_total(0), _free_chunks_count(0) {
 149     _free_chunks[SpecializedIndex].set_size(specialized_size);
 150     _free_chunks[SmallIndex].set_size(small_size);
 151     _free_chunks[MediumIndex].set_size(medium_size);
 152   }
 153 
 154   // add or delete (return) a chunk to the global freelist.
 155   Metachunk* chunk_freelist_allocate(size_t word_size);
 156 
 157   // Map a size to a list index assuming that there are lists
 158   // for special, small, medium, and humongous chunks.
 159   ChunkIndex list_index(size_t size) const;
 160 
 161   // Remove the chunk from its freelist.  It is
 162   // expected to be on one of the _free_chunks[] lists.
 163   void remove_chunk(Metachunk* chunk);
 164 
 165   // Add the simple linked list of chunks to the freelist of chunks
 166   // of type index.
 167   void return_chunks(ChunkIndex index, Metachunk* chunks);
 168 
 169   // Total of the space in the free chunks list
 170   size_t free_chunks_total_words();
 171   size_t free_chunks_total_bytes();
 172 
 173   // Number of chunks in the free chunks list
 174   size_t free_chunks_count();
 175 
 176   void inc_free_chunks_total(size_t v, size_t count = 1) {
 177     Atomic::add_ptr(count, &_free_chunks_count);
 178     Atomic::add_ptr(v, &_free_chunks_total);
 179   }


 235   void verify();
 236   void slow_verify() {
 237     if (metaspace_slow_verify) {
 238       verify();
 239     }
 240   }
 241   void locked_verify();
 242   void slow_locked_verify() {
 243     if (metaspace_slow_verify) {
 244       locked_verify();
 245     }
 246   }
 247   void verify_free_chunks_total();
 248 
 249   void locked_print_free_chunks(outputStream* st);
 250   void locked_print_sum_free_chunks(outputStream* st);
 251 
 252   void print_on(outputStream* st) const;
 253 };
 254 
 255 void ChunkManager_test_list_index() {
 256   ChunkManager manager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk);
 257 
 258   // Test previous bug where a query for a humongous class metachunk,
 259   // incorrectly matched the non-class medium metachunk size.
 260   {
 261     assert(MediumChunk > ClassMediumChunk, "Precondition for test");
 262 
 263     ChunkIndex index = manager.list_index(MediumChunk);
 264 
 265     assert(index == HumongousIndex,
 266            "Requested size is larger than ClassMediumChunk,"
 267            " so should return HumongousIndex. Got index: %d", (int)index);
 268   }
 269 
 270   // Check the specified sizes as well.
 271   {
 272     ChunkIndex index = manager.list_index(ClassSpecializedChunk);
 273     assert(index == SpecializedIndex, "Wrong index returned. Got index: %d", (int)index);
 274   }
 275   {
 276     ChunkIndex index = manager.list_index(ClassSmallChunk);
 277     assert(index == SmallIndex, "Wrong index returned. Got index: %d", (int)index);
 278   }
 279   {
 280     ChunkIndex index = manager.list_index(ClassMediumChunk);
 281     assert(index == MediumIndex, "Wrong index returned. Got index: %d", (int)index);
 282   }
 283   {
 284     ChunkIndex index = manager.list_index(ClassMediumChunk + 1);
 285     assert(index == HumongousIndex, "Wrong index returned. Got index: %d", (int)index);
 286   }
 287 }
 288 
 289 class SmallBlocks : public CHeapObj<mtClass> {
 290   const static uint _small_block_max_size = sizeof(TreeChunk<Metablock,  FreeList<Metablock> >)/HeapWordSize;
 291   const static uint _small_block_min_size = sizeof(Metablock)/HeapWordSize;
 292 
 293  private:
 294   FreeList<Metablock> _small_lists[_small_block_max_size - _small_block_min_size];
 295 
 296   FreeList<Metablock>& list_at(size_t word_size) {
 297     assert(word_size >= _small_block_min_size, "There are no metaspace objects less than %u words", _small_block_min_size);
 298     return _small_lists[word_size - _small_block_min_size];
 299   }
 300 
 301  public:
 302   SmallBlocks() {
 303     for (uint i = _small_block_min_size; i < _small_block_max_size; i++) {
 304       uint k = i - _small_block_min_size;
 305       _small_lists[k].set_size(i);
 306     }
 307   }
 308 


2357   if (_block_freelists != NULL) {
2358     delete _block_freelists;
2359   }
2360 }
2361 
2362 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
2363   switch (index) {
2364     case SpecializedIndex:
2365       return "Specialized";
2366     case SmallIndex:
2367       return "Small";
2368     case MediumIndex:
2369       return "Medium";
2370     case HumongousIndex:
2371       return "Humongous";
2372     default:
2373       return NULL;
2374   }
2375 }
2376 
2377 size_t ChunkManager::list_chunk_size(ChunkIndex index) const {
2378   assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex,
2379       "Bad index: %d", (int)index);
2380 
2381   return _free_chunks[index].size();
2382 }
2383 
2384 ChunkIndex ChunkManager::list_index(size_t size) const {
2385   if (list_chunk_size(SpecializedIndex) == size) {
2386     return SpecializedIndex;
2387   }
2388   if (list_chunk_size(SmallIndex) == size) {
2389     return SmallIndex;
2390   }
2391   if (list_chunk_size(MediumIndex) == size) {
2392     return MediumIndex;




2393   }
2394 
2395   assert(size > list_chunk_size(MediumIndex), "Not a humongous chunk");
2396   return HumongousIndex;
2397 }
2398 
2399 void SpaceManager::deallocate(MetaWord* p, size_t word_size) {
2400   assert_lock_strong(_lock);
2401   // Allocations and deallocations are in raw_word_size
2402   size_t raw_word_size = get_allocation_word_size(word_size);
2403   // Lazily create a block_freelist
2404   if (block_freelists() == NULL) {
2405     _block_freelists = new BlockFreelist();
2406   }
2407   block_freelists()->return_block(p, raw_word_size);
2408 }
2409 
2410 // Adds a chunk to the list of chunks in use.
2411 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
2412 
2413   assert(new_chunk != NULL, "Should not be NULL");
2414   assert(new_chunk->next() == NULL, "Should not be on a list");
2415 
2416   new_chunk->reset_empty();
2417 
2418   // Find the correct list and and set the current
2419   // chunk for that list.
2420   ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size());
2421 
2422   if (index != HumongousIndex) {
2423     retire_current_chunk();
2424     set_current_chunk(new_chunk);
2425     new_chunk->set_next(chunks_in_use(index));
2426     set_chunks_in_use(index, new_chunk);
2427   } else {
2428     // For null class loader data and DumpSharedSpaces, the first chunk isn't
2429     // small, so small will be null.  Link this first chunk as the current
2430     // chunk.
2431     if (make_current) {
2432       // Set as the current chunk but otherwise treat as a humongous chunk.
2433       set_current_chunk(new_chunk);
2434     }
2435     // Link at head.  The _current_chunk only points to a humongous chunk for
2436     // the null class loader metaspace (class and data virtual space managers)
2437     // any humongous chunks so will not point to the tail
2438     // of the humongous chunks list.
2439     new_chunk->set_next(chunks_in_use(HumongousIndex));
2440     set_chunks_in_use(HumongousIndex, new_chunk);


< prev index next >