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




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




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



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

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


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