< prev index next >

src/share/vm/memory/metaspace.cpp

Print this page




 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   }


1766                      Mutex::_no_safepoint_check_flag);
1767   locked_verify();
1768 }
1769 
1770 void ChunkManager::locked_verify() {
1771   locked_verify_free_chunks_count();
1772   locked_verify_free_chunks_total();
1773 }
1774 
1775 void ChunkManager::locked_print_free_chunks(outputStream* st) {
1776   assert_lock_strong(SpaceManager::expand_lock());
1777   st->print_cr("Free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
1778                 _free_chunks_total, _free_chunks_count);
1779 }
1780 
1781 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) {
1782   assert_lock_strong(SpaceManager::expand_lock());
1783   st->print_cr("Sum free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
1784                 sum_free_chunks(), sum_free_chunks_count());
1785 }

1786 ChunkList* ChunkManager::free_chunks(ChunkIndex index) {



1787   return &_free_chunks[index];
1788 }
1789 
1790 // These methods that sum the free chunk lists are used in printing
1791 // methods that are used in product builds.
1792 size_t ChunkManager::sum_free_chunks() {
1793   assert_lock_strong(SpaceManager::expand_lock());
1794   size_t result = 0;
1795   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
1796     ChunkList* list = free_chunks(i);
1797 
1798     if (list == NULL) {
1799       continue;
1800     }
1801 
1802     result = result + list->count() * list->size();
1803   }
1804   result = result + humongous_dictionary()->total_size();
1805   return result;
1806 }


1870   // work.
1871   chunk->set_is_tagged_free(false);
1872 #endif
1873   chunk->container()->inc_container_count();
1874 
1875   slow_locked_verify();
1876   return chunk;
1877 }
1878 
1879 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
1880   assert_lock_strong(SpaceManager::expand_lock());
1881   slow_locked_verify();
1882 
1883   // Take from the beginning of the list
1884   Metachunk* chunk = free_chunks_get(word_size);
1885   if (chunk == NULL) {
1886     return NULL;
1887   }
1888 
1889   assert((word_size <= chunk->word_size()) ||
1890          list_index(chunk->word_size() == HumongousIndex),
1891          "Non-humongous variable sized chunk");
1892   Log(gc, metaspace, freelist) log;
1893   if (log.is_debug()) {
1894     size_t list_count;
1895     if (list_index(word_size) < HumongousIndex) {
1896       ChunkList* list = find_free_chunks_list(word_size);
1897       list_count = list->count();
1898     } else {
1899       list_count = humongous_dictionary()->total_count();
1900     }
1901     log.debug("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " PTR_FORMAT "  size " SIZE_FORMAT " count " SIZE_FORMAT " ",
1902                p2i(this), p2i(chunk), chunk->word_size(), list_count);
1903     ResourceMark rm;
1904     locked_print_free_chunks(log.debug_stream());
1905   }
1906 
1907   return chunk;
1908 }
1909 
1910 void ChunkManager::print_on(outputStream* out) const {


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);


3996     void* virtual_space_max = (void*)(uintptr_t)-1;
3997     size_t bottom_to_max = pointer_delta(virtual_space_max, vsn.bottom(), 1);
3998     size_t overflow_size = bottom_to_max + BytesPerWord;
3999     size_t overflow_word_size = overflow_size / BytesPerWord;
4000 
4001     // Check that is_available can handle the overflow.
4002     assert_is_available_negative(overflow_word_size);
4003   }
4004 
4005   static void test_is_available() {
4006     TestVirtualSpaceNodeTest::test_is_available_positive();
4007     TestVirtualSpaceNodeTest::test_is_available_negative();
4008     TestVirtualSpaceNodeTest::test_is_available_overflow();
4009   }
4010 };
4011 
4012 void TestVirtualSpaceNode_test() {
4013   TestVirtualSpaceNodeTest::test();
4014   TestVirtualSpaceNodeTest::test_is_available();
4015 }





































4016 #endif


 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   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   }


1766                      Mutex::_no_safepoint_check_flag);
1767   locked_verify();
1768 }
1769 
1770 void ChunkManager::locked_verify() {
1771   locked_verify_free_chunks_count();
1772   locked_verify_free_chunks_total();
1773 }
1774 
1775 void ChunkManager::locked_print_free_chunks(outputStream* st) {
1776   assert_lock_strong(SpaceManager::expand_lock());
1777   st->print_cr("Free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
1778                 _free_chunks_total, _free_chunks_count);
1779 }
1780 
1781 void ChunkManager::locked_print_sum_free_chunks(outputStream* st) {
1782   assert_lock_strong(SpaceManager::expand_lock());
1783   st->print_cr("Sum free chunk total " SIZE_FORMAT "  count " SIZE_FORMAT,
1784                 sum_free_chunks(), sum_free_chunks_count());
1785 }
1786 
1787 ChunkList* ChunkManager::free_chunks(ChunkIndex index) {
1788   assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex,
1789          "Bad index: %d", (int)index);
1790 
1791   return &_free_chunks[index];
1792 }
1793 
1794 // These methods that sum the free chunk lists are used in printing
1795 // methods that are used in product builds.
1796 size_t ChunkManager::sum_free_chunks() {
1797   assert_lock_strong(SpaceManager::expand_lock());
1798   size_t result = 0;
1799   for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
1800     ChunkList* list = free_chunks(i);
1801 
1802     if (list == NULL) {
1803       continue;
1804     }
1805 
1806     result = result + list->count() * list->size();
1807   }
1808   result = result + humongous_dictionary()->total_size();
1809   return result;
1810 }


1874   // work.
1875   chunk->set_is_tagged_free(false);
1876 #endif
1877   chunk->container()->inc_container_count();
1878 
1879   slow_locked_verify();
1880   return chunk;
1881 }
1882 
1883 Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) {
1884   assert_lock_strong(SpaceManager::expand_lock());
1885   slow_locked_verify();
1886 
1887   // Take from the beginning of the list
1888   Metachunk* chunk = free_chunks_get(word_size);
1889   if (chunk == NULL) {
1890     return NULL;
1891   }
1892 
1893   assert((word_size <= chunk->word_size()) ||
1894          (list_index(chunk->word_size()) == HumongousIndex),
1895          "Non-humongous variable sized chunk");
1896   Log(gc, metaspace, freelist) log;
1897   if (log.is_debug()) {
1898     size_t list_count;
1899     if (list_index(word_size) < HumongousIndex) {
1900       ChunkList* list = find_free_chunks_list(word_size);
1901       list_count = list->count();
1902     } else {
1903       list_count = humongous_dictionary()->total_count();
1904     }
1905     log.debug("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " PTR_FORMAT "  size " SIZE_FORMAT " count " SIZE_FORMAT " ",
1906                p2i(this), p2i(chunk), chunk->word_size(), list_count);
1907     ResourceMark rm;
1908     locked_print_free_chunks(log.debug_stream());
1909   }
1910 
1911   return chunk;
1912 }
1913 
1914 void ChunkManager::print_on(outputStream* out) const {


2325     delete _block_freelists;
2326   }
2327 }
2328 
2329 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
2330   switch (index) {
2331     case SpecializedIndex:
2332       return "Specialized";
2333     case SmallIndex:
2334       return "Small";
2335     case MediumIndex:
2336       return "Medium";
2337     case HumongousIndex:
2338       return "Humongous";
2339     default:
2340       return NULL;
2341   }
2342 }
2343 
2344 ChunkIndex ChunkManager::list_index(size_t size) {
2345   if (free_chunks(SpecializedIndex)->size() == size) {



2346     return SpecializedIndex;
2347   }
2348   if (free_chunks(SmallIndex)->size() == size) {
2349     return SmallIndex;
2350   }
2351   if (free_chunks(MediumIndex)->size() == size) {
2352     return MediumIndex;




2353   }
2354 
2355   assert(size > free_chunks(MediumIndex)->size(), "Not a humongous chunk");
2356   return HumongousIndex;
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 = chunk_manager()->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);


3996     void* virtual_space_max = (void*)(uintptr_t)-1;
3997     size_t bottom_to_max = pointer_delta(virtual_space_max, vsn.bottom(), 1);
3998     size_t overflow_size = bottom_to_max + BytesPerWord;
3999     size_t overflow_word_size = overflow_size / BytesPerWord;
4000 
4001     // Check that is_available can handle the overflow.
4002     assert_is_available_negative(overflow_word_size);
4003   }
4004 
4005   static void test_is_available() {
4006     TestVirtualSpaceNodeTest::test_is_available_positive();
4007     TestVirtualSpaceNodeTest::test_is_available_negative();
4008     TestVirtualSpaceNodeTest::test_is_available_overflow();
4009   }
4010 };
4011 
4012 void TestVirtualSpaceNode_test() {
4013   TestVirtualSpaceNodeTest::test();
4014   TestVirtualSpaceNodeTest::test_is_available();
4015 }
4016 
4017 // The following test is placed here instead of a gtest / unittest file
4018 // because the ChunkManager class is only available in this file.
4019 void ChunkManager_test_list_index() {
4020   ChunkManager manager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk);
4021 
4022   // Test previous bug where a query for a humongous class metachunk,
4023   // incorrectly matched the non-class medium metachunk size.
4024   {
4025     assert(MediumChunk > ClassMediumChunk, "Precondition for test");
4026 
4027     ChunkIndex index = manager.list_index(MediumChunk);
4028 
4029     assert(index == HumongousIndex,
4030            "Requested size is larger than ClassMediumChunk,"
4031            " so should return HumongousIndex. Got index: %d", (int)index);
4032   }
4033 
4034   // Check the specified sizes as well.
4035   {
4036     ChunkIndex index = manager.list_index(ClassSpecializedChunk);
4037     assert(index == SpecializedIndex, "Wrong index returned. Got index: %d", (int)index);
4038   }
4039   {
4040     ChunkIndex index = manager.list_index(ClassSmallChunk);
4041     assert(index == SmallIndex, "Wrong index returned. Got index: %d", (int)index);
4042   }
4043   {
4044     ChunkIndex index = manager.list_index(ClassMediumChunk);
4045     assert(index == MediumIndex, "Wrong index returned. Got index: %d", (int)index);
4046   }
4047   {
4048     ChunkIndex index = manager.list_index(ClassMediumChunk + 1);
4049     assert(index == HumongousIndex, "Wrong index returned. Got index: %d", (int)index);
4050   }
4051 }
4052 
4053 #endif
< prev index next >