1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 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_CHUNKHEADERPOOL_HPP 27 #define SHARE_MEMORY_METASPACE_CHUNKHEADERPOOL_HPP 28 29 #include "memory/allocation.hpp" 30 #include "memory/metaspace/metachunk.hpp" 31 #include "memory/metaspace/metachunkList.hpp" 32 #include "utilities/debug.hpp" 33 #include "utilities/globalDefinitions.hpp" 34 35 namespace metaspace { 36 37 // Chunk headers (Metachunk objects) are separate entities from their payload. 38 // Since they are allocated and released frequently in the course of buddy allocation 39 // (splitting, merging chunks happens often) we want allocation of them fast. Therefore 40 // we keep them in a simple pool (somewhat like a primitive slab allocator). 41 42 class ChunkHeaderPool : public CHeapObj<mtMetaspace> { 43 44 static const int slab_capacity = 128; 45 46 struct slab_t : public CHeapObj<mtMetaspace> { 47 slab_t* next; 48 int top; 49 Metachunk elems [slab_capacity]; 50 slab_t() : next(NULL), top(0) { 51 for (int i = 0; i < slab_capacity; i++) { 52 elems[i].clear(); 53 } 54 } 55 }; 56 57 IntCounter _num_slabs; 58 slab_t* _first_slab; 59 slab_t* _current_slab; 60 61 IntCounter _num_handed_out; 62 63 MetachunkList _freelist; 64 65 void allocate_new_slab(); 66 67 static ChunkHeaderPool* _chunkHeaderPool; 68 69 70 public: 71 72 ChunkHeaderPool(); 73 74 ~ChunkHeaderPool(); 75 76 // Allocates a Metachunk structure. The structure is uninitialized. 77 Metachunk* allocate_chunk_header() { 78 79 Metachunk* c = NULL; 80 81 DEBUG_ONLY(verify(false)); 82 83 c = _freelist.remove_first(); 84 assert(c == NULL || c->is_dead(), "Not a freelist chunk header?"); 85 86 if (c == NULL) { 87 88 if (_current_slab == NULL || 89 _current_slab->top == slab_capacity) { 90 allocate_new_slab(); 91 assert(_current_slab->top < slab_capacity, "Sanity"); 92 } 93 94 c = _current_slab->elems + _current_slab->top; 95 _current_slab->top ++; 96 97 } 98 99 _num_handed_out.increment(); 100 101 // By contract, the returned structure is uninitialized. 102 // Zap to make this clear. 103 DEBUG_ONLY(c->zap_header(0xBB);) 104 105 return c; 106 107 } 108 109 void return_chunk_header(Metachunk* c) { 110 // We only ever should return free chunks, since returning chunks 111 // happens only on merging and merging only works with free chunks. 112 assert(c != NULL && c->is_free(), "Sanity"); 113 #ifdef ASSERT 114 // In debug, fill dead header with pattern. 115 c->zap_header(0xCC); 116 c->set_next(NULL); 117 c->set_prev(NULL); 118 #endif 119 c->set_dead(); 120 _freelist.add(c); 121 _num_handed_out.decrement(); 122 123 } 124 125 // Returns number of allocated elements. 126 int used() const { return _num_handed_out.get(); } 127 128 // Returns number of elements in free list. 129 int freelist_size() const { return _freelist.count(); } 130 131 // Returns size of memory used. 132 size_t memory_footprint_words() const; 133 134 DEBUG_ONLY(void verify(bool slow) const;) 135 136 static void initialize(); 137 138 // Returns reference to the one global chunk header pool. 139 static ChunkHeaderPool* pool() { return _chunkHeaderPool; } 140 141 }; 142 143 144 } // namespace metaspace 145 146 147 148 149 #endif // SHARE_MEMORY_METASPACE_CHUNKHEADERPOOL_HPP