1 /* 2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 #include "precompiled.hpp" 25 26 27 #include "logging/log.hpp" 28 #include "memory/metaspace/constants.hpp" 29 #include "memory/metaspace/chunkAllocSequence.hpp" 30 #include "memory/metaspace/chunkLevel.hpp" 31 #include "memory/metaspace/chunkManager.hpp" 32 #include "memory/metaspace/metachunk.hpp" 33 #include "memory/metaspace/virtualSpaceNode.hpp" 34 #include "memory/metaspace/virtualSpaceList.hpp" 35 #include "runtime/mutexLocker.hpp" 36 #include "utilities/debug.hpp" 37 #include "utilities/globalDefinitions.hpp" 38 39 namespace metaspace { 40 41 42 // Return a single chunk to the freelist and adjust accounting. No merge is attempted. 43 void ChunkManager::return_chunk_simple(Metachunk* c) { 44 DEBUG_ONLY(c->verify(false)); 45 const chklvl_t lvl = c->level(); 46 _chunks[lvl].add(c); 47 _total_word_size.increment_by(c->word_size()); 48 } 49 50 // Remove the given chunk from its free list and adjust accounting. 51 void ChunkManager::remove_chunk(Metachunk* c) { 52 DEBUG_ONLY(c->verify(false)); 53 const chklvl_t lvl = c->level(); 54 _chunks[lvl].remove(c); 55 _total_word_size.decrement_by(c->word_size()); 56 } 57 58 // Creates a chunk manager with a given name (which is for debug purposes only) 59 // and an associated space list which will be used to request new chunks from 60 // (see get_chunk()) 61 ChunkManager::ChunkManager(const char* name, VirtualSpaceList* space_list) 62 : _vslist(space_list), 63 _name(name) 64 { 65 for (int i = 0; i < chklvl::NUM_CHUNK_LEVELS; i ++) { 66 _chunks[i] = NULL; 67 } 68 } 69 70 // Given a chunk we are about to handout to the caller, make sure it is committed 71 // according to constants::committed_words_on_fresh_chunks 72 bool ChunkManager::commit_chunk_before_handout(Metachunk* c) { 73 const size_t must_be_committed = MIN2(c->word_size(), constants::committed_words_on_fresh_chunks); 74 return c->ensure_committed(must_be_committed); 75 } 76 77 #ifdef ASSERT 78 // Given a splinters array returned from a split operation, check that it meets expectations 79 static void check_splinters_array(Metachunk* splinters[chklvl::NUM_CHUNK_LEVELS], chklvl_t min, chklvl_t max) { 80 // The array shall contain splinters in the range [min, max] and nothing outside. The chunk levels for 81 // the chunks must match too. 82 for (chklvl_t l = chklvl::ROOT_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 83 if (l >= min && l < max) { 84 assert(splinters[l] != NULL, "Missing splinters"); 85 assert(splinters[l]->level() == l, "Unexpected level"); 86 splinters[l]->verify(false); 87 } else { 88 assert(splinters[l] == NULL, "Unexpected splinters"); 89 } 90 } 91 } 92 #endif 93 94 95 // Given a chunk which must be outside of a freelist and must be free, split it to 96 // meet a target level and return it. Splinters are added to the freelist. 97 Metachunk* ChunkManager::split_chunk_and_add_splinters(Metachunk* c, chklvl_t target_level) { 98 99 assert(c->is_free() && c->level() > target_level, "Invalid chunk for splitting"); 100 DEBUG_ONLY(chklvl::check_valid_level(target_level);) 101 102 const chklvl_t orig_level = c->level(); 103 Metachunk* splinters[chklvl::NUM_CHUNK_LEVELS] = { 0 }; 104 c = c->vsnode()->split(target_level, c, splinters); 105 106 // Splitting should never fail. 107 assert(c != NULL, "Split failed"); 108 assert(c->level() == target_level, "Sanity"); 109 DEBUG_ONLY(c->verify(false)); 110 DEBUG_ONLY(check_splinters_array(splinters, orig_level + 1, target_level);) 111 112 // Return splinters to freelist. 113 for (chklvl_t l = orig_level + 1; l <= target_level; l ++) { 114 return_chunk_simple(splinters[l]); 115 } 116 117 return c; 118 } 119 120 // Get a chunk and be smart about it. 121 // - 1) Attempt to find a free chunk of exactly the pref_level level 122 // - 2) Failing that, attempt to find a chunk smaller or equal the minimal level. 123 // - 3) Failing that, attempt to find a free chunk of larger size and split it. 124 // - 4) Failing that, attempt to allocate a new chunk from the connected virtual space. 125 // - Failing that, give up and return NULL. 126 // Note: this is not guaranteed to return a *committed* chunk. The chunk manager will 127 // attempt to commit the returned chunk according to constants::committed_words_on_fresh_chunks; 128 // but this may fail if we hit a commit limit. In that case, a partly uncommit chunk 129 // will be returned, and the commit is attempted again when we allocate from the chunk's 130 // uncommitted area. See also Metachunk::allocate. 131 Metachunk* ChunkManager::get_chunk(chklvl_t min_level, chklvl_t pref_level) { 132 133 assert_lock_strong(MetaspaceExpand_lock); 134 DEBUG_ONLY(chklvl::check_valid_level(min_level);) 135 DEBUG_ONLY(chklvl::check_valid_level(pref_level);) 136 137 Metachunk* c = NULL; 138 139 // 1) Attempt to find a free chunk of exactly the pref_level level 140 if (_chunks[pref_level] != NULL) { 141 c = _chunks[pref_level]; 142 remove_chunk(c); 143 } 144 145 // 2) Failing that, attempt to find a chunk smaller or equal the minimal level. 146 if (c == NULL) { 147 for (chklvl_t lvl = pref_level + 1; lvl <= min_level; lvl ++) { 148 Metachunk* c = _chunks[lvl]; 149 if (c != NULL) { 150 remove_chunk(c); 151 break; 152 } 153 } 154 } 155 156 // 3) Failing that, attempt to find a free chunk of larger size and split it. 157 if (c == NULL) { 158 for (chklvl_t lvl = pref_level - 1; lvl >= chklvl::ROOT_CHUNK_LEVEL; lvl --) { 159 Metachunk* c = _chunks[lvl]; 160 if (c != NULL) { 161 162 // Remove chunk before splitting. 163 remove_chunk(c); 164 165 // Split chunk; add splinters to freelist 166 c = split_chunk_and_add_splinters(c, pref_level); 167 168 break; 169 } 170 } 171 } 172 173 // 4) Failing that, attempt to allocate a new chunk from the connected virtual space. 174 if (c == NULL) { 175 176 c = _vslist->allocate_root_chunk(); 177 178 // This should always work. Note that getting the root chunk may not mean we committed memory. 179 assert(c != NULL, "Unexpected"); 180 181 // Split this root chunk to the desired chunk size. 182 c = split_chunk_and_add_splinters(c, pref_level); 183 184 } 185 186 // Note that we should at this point have a chunk; should always work. If we hit 187 // a commit limit in the meantime, the chunk may still be uncommitted, but the chunk 188 // itself should exist now. 189 assert(c != NULL, "Unexpected"); 190 191 // Before returning the chunk, attempt to commit it according to the handout rules. 192 // If that fails, we ignore the error and return the uncommitted chunk. 193 if (commit_chunk_before_handout(c) == false) { 194 log_info(gc, metaspace)("Failed to commit chunk prior to handout."); 195 } 196 197 return c; 198 199 } // ChunkManager::get_chunk 200 201 202 // Return a single chunk to the ChunkManager and adjust accounting. May merge chunk 203 // with neighbors. 204 // Happens after a Classloader was unloaded and releases its metaspace chunks. 205 // !! Note: this may invalidate the chunk. Do not access the chunk after 206 // this function returns !! 207 void ChunkManager::return_chunk(Metachunk* c) { 208 209 assert_lock_strong(MetaspaceExpand_lock); 210 DEBUG_ONLY(c->verify(false);) 211 212 const chklvl_t orig_lvl = c->level(); 213 214 int num_merged[chklvl::NUM_CHUNK_LEVELS] = { 0 }; 215 Metachunk* c2 = c->vsnode()->merge(c, num_merged); 216 217 if (c2 != NULL) { 218 DEBUG_ONLY(c2->verify(false)); 219 220 // We did merge chunks and now have a bigger chunk. 221 assert(c2->level() < orig_lvl, "Sanity"); 222 223 // Adjust counters - the merged-in chunks have been removed from the free lists, but the counters 224 // in this chunk manager must be adjusted too. 225 size_t size_chunks_removed = 0; 226 for (chklvl_t l = chklvl::ROOT_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 227 if (num_merged[l] > 0) { 228 // Since we have a binary tree, we should exactly see one merge per level. 229 assert(num_merged[l] == 1, "sanity"); 230 _chunks[l].dec_counter_by(1); 231 size_chunks_removed += chklvl::word_size_for_level(l); 232 } 233 } 234 _total_word_size.decrement_by(size_chunks_removed); 235 236 c = c2; 237 } 238 239 return_chunk_simple(c); 240 241 } 242 243 244 ChunkManager* ChunkManager::_chunkmanager_class = NULL; 245 ChunkManager* ChunkManager::_chunkmanager_nonclass = NULL; 246 247 static void ChunkManager::initialize(ChunkManager* chunkmanager_class, ChunkManager* chunkmanager_nonclass) { 248 _chunkmanager_class = chunkmanager_class; 249 _chunkmanager_nonclass = chunkmanager_nonclass; 250 } 251 252 } // namespace metaspace 253 254 255