1 /* 2 * Copyright Amazon.com Inc. 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_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP 27 28 #include <cstddef> 29 30 #include "gc/shenandoah/shenandoahAsserts.hpp" 31 32 // TODO: Merge the enhanced capabilities of ShenandoahSimpleBitMap into src/hotspot/share/utilities/bitMap.hpp 33 // and deprecate ShenandoahSimpleBitMap. The key enhanced capabilities to be integrated include: 34 // 35 // 1. Allow searches from high to low memory (when biasing allocations towards the top of the heap) 36 // 2. Allow searches for clusters of contiguous set bits (to expedite allocation for humongous objects) 37 // 38 // idx_t is defined here as ssize_t. In src/hotspot/share/utiliities/bitMap.hpp, idx is defined as size_t. 39 // This is a significant incompatibility. 40 // 41 // The API and internal implementation of ShenandoahSimpleBitMap and ShenandoahRegionPartitions use idx_t to 42 // represent index, even though index is "inherently" unsigned. There are two reasons for this choice: 43 // 1. We use -1 as a sentinel value to represent empty partitions. This same value may be used to represent 44 // failure to find a previous set bit or previous range of set bits. 45 // 2. Certain loops are written most naturally if the iterator, which may hold the sentinel -1 value, can be 46 // declared as signed and the terminating condition can be < 0. 47 48 typedef ssize_t idx_t; 49 50 // ShenandoahSimpleBitMap resembles CHeapBitMap but adds missing support for find_first_consecutive_set_bits() and 51 // find_last_consecutive_set_bits. An alternative refactoring of code would subclass CHeapBitMap, but this might 52 // break abstraction rules, because efficient implementation requires assumptions about superclass internals that 53 // might be violated through future software maintenance. 54 class ShenandoahSimpleBitMap { 55 const idx_t _num_bits; 56 const size_t _num_words; 57 uintx* const _bitmap; 58 59 public: 60 ShenandoahSimpleBitMap(size_t num_bits); 61 62 ~ShenandoahSimpleBitMap(); 63 64 void clear_all() { 65 for (size_t i = 0; i < _num_words; i++) { 66 _bitmap[i] = 0; 67 } 68 } 69 70 private: 71 72 // Count consecutive ones in forward order, starting from start_idx. Requires that there is at least one zero 73 // between start_idx and index value (_num_bits - 1), inclusive. 74 size_t count_leading_ones(idx_t start_idx) const; 75 76 // Count consecutive ones in reverse order, starting from last_idx. Requires that there is at least one zero 77 // between last_idx and index value zero, inclusive. 78 size_t count_trailing_ones(idx_t last_idx) const; 79 80 bool is_forward_consecutive_ones(idx_t start_idx, idx_t count) const; 81 bool is_backward_consecutive_ones(idx_t last_idx, idx_t count) const; 82 83 static inline uintx tail_mask(uintx bit_number); 84 85 public: 86 87 inline idx_t aligned_index(idx_t idx) const { 88 assert((idx >= 0) && (idx < _num_bits), "precondition"); 89 idx_t array_idx = idx & ~(BitsPerWord - 1); 90 return array_idx; 91 } 92 93 inline constexpr idx_t alignment() const { 94 return BitsPerWord; 95 } 96 97 // For testing 98 inline idx_t size() const { 99 return _num_bits; 100 } 101 102 // Return the word that holds idx bit and its neighboring bits. 103 inline uintx bits_at(idx_t idx) const { 104 assert((idx >= 0) && (idx < _num_bits), "precondition"); 105 idx_t array_idx = idx >> LogBitsPerWord; 106 return _bitmap[array_idx]; 107 } 108 109 inline void set_bit(idx_t idx) { 110 assert((idx >= 0) && (idx < _num_bits), "precondition"); 111 size_t array_idx = idx >> LogBitsPerWord; 112 uintx bit_number = idx & (BitsPerWord - 1); 113 uintx the_bit = nth_bit(bit_number); 114 _bitmap[array_idx] |= the_bit; 115 } 116 117 inline void clear_bit(idx_t idx) { 118 assert((idx >= 0) && (idx < _num_bits), "precondition"); 119 assert(idx >= 0, "precondition"); 120 size_t array_idx = idx >> LogBitsPerWord; 121 uintx bit_number = idx & (BitsPerWord - 1); 122 uintx the_bit = nth_bit(bit_number); 123 _bitmap[array_idx] &= ~the_bit; 124 } 125 126 inline bool is_set(idx_t idx) const { 127 assert((idx >= 0) && (idx < _num_bits), "precondition"); 128 assert(idx >= 0, "precondition"); 129 size_t array_idx = idx >> LogBitsPerWord; 130 uintx bit_number = idx & (BitsPerWord - 1); 131 uintx the_bit = nth_bit(bit_number); 132 return (_bitmap[array_idx] & the_bit) != 0; 133 } 134 135 // Return the index of the first set bit in the range [beg, size()), or size() if none found. 136 // precondition: beg and end form a valid range for the bitmap. 137 inline idx_t find_first_set_bit(idx_t beg) const; 138 139 // Return the index of the first set bit in the range [beg, end), or end if none found. 140 // precondition: beg and end form a valid range for the bitmap. 141 inline idx_t find_first_set_bit(idx_t beg, idx_t end) const; 142 143 // Return the index of the last set bit in the range (-1, end], or -1 if none found. 144 // precondition: beg and end form a valid range for the bitmap. 145 inline idx_t find_last_set_bit(idx_t end) const; 146 147 // Return the index of the last set bit in the range (beg, end], or beg if none found. 148 // precondition: beg and end form a valid range for the bitmap. 149 inline idx_t find_last_set_bit(idx_t beg, idx_t end) const; 150 151 // Return the start index of the first run of <num_bits> consecutive set bits for which the first set bit is within 152 // the range [beg, size()), or size() if the run of <num_bits> is not found within this range. 153 // precondition: beg is within the valid range for the bitmap. 154 inline idx_t find_first_consecutive_set_bits(idx_t beg, size_t num_bits) const; 155 156 // Return the start index of the first run of <num_bits> consecutive set bits for which the first set bit is within 157 // the range [beg, end), or end if the run of <num_bits> is not found within this range. 158 // precondition: beg and end form a valid range for the bitmap. 159 idx_t find_first_consecutive_set_bits(idx_t beg, idx_t end, size_t num_bits) const; 160 161 // Return the start index of the last run of <num_bits> consecutive set bits for which the entire run of set bits is within 162 // the range (-1, end], or -1 if the run of <num_bits> is not found within this range. 163 // precondition: end is within the valid range for the bitmap. 164 inline idx_t find_last_consecutive_set_bits(idx_t end, size_t num_bits) const; 165 166 // Return the start index of the first run of <num_bits> consecutive set bits for which the entire run of set bits is within 167 // the range (beg, end], or beg if the run of <num_bits> is not found within this range. 168 // precondition: beg and end form a valid range for the bitmap. 169 idx_t find_last_consecutive_set_bits(idx_t beg, idx_t end, size_t num_bits) const; 170 }; 171 172 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP