rev 60538 : imported patch jep387-all.patch
1 /* 2 * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2017, 2020 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef SHARE_MEMORY_METASPACE_METACHUNK_HPP 27 #define SHARE_MEMORY_METASPACE_METACHUNK_HPP 28 29 30 #include "memory/metaspace/counter.hpp" 31 #include "memory/metaspace/chunkLevel.hpp" 32 #include "utilities/debug.hpp" 33 #include "utilities/globalDefinitions.hpp" 34 35 36 class outputStream; 37 38 namespace metaspace { 39 40 class VirtualSpaceNode; 41 42 // A Metachunk is a contiguous metaspace memory region. It is part of 43 // a MetaspaceArena, which keeps a list of MetaChunk and allocates via 44 // pointer bump from the top element in the list. 45 // 46 // The Metachunk object itself (the "chunk header") is separated from 47 // the memory region (the chunk payload) it describes. It also can have 48 // no payload (a "dead" chunk). In itself it lives in C-heap, managed 49 // as part of a pool of Metachunk headers (ChunkHeaderPool). 50 // 51 // -- Metachunk state -- 52 // 53 // A Metachunk is "in-use" if it is part of a MetaspaceArena. That means 54 // its memory is used - or will be used shortly - to hold VM metadata 55 // on behalf of a class loader. 56 // 57 // A Metachunk is "free" if its payload is currently unused. In that 58 // case it is managed by a chunk freelist (the ChunkManager). 59 // 60 // A Metachunk is "dead" if it does not have a corresponding payload. 61 // In that case it lives as part of a freelist-of-dead-chunk-headers 62 // in the ChunkHeaderPool. 63 // 64 // -- Level -- 65 // 66 // Metachunks are managed as part of a buddy style allocation scheme. 67 // Sized always in steps of power-of-2, ranging from the smallest chunk size 68 // (1Kb) to the largest (4Mb) (see chunklevel.hpp). 69 // Its size is encoded as level, with level 0 being the largest chunk 70 // size ("root chunk"). 71 // 72 // -- Payload commit state -- 73 // 74 // A Metachunk payload may be committed, partly committed or completely 75 // uncommitted. Technically, a payload may be committed "checkered" - 76 // i.e. committed and uncommitted parts may interleave - but the 77 // important part is how much contiguous space is committed starting 78 // at the base of the payload (since that's where we allocate). 79 // 80 // The Metachunk keeps track of how much space is committed starting 81 // at the base of the payload - which is a performace optimization - 82 // while underlying layers (VirtualSpaceNode->commitmask) keep track 83 // of the "real" commit state, aka which granules are committed, 84 // independent on what chunks reside above those granules. 85 86 87 // +--------------+ <- end -----------+ ----------+ 88 // | | | | 89 // | | | | 90 // | | | | 91 // | | | | 92 // | | | | 93 // | ----------- | <- committed_top -- + | 94 // | | | | 95 // | | | "free" | 96 // | | | | size 97 // | | "free_below_ | | 98 // | | committed" | | 99 // | | | | 100 // | | | | 101 // | ----------- | <- top --------- + -------- | 102 // | | | | 103 // | | "used" | | 104 // | | | | 105 // +--------------+ <- start ----------+ ----------+ 106 107 // Note: this is a chunk **descriptor**. The real Payload area lives in metaspace, 108 // this class lives somewhere else. 109 class Metachunk { 110 111 // start of chunk memory; NULL if dead. 112 MetaWord* _base; 113 114 // Used words. 115 size_t _used_words; 116 117 // Size of the region, starting from base, which is guaranteed to be committed. In words. 118 // The actual size of committed regions may actually be larger. 119 // 120 // (This is a performance optimization. The underlying VirtualSpaceNode knows 121 // which granules are committed; but we want to avoid having to ask.) 122 size_t _committed_words; 123 124 chunklevel_t _level; // aka size. 125 126 // state_free: free, owned by a ChunkManager 127 // state_in_use: in-use, owned by a MetaspaceArena 128 // dead: just a hollow chunk header without associated memory, owned 129 // by chunk header pool. 130 enum state_t { 131 state_free = 0, 132 state_in_use = 1, 133 state_dead = 2 134 }; 135 state_t _state; 136 137 // We need unfortunately a back link to the virtual space node 138 // for splitting and merging nodes. 139 VirtualSpaceNode* _vsnode; 140 141 142 // A chunk header is kept in a list: 143 // 1 in the list of used chunks inside a MetaspaceArena, if it is in use 144 // 2 in the list of free chunks inside a ChunkManager, if it is free 145 // 3 in the freelist of unused headers inside the ChunkHeaderPool, 146 // if it is unused (e.g. result of chunk merging) and has no associated 147 // memory area. 148 Metachunk* _prev; 149 Metachunk* _next; 150 151 // Furthermore, we keep, per chunk, information about the neighboring chunks. 152 // This is needed to split and merge chunks. 153 // 154 // Note: These members can be modified concurrently while a chunk is alive and in use. 155 // This can happen if a neighboring chunk is added or removed. 156 // This means only read or modify these members under expand lock protection. 157 Metachunk* _prev_in_vs; 158 Metachunk* _next_in_vs; 159 160 // Commit uncommitted section of the chunk. 161 // Fails if we hit a commit limit. 162 bool commit_up_to(size_t new_committed_words); 163 164 DEBUG_ONLY(static void assert_have_expand_lock();) 165 166 public: 167 168 Metachunk() 169 : _base(NULL), 170 _used_words(0), 171 _committed_words(0), 172 _level(chunklevel::ROOT_CHUNK_LEVEL), 173 _state(state_free), 174 _vsnode(NULL), 175 _prev(NULL), _next(NULL), 176 _prev_in_vs(NULL), _next_in_vs(NULL) 177 {} 178 179 void clear() { 180 _base = NULL; 181 _used_words = 0; 182 _committed_words = 0; 183 _level = chunklevel::ROOT_CHUNK_LEVEL; 184 _state = state_free; 185 _vsnode = NULL; 186 _prev = NULL; 187 _next = NULL; 188 _prev_in_vs = NULL; 189 _next_in_vs = NULL; 190 } 191 192 193 size_t word_size() const { return chunklevel::word_size_for_level(_level); } 194 195 MetaWord* base() const { return _base; } 196 MetaWord* top() const { return base() + _used_words; } 197 MetaWord* committed_top() const { return base() + _committed_words; } 198 MetaWord* end() const { return base() + word_size(); } 199 200 // Chunk list wiring 201 void set_prev(Metachunk* c) { _prev = c; } 202 Metachunk* prev() const { return _prev; } 203 void set_next(Metachunk* c) { _next = c; } 204 Metachunk* next() const { return _next; } 205 206 DEBUG_ONLY(bool in_list() const { return _prev != NULL || _next != NULL; }) 207 208 // Physical neighbors wiring 209 void set_prev_in_vs(Metachunk* c) { DEBUG_ONLY(assert_have_expand_lock()); _prev_in_vs = c; } 210 Metachunk* prev_in_vs() const { DEBUG_ONLY(assert_have_expand_lock()); return _prev_in_vs; } 211 void set_next_in_vs(Metachunk* c) { DEBUG_ONLY(assert_have_expand_lock()); _next_in_vs = c; } 212 Metachunk* next_in_vs() const { DEBUG_ONLY(assert_have_expand_lock()); return _next_in_vs; } 213 214 bool is_free() const { return _state == state_free; } 215 bool is_in_use() const { return _state == state_in_use; } 216 bool is_dead() const { return _state == state_dead; } 217 void set_free() { _state = state_free; } 218 void set_in_use() { _state = state_in_use; } 219 void set_dead() { _state = state_dead; } 220 221 // Return a single char presentation of the state ('f', 'u', 'd') 222 char get_state_char() const; 223 224 void inc_level() { _level ++; DEBUG_ONLY(chunklevel::is_valid_level(_level);) } 225 void dec_level() { _level --; DEBUG_ONLY(chunklevel::is_valid_level(_level);) } 226 chunklevel_t level() const { return _level; } 227 228 // Convenience functions for extreme levels. 229 bool is_root_chunk() const { return chunklevel::ROOT_CHUNK_LEVEL == _level; } 230 bool is_leaf_chunk() const { return chunklevel::HIGHEST_CHUNK_LEVEL == _level; } 231 232 VirtualSpaceNode* vsnode() const { return _vsnode; } 233 234 size_t used_words() const { return _used_words; } 235 size_t free_words() const { return word_size() - used_words(); } 236 size_t free_below_committed_words() const { return committed_words() - used_words(); } 237 void reset_used_words() { _used_words = 0; } 238 239 size_t committed_words() const { return _committed_words; } 240 void set_committed_words(size_t v); 241 bool is_fully_committed() const { return committed_words() == word_size(); } 242 bool is_fully_uncommitted() const { return committed_words() == 0; } 243 244 // Ensure that chunk is committed up to at least new_committed_words words. 245 // Fails if we hit a commit limit. 246 bool ensure_committed(size_t new_committed_words); 247 bool ensure_committed_locked(size_t new_committed_words); 248 249 bool ensure_fully_committed() { return ensure_committed(word_size()); } 250 bool ensure_fully_committed_locked() { return ensure_committed_locked(word_size()); } 251 252 // Ensure that the chunk is committed far enough to serve an additional allocation of word_size. 253 bool ensure_committed_additional(size_t additional_word_size) { 254 return ensure_committed(used_words() + additional_word_size); 255 } 256 257 // Uncommit chunk area. The area must be a common multiple of the 258 // commit granule size (in other words, we cannot uncommit chunks smaller than 259 // a commit granule size). 260 void uncommit(); 261 void uncommit_locked(); 262 263 // Allocation from a chunk 264 265 // Allocate word_size words from this chunk (word_size must be aligned to 266 // allocation_alignment_words). 267 // 268 // Caller must make sure the chunk is both large enough and committed far enough 269 // to hold the allocation. Will always work. 270 // 271 MetaWord* allocate(size_t request_word_size); 272 273 // Initialize structure for reuse. 274 void initialize(VirtualSpaceNode* node, MetaWord* base, chunklevel_t lvl) { 275 _vsnode = node; _base = base; _level = lvl; 276 _used_words = _committed_words = 0; _state = state_free; 277 _next = _prev = _next_in_vs = _prev_in_vs = NULL; 278 } 279 280 // Returns true if this chunk is the leader in its buddy pair, false if not. 281 // Do not call for root chunks. 282 bool is_leader() const { 283 assert(!is_root_chunk(), "Root chunks have no buddy."); // Bit harsh? 284 return is_aligned(base(), chunklevel::word_size_for_level(level() - 1) * BytesPerWord); 285 } 286 287 //// Debug stuff //// 288 #ifdef ASSERT 289 void verify(bool slow) const; 290 // Verifies linking with neighbors in virtual space. Needs expand lock protection. 291 void verify_neighborhood() const; 292 void zap_header(uint8_t c = 0x17); 293 void fill_with_pattern(MetaWord pattern, size_t word_size); 294 void check_pattern(MetaWord pattern, size_t word_size); 295 296 // Returns true if given pointer points into the payload area of this chunk. 297 bool is_valid_pointer(const MetaWord* p) const { 298 return base() <= p && p < top(); 299 } 300 301 // Returns true if given pointer points into the commmitted payload area of this chunk. 302 bool is_valid_committed_pointer(const MetaWord* p) const { 303 return base() <= p && p < committed_top(); 304 } 305 306 #endif // ASSERT 307 308 void print_on(outputStream* st) const; 309 310 }; 311 312 // Little print helpers: since we often print out chunks, here some convenience macros 313 #define METACHUNK_FORMAT "@" PTR_FORMAT ", %c, base " PTR_FORMAT ", level " CHKLVL_FORMAT 314 #define METACHUNK_FORMAT_ARGS(chunk) p2i(chunk), chunk->get_state_char(), p2i(chunk->base()), chunk->level() 315 316 #define METACHUNK_FULL_FORMAT "@" PTR_FORMAT ", %c, base " PTR_FORMAT ", level " CHKLVL_FORMAT " (" SIZE_FORMAT "), used: " SIZE_FORMAT ", committed: " SIZE_FORMAT ", committed-free: " SIZE_FORMAT 317 #define METACHUNK_FULL_FORMAT_ARGS(chunk) p2i(chunk), chunk->get_state_char(), p2i(chunk->base()), chunk->level(), chunk->word_size(), chunk->used_words(), chunk->committed_words(), chunk->free_below_committed_words() 318 319 } // namespace metaspace 320 321 #endif // SHARE_MEMORY_METASPACE_METACHUNK_HPP --- EOF ---