1 /* 2 * Copyright (c) 2018, 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 25 #ifndef SHARE_MEMORY_METASPACE_ABSTRACTPOOL_HPP 26 #define SHARE_MEMORY_METASPACE_ABSTRACTPOOL_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/debug.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 32 namespace metaspace { 33 34 // A simple helper class; 35 // 36 // holds a linear array of elements of type E; 37 // 38 // array lives in C heap and expands automatically; 39 // 40 // free elements can be returned and are kept in a freelist; 41 // 42 // elements can be retrieved by their index (index type I). 43 // 44 // E must offer a "E* next()" and "set_next(E*)" methods. 45 // I must be an integral type. 46 // 47 template <class E, class I> 48 class AbstractPool { 49 public: 50 51 typedef I size_type_t; 52 53 private: 54 55 E* _arr; 56 size_type_t _len; 57 size_type_t _used; 58 E* _freelist; 59 const char* const _name; 60 61 // Enlarge internal array if needed. Zero out new portion of array. 62 void enlarge_to(size_type_t new_len) { 63 const size_t new_size_bytes = new_len * sizeof(E); 64 E* p = (E*) os::realloc(_arr, new_size_bytes, mtInternal); 65 if (p == NULL) { 66 vm_exit_out_of_memory(new_size_bytes, OOM_MALLOC_ERROR, "Pool %s: not enough space", _name); 67 } 68 _arr = p; _len = new_len; 69 } 70 71 #ifdef ASSERT 72 void check_elem(E* p) { assert(is_valid_elem(p), "invalid pointer"); } 73 void check_idx(I i) { assert(i <= _used, "invalid index"); } 74 #endif 75 76 public: 77 78 AbstractPool(const char* name) 79 : _arr(NULL), _len(0), _used(0), _name(name), _freelist(NULL) {} 80 ~AbstractPool() { os::free(_arr); } 81 82 I index_for_elem(E* p) const { 83 DEBUG_ONLY(check_elem(p)); 84 return p - _arr; 85 } 86 87 E* elem_at_index(I i) const { 88 DEBUG_ONLY(check_idx(i)); 89 return _arr + i; 90 } 91 92 // Allocate a new element. Enlarge internal array if needed. 93 // Will return NULL if cap is reached. 94 E* allocate_element() { 95 96 if (_freelist != NULL) { 97 E* p = _freelist; 98 _freelist = _freelist->next(); 99 DEBUG_ONLY(p->set_next(NULL);) 100 return p; 101 } 102 103 if (_len == _used) { 104 size_type_t new_len = _len == 0 ? 0x100 : _len * 2; 105 enlarge_to(new_len); 106 } 107 108 // Avoid handing out anything at index 0. 109 // This allows callers to use "I index == 0" as "invalid ref". 110 if (_used == 0) { 111 _used ++; 112 } 113 114 E* p = _arr[_used ++]; 115 return p; 116 117 } 118 119 void return_element(E* p) { 120 DEBUG_ONLY(check_elem(p)); 121 p->set_next(_freelist); 122 _freelist = p; 123 } 124 125 // Returns true if p was allocated from this pool. 126 bool is_valid_elem(const E* p) { return p >= _arr && p < _arr + _used; } 127 128 }; 129 130 } // namespace metaspace 131 132 #endif // SHARE_MEMORY_METASPACE_ABSTRACTPOOL_HPP