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 GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP 27 #define GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP 28 29 #include "memory/allocation.hpp" 30 #include "runtime/os.hpp" 31 #include "utilities/debug.hpp" 32 33 #include "metaspaceGtestCommon.hpp" 34 #include "metaspaceGtestRangeHelpers.hpp" 35 36 /////// SparseArray<T> //////////////// 37 38 // Throughout these tests we need to keep track of allocated items (ranges of metaspace memory, metachunks, ..) 39 // and be able to random-access them. Makes sense to have a helper for that. 40 template <class T> 41 class SparseArray : public StackObj { 42 43 T* const _slots; 44 const int _num; 45 46 // For convenience: a range covering all possible slot indices. 47 const IntRange _index_range; 48 49 bool contains(int index) const { 50 return _index_range.contains(index); 51 } 52 53 // Check slot intex for oob 54 void check_index(int i) const { 55 assert(contains(i), "Sanity"); 56 } 57 58 // Swap the content of two slots. 59 void swap(int i1, int i2) { 60 check_index(i1); 61 check_index(i2); 62 T tmp = _slots[i1]; 63 _slots[i1] = _slots[i2]; 64 _slots[i2] = tmp; 65 } 66 67 enum condition_t { cond_null = 0, cond_non_null = 1, cond_dontcare = 2 }; 68 69 // Helper for next_matching_slot 70 bool slot_matches(int slot, condition_t c) const { 71 switch(c) { 72 case cond_null: return _slots[slot] == NULL; 73 case cond_non_null: return _slots[slot] != NULL; 74 case cond_dontcare: return true; 75 } 76 ShouldNotReachHere(); 77 return false; 78 } 79 80 // Starting at (including) index, find the next matching slot. Returns index or -1 if none found. 81 int next_matching_slot(int slot, condition_t c) const { 82 while(slot < _num) { 83 if (slot_matches(slot, c)) { 84 return slot; 85 } 86 slot++; 87 } 88 return -1; 89 } 90 91 public: 92 93 SparseArray(int num) 94 : _slots(NEW_C_HEAP_ARRAY(T, num, mtInternal)), 95 _num(num), 96 _index_range(num) 97 { 98 for (int i = 0; i < _num; i++) { 99 _slots[i] = NULL; 100 } 101 } 102 103 T at(int i) { return _slots[i]; } 104 const T at(int i) const { return _slots[i]; } 105 void set_at(int i, T e) { _slots[i] = e; } 106 107 int size() const { return _num; } 108 109 bool slot_is_null(int i) const { check_index(i); return _slots[i] == NULL; } 110 111 DEBUG_ONLY(void check_slot_is_null(int i) const { assert(slot_is_null(i), "Slot %d is not null", i); }) 112 DEBUG_ONLY(void check_slot_is_not_null(int i) const { assert(!slot_is_null(i), "Slot %d is null", i); }) 113 114 // Shuffle all elements randomly 115 void shuffle() { 116 for (int i = 0; i < _num; i++) { 117 swap(i, random_slot_index()); 118 } 119 } 120 121 // Reverse elements 122 void reverse() { 123 for (int i = 0; i < _num / 2; i++) { 124 swap(i, _num - i); 125 } 126 } 127 128 int first_slot() const { return 0; } 129 int next_slot(int index) const { return index == _index_range.highest() ? -1 : index + 1; } 130 131 int first_non_null_slot() const { return next_matching_slot(0, cond_non_null); } 132 int next_non_null_slot(int index) const { return next_matching_slot(index + 1, cond_non_null); } 133 134 int first_null_slot() const { return next_matching_slot(0, cond_null); } 135 int next_null_slot(int index) const { return next_matching_slot(index + 1, cond_null); } 136 137 // Return a random slot index. 138 int random_slot_index() const { 139 return _index_range.random_value(); 140 } 141 142 int random_non_null_slot_index() const { 143 int i = next_non_null_slot(_index_range.random_value()); 144 if (i == -1) { 145 i = first_non_null_slot(); 146 } 147 return i; 148 } 149 150 int random_null_slot_index() const { 151 int i = next_null_slot(_index_range.random_value()); 152 if (i == -1) { 153 i = first_null_slot(); 154 } 155 return i; 156 } 157 158 IntRange random_slot_range() const { 159 return _index_range.random_subrange(); 160 } 161 162 }; 163 164 #endif // GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP 165