src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/memory

src/share/vm/memory/metaspace.cpp

Print this page




 794 }
 795 
 796 void VirtualSpaceNode::dec_container_count() {
 797   assert_lock_strong(SpaceManager::expand_lock());
 798   _container_count--;
 799 }
 800 
 801 #ifdef ASSERT
 802 void VirtualSpaceNode::verify_container_count() {
 803   assert(_container_count == container_count_slow(),
 804          "Inconsistency in container_count _container_count " UINTX_FORMAT
 805          " container_count_slow() " UINTX_FORMAT, _container_count, container_count_slow());
 806 }
 807 #endif
 808 
 809 // BlockFreelist methods
 810 
 811 BlockFreelist::BlockFreelist() : _dictionary(new BlockTreeDictionary()) {}
 812 
 813 BlockFreelist::~BlockFreelist() {
 814   LogHandle(gc, metaspace, freelist) log;
 815   if (log.is_trace()) {
 816     ResourceMark rm;
 817     dictionary()->print_free_lists(log.trace_stream());
 818   }
 819   delete _dictionary;
 820 }
 821 
 822 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
 823   Metablock* free_chunk = ::new (p) Metablock(word_size);
 824   dictionary()->return_chunk(free_chunk);
 825 }
 826 
 827 MetaWord* BlockFreelist::get_block(size_t word_size) {
 828   if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
 829     // Dark matter.  Too small for dictionary.
 830     return NULL;
 831   }
 832 
 833   Metablock* free_block =
 834     dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::atLeast);
 835   if (free_block == NULL) {
 836     return NULL;
 837   }
 838 


2128 void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) {
2129   if (chunks == NULL) {
2130     return;
2131   }
2132   ChunkList* list = free_chunks(index);
2133   assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes");
2134   assert_lock_strong(SpaceManager::expand_lock());
2135   Metachunk* cur = chunks;
2136 
2137   // This returns chunks one at a time.  If a new
2138   // class List can be created that is a base class
2139   // of FreeList then something like FreeList::prepend()
2140   // can be used in place of this loop
2141   while (cur != NULL) {
2142     assert(cur->container() != NULL, "Container should have been set");
2143     cur->container()->dec_container_count();
2144     // Capture the next link before it is changed
2145     // by the call to return_chunk_at_head();
2146     Metachunk* next = cur->next();
2147     DEBUG_ONLY(cur->set_is_tagged_free(true);)

2148     list->return_chunk_at_head(cur);
2149     cur = next;
2150   }
2151 }
2152 
2153 SpaceManager::~SpaceManager() {
2154   // This call this->_lock which can't be done while holding expand_lock()
2155   assert(sum_capacity_in_chunks_in_use() == allocated_chunks_words(),
2156          "sum_capacity_in_chunks_in_use() " SIZE_FORMAT
2157          " allocated_chunks_words() " SIZE_FORMAT,
2158          sum_capacity_in_chunks_in_use(), allocated_chunks_words());
2159 
2160   MutexLockerEx fcl(SpaceManager::expand_lock(),
2161                     Mutex::_no_safepoint_check_flag);
2162 
2163   chunk_manager()->slow_locked_verify();
2164 
2165   dec_total_from_size_metrics();
2166 
2167   LogHandle(gc, metaspace, freelist) log;
2168   if (log.is_trace()) {
2169     log.trace("~SpaceManager(): " PTR_FORMAT, p2i(this));
2170     ResourceMark rm;
2171     locked_print_chunks_in_use_on(log.trace_stream());

2172   }
2173 
2174   // Do not mangle freed Metachunks.  The chunk size inside Metachunks
2175   // is during the freeing of a VirtualSpaceNodes.
2176 
2177   // Have to update before the chunks_in_use lists are emptied
2178   // below.
2179   chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
2180                                          sum_count_in_chunks_in_use());
2181 
2182   // Add all the chunks in use by this space manager
2183   // to the global list of free chunks.
2184 
2185   // Follow each list of chunks-in-use and add them to the
2186   // free lists.  Each list is NULL terminated.
2187 
2188   for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) {
2189     log.trace("returned " SIZE_FORMAT " %s chunks to freelist", sum_count_in_chunks_in_use(i), chunk_size_name(i));
2190     Metachunk* chunks = chunks_in_use(i);
2191     chunk_manager()->return_chunks(i, chunks);
2192     set_chunks_in_use(i, NULL);
2193     log.trace("updated freelist count " SSIZE_FORMAT " %s", chunk_manager()->free_chunks(i)->count(), chunk_size_name(i));
2194     assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
2195   }
2196 
2197   // The medium chunk case may be optimized by passing the head and
2198   // tail of the medium chunk list to add_at_head().  The tail is often
2199   // the current chunk but there are probably exceptions.
2200 
2201   // Humongous chunks
2202   log.trace("returned " SIZE_FORMAT " %s humongous chunks to dictionary",
2203             sum_count_in_chunks_in_use(HumongousIndex), chunk_size_name(HumongousIndex));
2204   log.trace("Humongous chunk dictionary: ");
2205   // Humongous chunks are never the current chunk.
2206   Metachunk* humongous_chunks = chunks_in_use(HumongousIndex);
2207 
2208   while (humongous_chunks != NULL) {
2209 #ifdef ASSERT
2210     humongous_chunks->set_is_tagged_free(true);
2211 #endif
2212     log.trace(PTR_FORMAT " (" SIZE_FORMAT ") ", p2i(humongous_chunks), humongous_chunks->word_size());
2213     assert(humongous_chunks->word_size() == (size_t)
2214            align_size_up(humongous_chunks->word_size(),
2215                              smallest_chunk_size()),
2216            "Humongous chunk size is wrong: word size " SIZE_FORMAT
2217            " granularity " SIZE_FORMAT,
2218            humongous_chunks->word_size(), smallest_chunk_size());
2219     Metachunk* next_humongous_chunks = humongous_chunks->next();
2220     humongous_chunks->container()->dec_container_count();
2221     chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
2222     humongous_chunks = next_humongous_chunks;
2223   }
2224   log.trace("updated dictionary count " SIZE_FORMAT " %s", chunk_manager()->humongous_dictionary()->total_count(), chunk_size_name(HumongousIndex));
2225   chunk_manager()->slow_locked_verify();
2226 }
2227 
2228 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
2229   switch (index) {
2230     case SpecializedIndex:
2231       return "Specialized";




 794 }
 795 
 796 void VirtualSpaceNode::dec_container_count() {
 797   assert_lock_strong(SpaceManager::expand_lock());
 798   _container_count--;
 799 }
 800 
 801 #ifdef ASSERT
 802 void VirtualSpaceNode::verify_container_count() {
 803   assert(_container_count == container_count_slow(),
 804          "Inconsistency in container_count _container_count " UINTX_FORMAT
 805          " container_count_slow() " UINTX_FORMAT, _container_count, container_count_slow());
 806 }
 807 #endif
 808 
 809 // BlockFreelist methods
 810 
 811 BlockFreelist::BlockFreelist() : _dictionary(new BlockTreeDictionary()) {}
 812 
 813 BlockFreelist::~BlockFreelist() {





 814   delete _dictionary;
 815 }
 816 
 817 void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
 818   Metablock* free_chunk = ::new (p) Metablock(word_size);
 819   dictionary()->return_chunk(free_chunk);
 820 }
 821 
 822 MetaWord* BlockFreelist::get_block(size_t word_size) {
 823   if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
 824     // Dark matter.  Too small for dictionary.
 825     return NULL;
 826   }
 827 
 828   Metablock* free_block =
 829     dictionary()->get_chunk(word_size, FreeBlockDictionary<Metablock>::atLeast);
 830   if (free_block == NULL) {
 831     return NULL;
 832   }
 833 


2123 void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) {
2124   if (chunks == NULL) {
2125     return;
2126   }
2127   ChunkList* list = free_chunks(index);
2128   assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes");
2129   assert_lock_strong(SpaceManager::expand_lock());
2130   Metachunk* cur = chunks;
2131 
2132   // This returns chunks one at a time.  If a new
2133   // class List can be created that is a base class
2134   // of FreeList then something like FreeList::prepend()
2135   // can be used in place of this loop
2136   while (cur != NULL) {
2137     assert(cur->container() != NULL, "Container should have been set");
2138     cur->container()->dec_container_count();
2139     // Capture the next link before it is changed
2140     // by the call to return_chunk_at_head();
2141     Metachunk* next = cur->next();
2142     DEBUG_ONLY(cur->set_is_tagged_free(true);)
2143     NOT_PRODUCT(cur->mangle(badMetaWordVal);)
2144     list->return_chunk_at_head(cur);
2145     cur = next;
2146   }
2147 }
2148 
2149 SpaceManager::~SpaceManager() {
2150   // This call this->_lock which can't be done while holding expand_lock()
2151   assert(sum_capacity_in_chunks_in_use() == allocated_chunks_words(),
2152          "sum_capacity_in_chunks_in_use() " SIZE_FORMAT
2153          " allocated_chunks_words() " SIZE_FORMAT,
2154          sum_capacity_in_chunks_in_use(), allocated_chunks_words());
2155 
2156   MutexLockerEx fcl(SpaceManager::expand_lock(),
2157                     Mutex::_no_safepoint_check_flag);
2158 
2159   chunk_manager()->slow_locked_verify();
2160 
2161   dec_total_from_size_metrics();
2162 
2163   LogHandle(gc, metaspace, freelist) log;
2164   if (log.is_trace()) {
2165     log.trace("~SpaceManager(): " PTR_FORMAT, p2i(this));
2166     ResourceMark rm;
2167     locked_print_chunks_in_use_on(log.trace_stream());
2168     block_freelists()->print_on(log.trace_stream());
2169   }
2170 



2171   // Have to update before the chunks_in_use lists are emptied
2172   // below.
2173   chunk_manager()->inc_free_chunks_total(allocated_chunks_words(),
2174                                          sum_count_in_chunks_in_use());
2175 
2176   // Add all the chunks in use by this space manager
2177   // to the global list of free chunks.
2178 
2179   // Follow each list of chunks-in-use and add them to the
2180   // free lists.  Each list is NULL terminated.
2181 
2182   for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) {
2183     log.trace("returned " SIZE_FORMAT " %s chunks to freelist", sum_count_in_chunks_in_use(i), chunk_size_name(i));
2184     Metachunk* chunks = chunks_in_use(i);
2185     chunk_manager()->return_chunks(i, chunks);
2186     set_chunks_in_use(i, NULL);
2187     log.trace("updated freelist count " SSIZE_FORMAT " %s", chunk_manager()->free_chunks(i)->count(), chunk_size_name(i));
2188     assert(i != HumongousIndex, "Humongous chunks are handled explicitly later");
2189   }
2190 
2191   // The medium chunk case may be optimized by passing the head and
2192   // tail of the medium chunk list to add_at_head().  The tail is often
2193   // the current chunk but there are probably exceptions.
2194 
2195   // Humongous chunks
2196   log.trace("returned " SIZE_FORMAT " %s humongous chunks to dictionary",
2197             sum_count_in_chunks_in_use(HumongousIndex), chunk_size_name(HumongousIndex));
2198   log.trace("Humongous chunk dictionary: ");
2199   // Humongous chunks are never the current chunk.
2200   Metachunk* humongous_chunks = chunks_in_use(HumongousIndex);
2201 
2202   while (humongous_chunks != NULL) {
2203     DEBUG_ONLY(humongous_chunks->set_is_tagged_free(true);)
2204     NOT_PRODUCT(humongous_chunks->mangle(badMetaWordVal);)

2205     log.trace(PTR_FORMAT " (" SIZE_FORMAT ") ", p2i(humongous_chunks), humongous_chunks->word_size());
2206     assert(humongous_chunks->word_size() == (size_t)
2207            align_size_up(humongous_chunks->word_size(),
2208                              smallest_chunk_size()),
2209            "Humongous chunk size is wrong: word size " SIZE_FORMAT
2210            " granularity " SIZE_FORMAT,
2211            humongous_chunks->word_size(), smallest_chunk_size());
2212     Metachunk* next_humongous_chunks = humongous_chunks->next();
2213     humongous_chunks->container()->dec_container_count();
2214     chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
2215     humongous_chunks = next_humongous_chunks;
2216   }
2217   log.trace("updated dictionary count " SIZE_FORMAT " %s", chunk_manager()->humongous_dictionary()->total_count(), chunk_size_name(HumongousIndex));
2218   chunk_manager()->slow_locked_verify();
2219 }
2220 
2221 const char* SpaceManager::chunk_size_name(ChunkIndex index) const {
2222   switch (index) {
2223     case SpecializedIndex:
2224       return "Specialized";


src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File