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 violatee 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 public:
 84 
 85   inline idx_t aligned_index(idx_t idx) const {
 86     assert((idx >= 0) && (idx < _num_bits), "precondition");
 87     idx_t array_idx = idx & ~right_n_bits(LogBitsPerWord);
 88     return array_idx;
 89   }
 90 
 91   inline constexpr idx_t alignment() const {
 92     return BitsPerWord;
 93   }
 94 
 95   // For testing
 96   inline idx_t size() const {
 97     return _num_bits;
 98   }
 99 
100   // Return the word that holds idx bit and its neighboring bits.
101   inline uintx bits_at(idx_t idx) const {
102     assert((idx >= 0) && (idx < _num_bits), "precondition");
103     idx_t array_idx = idx >> LogBitsPerWord;
104     return _bitmap[array_idx];
105   }
106 
107   inline void set_bit(idx_t idx) {
108     assert((idx >= 0) && (idx < _num_bits), "precondition");
109     size_t array_idx = idx >> LogBitsPerWord;
110     uintx bit_number = idx & right_n_bits(LogBitsPerWord);
111     uintx the_bit = nth_bit(bit_number);
112     _bitmap[array_idx] |= the_bit;
113   }
114 
115   inline void clear_bit(idx_t idx) {
116     assert((idx >= 0) && (idx < _num_bits), "precondition");
117     assert(idx >= 0, "precondition");
118     size_t array_idx = idx >> LogBitsPerWord;
119     uintx bit_number = idx & right_n_bits(LogBitsPerWord);
120     uintx the_bit = nth_bit(bit_number);
121     _bitmap[array_idx] &= ~the_bit;
122   }
123 
124   inline bool is_set(idx_t idx) const {
125     assert((idx >= 0) && (idx < _num_bits), "precondition");
126     assert(idx >= 0, "precondition");
127     size_t array_idx = idx >> LogBitsPerWord;
128     uintx bit_number = idx & right_n_bits(LogBitsPerWord);
129     uintx the_bit = nth_bit(bit_number);
130     return (_bitmap[array_idx] & the_bit)? true: false;
131   }
132 
133   // Return the index of the first set bit in the range [beg, size()), or size() if none found.
134   // precondition: beg and end form a valid range for the bitmap.
135   inline idx_t find_first_set_bit(idx_t beg) const;
136 
137   // Return the index of the first set bit in the range [beg, end), or end if none found.
138   // precondition: beg and end form a valid range for the bitmap.
139   inline idx_t find_first_set_bit(idx_t beg, idx_t end) const;
140 
141   // Return the index of the last set bit in the range (-1, end], or -1 if none found.
142   // precondition: beg and end form a valid range for the bitmap.
143   inline idx_t find_last_set_bit(idx_t end) const;
144 
145   // Return the index of the last set bit in the range (beg, end], or beg if none found.
146   // precondition: beg and end form a valid range for the bitmap.
147   inline idx_t find_last_set_bit(idx_t beg, idx_t end) const;
148 
149   // Return the start index of the first run of <num_bits> consecutive set bits for which the first set bit is within
150   //   the range [beg, size()), or size() if the run of <num_bits> is not found within this range.
151   // precondition: beg is within the valid range for the bitmap.
152   inline idx_t find_first_consecutive_set_bits(idx_t beg, size_t num_bits) const;
153 
154   // Return the start index of the first run of <num_bits> consecutive set bits for which the first set bit is within
155   //   the range [beg, end), or end if the run of <num_bits> is not found within this range.
156   // precondition: beg and end form a valid range for the bitmap.
157   idx_t find_first_consecutive_set_bits(idx_t beg, idx_t end, size_t num_bits) const;
158 
159   // Return the start index of the last run of <num_bits> consecutive set bits for which the entire run of set bits is within
160   // the range (-1, end], or -1 if the run of <num_bits> is not found within this range.
161   // precondition: end is within the valid range for the bitmap.
162   inline idx_t find_last_consecutive_set_bits(idx_t end, size_t num_bits) const;
163 
164   // Return the start index of the first run of <num_bits> consecutive set bits for which the entire run of set bits is within
165   // the range (beg, end], or beg if the run of <num_bits> is not found within this range.
166   // precondition: beg and end form a valid range for the bitmap.
167   idx_t find_last_consecutive_set_bits(idx_t beg, idx_t end, size_t num_bits) const;
168 };
169 
170 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP