rev 57380 : [mq]: metaspace-improvement
1 /* 2 * Copyright (c) 2012, 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 #ifndef SHARE_MEMORY_METASPACE_METACHUNK_HPP 25 #define SHARE_MEMORY_METASPACE_METACHUNK_HPP 26 27 28 #include "memory/metaspace/abstractPool.hpp" 29 #include "memory/metaspace/chunkLevel.hpp" 30 #include "utilities/debug.hpp" 31 #include "utilities/globalDefinitions.hpp" 32 33 34 35 namespace metaspace { 36 37 struct qtnode_t; 38 class VirtualSpaceNode; 39 40 // Metachunk - Quantum of allocation from a Virtualspace 41 // Metachunks are reused (when freed are put on a global freelist) and 42 // have no permanent association to a SpaceManager. 43 44 // +--------------+ <- end ----+ --+ 45 // | | | | 46 // | | | free | 47 // | | | 48 // | | | | size (aka capacity) 49 // | | | | 50 // | ----------- | <- top -- + | 51 // | | | | 52 // | | | used | 53 // +--------------+ <- start -- + -- + 54 55 // Note: this is a chunk **descriptor**. The real Payload area lives in metaspace, 56 // this class lives somewhere else. 57 class Metachunk { 58 59 // A chunk header is kept in a list: 60 // - in the list of used chunks inside a SpaceManager, if it is in use 61 // - in the list of free chunks inside a ChunkManager, if it is free 62 // - in the freelist of dead headers inside the MetaChunkHeaderPool, 63 // if it is dead (e.g. result of chunk merging). 64 Metachunk* _prev; 65 Metachunk* _next; 66 67 chklvl_t _level; // aka size. 68 69 // true: free, owned by ChunkManager 70 // false: in-use, owned by SpaceManager 71 // if dead, meaningless 72 bool _is_free; 73 74 // start of chunk memory; NULL if dead. 75 MetaWord* _base; 76 77 // Used words. 78 size_t _used_words; 79 80 // the chunk tree node this header is hanging under; NULL if dead. 81 qtnode_t* _tree_node; 82 83 // We need unfortunately a back link to the virtual space node 84 // for splitting and merging nodes. 85 VirtualSpaceNode* _vsnode; 86 87 MetaWord* top() const { return base() + _used_words; } 88 89 Metachunk() 90 : _prev(NULL), _next(NULL), 91 _level(chklvl::ROOT_CHUNK_LEVEL), 92 _is_free(true), 93 _base(NULL), 94 _used_words(0), 95 _tree_node(NULL), 96 _vsnode(NULL) 97 {} 98 99 size_t word_size() const { return chklvl::word_size_for_level(_level); } 100 101 MetaWord* base() const { return _base; } 102 void set_base(MetaWord* p) { _base = p; } 103 MetaWord* end() const { return base() + word_size(); } 104 105 void set_prev(Metachunk* c) { _prev = c; } 106 Metachunk* prev() const { return _prev; } 107 void set_next(Metachunk* c) { _next = c; } 108 Metachunk* next() const { return _next; } 109 // Remove chunk from whatever list it lives in by wiring next with previous. 110 void remove_from_list(); 111 112 bool is_free() const { return _is_free; } 113 bool is_in_use() const { return !_is_free; } 114 void set_free(bool v) { _is_free = v; } 115 116 117 void inc_level() { _level ++; DEBUG_ONLY(chklvl::is_valid_level(_level);) } 118 void dec_level() { _level --; DEBUG_ONLY(chklvl::is_valid_level(_level);) } 119 void set_level(chklvl_t v) { _level = v; DEBUG_ONLY(chklvl::is_valid_level(_level);) } 120 chklvl_t level() const { return _level; } 121 122 void set_tree_node(qtnode_t* n) { _tree_node = n; } 123 qtnode_t* tree_node() const { return _tree_node; } 124 125 VirtualSpaceNode* vsnode() const { return _vsnode; } 126 void set_vsnode(VirtualSpaceNode* n) { _vsnode = n; } 127 128 size_t used_words() const { return _used_words; } 129 size_t free_words() const { return word_size() - used_words(); } 130 void reset_used_words() { _used_words = 0; } 131 132 // Allocation from a chunk 133 134 // Allocate word_size words from this chunk. 135 // 136 // May cause memory to be committed. That may fail if we hit a commit limit. In that case, 137 // NULL is returned and p_did_hit_commit_limit will be set to true. 138 // If the remainder portion of the chunk was too small to hold the allocation, 139 // NULL is returned and p_did_hit_commit_limit will be set to false. 140 MetaWord* allocate(size_t word_size, bool* p_did_hit_commit_limit); 141 142 // Wipe this object to look as if it were default constructed. 143 void wipe() { 144 _prev = NULL; _next = NULL; 145 _level = chklvl::ROOT_CHUNK_LEVEL; 146 _is_free(true); 147 _base(NULL); 148 _used_words(0); 149 _tree_node(NULL); 150 _vsnode(NULL); 151 } 152 153 //// Debug stuff //// 154 DEBUG_ONLY(void verify(bool slow) const;) 155 156 }; 157 158 159 class MetachunkPool : private AbstractPool<Metachunk, uint32_t> { 160 public: 161 162 static bool is_metachunk_pointer(void* p) { 163 return is_valid_elem((Metachunk*)p); 164 } 165 166 // Allocate new Metachunk header. Header will be default constructed. 167 static Metachunk* alloc_header() { 168 Metachunk* c = allocate_element(); 169 c->wipe(); 170 return c; 171 } 172 173 // Mark a header as dead and return to the pool for later reuse. 174 static void release_header(Metachunk* c) { 175 DEBUG_ONLY(c->set_base(NULL);) 176 return_element(c); 177 } 178 179 }; 180 181 182 183 } // namespace metaspace 184 185 #endif // SHARE_MEMORY_METASPACE_METACHUNK_HPP --- EOF ---