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