1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, 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_MSVIRTUALSPACENODE_HPP 27 #define SHARE_MEMORY_METASPACE_MSVIRTUALSPACENODE_HPP 28 29 #include "memory/allocation.hpp" 30 #include "memory/metaspace/msCommitMask.hpp" 31 #include "memory/metaspace/msCounter.hpp" 32 #include "memory/metaspace/msRootChunkArea.hpp" 33 #include "memory/metaspace/msSettings.hpp" 34 #include "memory/memRegion.hpp" 35 #include "memory/virtualspace.hpp" 36 #include "utilities/debug.hpp" 37 #include "utilities/bitMap.hpp" 38 #include "utilities/globalDefinitions.hpp" 39 40 class outputStream; 41 42 namespace metaspace { 43 44 class CommitLimiter; 45 class FreeChunkListVector; 46 47 // VirtualSpaceNode manages a single contiguous address range of metaspace. Logically that memory 48 // region is split up into a sequence of "root chunk areas", each one containing one root chunk 49 // or splinters of a root chunk. 50 // 51 // The underlying memory is also logically divided into a number of "commit granules", units of memory 52 // which may be committed or uncommitted independently from each other. 53 // 54 // (Both root chunk areas and commit granules have not much to do with each other - one is a way to 55 // reserve memory for the upper regions, see ChunkManager. One is a way to manage commited memory.) 56 // 57 // VirtualSpaceNode: 58 // - exposes a function to allocate a new root chunk (see VirtualSpaceNode::allocate_root_chunk()). 59 // 60 // - knows about the commit state of the memory region - which commit granule are committed, which 61 // are not. It exposes functions to commit and uncommit regions (without actively committing 62 // itself) 63 // 64 // - It has a reference to a "CommitLimiter", an interface to query whether committing is 65 // possible. That interface hides the various ways committing may be limited (GC threshold, 66 // MaxMetaspaceSize, ...) 67 // 68 // - It uses ReservedSpace to reserve its memory. It either owns the ReservedSpace or that 69 // space got handed in from outside (ccs). 70 // 71 // 72 // 73 // 74 // | root chunk area | root chunk area | root chunk area | <-- root chunk areas 75 // 76 // +-----------------------------------------------------------------------------------------------+ 77 // | | 78 // | `VirtualSpaceNode` memory | 79 // | | 80 // +-----------------------------------------------------------------------------------------------+ 81 // 82 // |x| |x|x|x| | | | |x|x|x| | | |x|x| | | |x|x|x|x| | | | | | | | |x| | | |x|x|x|x| | | |x| | | |x| <-- commit granules 83 // 84 // (x = committed) 85 // 86 87 class VirtualSpaceNode : public CHeapObj<mtClass> { 88 89 // Link to next VirtualSpaceNode 90 VirtualSpaceNode* _next; 91 92 // The underlying space. This has been either created by this node 93 // and is owned by it, or has been handed in from outside (e.g. in 94 // case of CompressedClassSpace). 95 ReservedSpace _rs; 96 97 // True if the node owns the reserved space, false if not. 98 const bool _owns_rs; 99 100 // Start pointer of the area. 101 MetaWord* const _base; 102 103 // Size, in words, of the whole node 104 const size_t _word_size; 105 106 // Size, in words, of the range of this node which has been handed out in 107 // the form of root chunks. 108 size_t _used_words; 109 110 // The bitmap describing the commit state of the region: 111 // Each bit covers a region of 64K (see constants::commit_granule_size). 112 CommitMask _commit_mask; 113 114 // An array/lookup table of RootChunkArea objects. Each one describes a root chunk area. 115 RootChunkAreaLUT _root_chunk_area_lut; 116 117 // Limiter object to ask before expanding the committed size of this node. 118 CommitLimiter* const _commit_limiter; 119 120 // Points to outside size counters which we are to increase/decrease when we commit/uncommit 121 // space from this node. 122 SizeCounter* const _total_reserved_words_counter; 123 SizeCounter* const _total_committed_words_counter; 124 125 /// committing, uncommitting /// 126 127 // Given a pointer into this node, calculate the start of the commit granule 128 // the pointer points into. 129 MetaWord* calc_start_of_granule(MetaWord* p) const { 130 DEBUG_ONLY(check_pointer(p)); 131 return align_down(p, Settings::commit_granule_bytes()); 132 } 133 134 // Given an address range, ensure it is committed. 135 // 136 // The range has to be aligned to granule size. 137 // 138 // Function will: 139 // - check how many granules in that region are uncommitted; If all are committed, it 140 // returns true immediately. 141 // - check if committing those uncommitted granules would bring us over the commit limit 142 // (GC threshold, MaxMetaspaceSize). If true, it returns false. 143 // - commit the memory. 144 // - mark the range as committed in the commit mask 145 // 146 // Returns true if success, false if it did hit a commit limit. 147 bool commit_range(MetaWord* p, size_t word_size); 148 149 //// creation //// 150 151 // Create a new empty node spanning the given given reserved space. 152 VirtualSpaceNode(ReservedSpace rs, bool owns_rs, CommitLimiter* limiter, 153 SizeCounter* reserve_counter, SizeCounter* commit_counter); 154 155 public: 156 157 // Create a node of a given size (it will create its own space). 158 static VirtualSpaceNode* create_node(size_t word_size, CommitLimiter* limiter, SizeCounter* reserve_words_counter, 159 SizeCounter* commit_words_counter); 160 161 // Create a node over an existing space 162 static VirtualSpaceNode* create_node(ReservedSpace rs, CommitLimiter* limiter, SizeCounter* reserve_words_counter, 163 SizeCounter* commit_words_counter); 164 165 ~VirtualSpaceNode(); 166 167 // Note: public for gtests only, could be private. 168 MetaWord* base() const { return _base; } 169 170 // Reserved size of the whole node. 171 size_t word_size() const { return _word_size; } 172 173 //// Chunk allocation, splitting, merging ///// 174 175 // Allocate a root chunk from this node. Will fail and return NULL if the node is full 176 // - if we used up the whole address space of this node's memory region. 177 // (in case this node backs compressed class space, this is how we hit 178 // CompressedClassSpaceSize). 179 // Note that this just returns reserved memory; caller must take care of committing this 180 // chunk before using it. 181 Metachunk* allocate_root_chunk(); 182 183 // Given a chunk c, split it recursively until you get a chunk of the given target_level. 184 // 185 // The resulting target chunk resides at the same address as the original chunk. 186 // The resulting splinters are added to freelists. 187 void split(chunklevel_t target_level, Metachunk* c, FreeChunkListVector* freelists); 188 189 // Given a chunk, attempt to merge it recursively with its neighboring chunks. 190 // 191 // If successful (merged at least once), returns address of 192 // the merged chunk; NULL otherwise. 193 // 194 // The merged chunks are removed from the freelists. 195 // 196 // !!! Please note that if this method returns a non-NULL value, the 197 // original chunk will be invalid and should not be accessed anymore! !!! 198 Metachunk* merge(Metachunk* c, FreeChunkListVector* freelists); 199 200 // Given a chunk c, which must be "in use" and must not be a root chunk, attempt to 201 // enlarge it in place by claiming its trailing buddy. 202 // 203 // This will only work if c is the leader of the buddy pair and the trailing buddy is free. 204 // 205 // If successful, the follower chunk will be removed from the freelists, the leader chunk c will 206 // double in size (level decreased by one). 207 // 208 // On success, true is returned, false otherwise. 209 bool attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector* freelists); 210 211 // Attempts to purge the node: 212 // 213 // If all chunks living in this node are free, they will all be removed from 214 // the freelist they currently reside in. Then, the node will be deleted. 215 // 216 // Returns true if the node has been deleted, false if not. 217 // !! If this returns true, do not access the node from this point on. !! 218 bool attempt_purge(FreeChunkListVector* freelists); 219 220 // Attempts to uncommit free areas according to the rules set in settings. 221 // Returns number of words uncommitted. 222 size_t uncommit_free_areas(); 223 224 /// misc ///// 225 226 // Returns size, in words, of the used space in this node alone. 227 // (Notes: 228 // - This is the space handed out to the ChunkManager, so it is "used" from the viewpoint of this node, 229 // but not necessarily used for Metadata. 230 // - This may or may not be committed memory. 231 size_t used_words() const { return _used_words; } 232 233 // Returns size, in words, of how much space is left in this node alone. 234 size_t free_words() const { return _word_size - _used_words; } 235 236 // Returns size, in words, of committed space in this node alone. 237 // Note: iterates over commit mask and hence may be a tad expensive on large nodes. 238 size_t committed_words() const; 239 240 //// Committing/uncommitting memory ///// 241 242 // Given an address range, ensure it is committed. 243 // 244 // The range does not have to be aligned to granule size. However, the function will always commit 245 // whole granules. 246 // 247 // Function will: 248 // - check how many granules in that region are uncommitted; If all are committed, it 249 // returns true immediately. 250 // - check if committing those uncommitted granules would bring us over the commit limit 251 // (GC threshold, MaxMetaspaceSize). If true, it returns false. 252 // - commit the memory. 253 // - mark the range as committed in the commit mask 254 // 255 // Returns true if success, false if it did hit a commit limit. 256 bool ensure_range_is_committed(MetaWord* p, size_t word_size); 257 258 // Given an address range (which has to be aligned to commit granule size): 259 // - uncommit it 260 // - mark it as uncommitted in the commit mask 261 void uncommit_range(MetaWord* p, size_t word_size); 262 263 //// List stuff //// 264 VirtualSpaceNode* next() const { return _next; } 265 void set_next(VirtualSpaceNode* vsn) { _next = vsn; } 266 267 /// Debug stuff //// 268 269 // Print a description about this node. 270 void print_on(outputStream* st) const; 271 272 // Verify counters and basic structure. Slow mode: verify all chunks in depth 273 bool contains(const MetaWord* p) const { 274 return p >= _base && p < _base + _used_words; 275 } 276 277 #ifdef ASSERT 278 void check_pointer(const MetaWord* p) const { 279 assert(contains(p), "invalid pointer"); 280 } 281 void verify() const; 282 void verify_locked() const; 283 #endif 284 285 }; 286 287 } // namespace metaspace 288 289 #endif // SHARE_MEMORY_METASPACE_MSVIRTUALSPACENODE_HPP