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