xref: /aosp_15_r20/art/libartbase/base/bit_vector.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_BIT_VECTOR_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_BIT_VECTOR_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <iterator>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "bit_utils.h"
25*795d594fSAndroid Build Coastguard Worker #include "globals.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art {
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker class Allocator;
30*795d594fSAndroid Build Coastguard Worker class ArenaBitVector;
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker /*
33*795d594fSAndroid Build Coastguard Worker  * Expanding bitmap. Bits are numbered starting from zero. All operations on a BitVector are
34*795d594fSAndroid Build Coastguard Worker  * unsynchronized. New BitVectors are not necessarily zeroed out. If the used allocator doesn't do
35*795d594fSAndroid Build Coastguard Worker  * clear the vector (e.g. ScopedArenaAllocator), the responsibility of clearing it relies on the
36*795d594fSAndroid Build Coastguard Worker  * caller (e.g. ArenaBitVector).
37*795d594fSAndroid Build Coastguard Worker  */
38*795d594fSAndroid Build Coastguard Worker class BitVector {
39*795d594fSAndroid Build Coastguard Worker  public:
40*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kWordBytes = sizeof(uint32_t);
41*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kWordBits = kWordBytes * 8;
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker   class IndexContainer;
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker   /**
46*795d594fSAndroid Build Coastguard Worker    * @brief Convenient iterator across the indexes of the BitVector's set bits.
47*795d594fSAndroid Build Coastguard Worker    *
48*795d594fSAndroid Build Coastguard Worker    * @details IndexIterator is a Forward iterator (C++11: 24.2.5) from the lowest
49*795d594fSAndroid Build Coastguard Worker    * to the highest index of the BitVector's set bits. Instances can be retrieved
50*795d594fSAndroid Build Coastguard Worker    * only through BitVector::Indexes() which returns an IndexContainer wrapper
51*795d594fSAndroid Build Coastguard Worker    * object with begin() and end() suitable for range-based loops:
52*795d594fSAndroid Build Coastguard Worker    *   for (uint32_t idx : bit_vector.Indexes()) {
53*795d594fSAndroid Build Coastguard Worker    *     // Use idx.
54*795d594fSAndroid Build Coastguard Worker    *   }
55*795d594fSAndroid Build Coastguard Worker    */
56*795d594fSAndroid Build Coastguard Worker   class IndexIterator {
57*795d594fSAndroid Build Coastguard Worker    public:
58*795d594fSAndroid Build Coastguard Worker     using iterator_category = std::forward_iterator_tag;
59*795d594fSAndroid Build Coastguard Worker     using value_type = uint32_t;
60*795d594fSAndroid Build Coastguard Worker     using difference_type = ptrdiff_t;
61*795d594fSAndroid Build Coastguard Worker     using pointer = void;
62*795d594fSAndroid Build Coastguard Worker     using reference = void;
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker     bool operator==(const IndexIterator& other) const;
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker     bool operator!=(const IndexIterator& other) const {
67*795d594fSAndroid Build Coastguard Worker       return !(*this == other);
68*795d594fSAndroid Build Coastguard Worker     }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker     uint32_t operator*() const;
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker     IndexIterator& operator++();
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker     IndexIterator operator++(int);
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker     // Helper function to check for end without comparing with bit_vector.Indexes().end().
Done()77*795d594fSAndroid Build Coastguard Worker     bool Done() const {
78*795d594fSAndroid Build Coastguard Worker       return bit_index_ == BitSize();
79*795d594fSAndroid Build Coastguard Worker     }
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker    private:
82*795d594fSAndroid Build Coastguard Worker     struct begin_tag { };
83*795d594fSAndroid Build Coastguard Worker     struct end_tag { };
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker     IndexIterator(const BitVector* bit_vector, begin_tag);
86*795d594fSAndroid Build Coastguard Worker     IndexIterator(const BitVector* bit_vector, end_tag);
87*795d594fSAndroid Build Coastguard Worker 
BitSize()88*795d594fSAndroid Build Coastguard Worker     uint32_t BitSize() const {
89*795d594fSAndroid Build Coastguard Worker       return storage_size_ * kWordBits;
90*795d594fSAndroid Build Coastguard Worker     }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker     uint32_t FindIndex(uint32_t start_index) const;
93*795d594fSAndroid Build Coastguard Worker     const uint32_t* const bit_storage_;
94*795d594fSAndroid Build Coastguard Worker     const uint32_t storage_size_;  // Size of vector in words.
95*795d594fSAndroid Build Coastguard Worker     uint32_t bit_index_;           // Current index (size in bits).
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker     friend class BitVector::IndexContainer;
98*795d594fSAndroid Build Coastguard Worker   };
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   /**
101*795d594fSAndroid Build Coastguard Worker    * @brief BitVector wrapper class for iteration across indexes of set bits.
102*795d594fSAndroid Build Coastguard Worker    */
103*795d594fSAndroid Build Coastguard Worker   class IndexContainer {
104*795d594fSAndroid Build Coastguard Worker    public:
IndexContainer(const BitVector * bit_vector)105*795d594fSAndroid Build Coastguard Worker     explicit IndexContainer(const BitVector* bit_vector) : bit_vector_(bit_vector) { }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker     IndexIterator begin() const;
108*795d594fSAndroid Build Coastguard Worker     IndexIterator end() const;
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker    private:
111*795d594fSAndroid Build Coastguard Worker     const BitVector* const bit_vector_;
112*795d594fSAndroid Build Coastguard Worker   };
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   // MoveConstructible but not MoveAssignable, CopyConstructible or CopyAssignable.
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker   BitVector(const BitVector& other) = delete;
117*795d594fSAndroid Build Coastguard Worker   BitVector& operator=(const BitVector& other) = delete;
118*795d594fSAndroid Build Coastguard Worker 
BitVector(BitVector && other)119*795d594fSAndroid Build Coastguard Worker   BitVector(BitVector&& other) noexcept
120*795d594fSAndroid Build Coastguard Worker       : storage_(other.storage_),
121*795d594fSAndroid Build Coastguard Worker         storage_size_(other.storage_size_),
122*795d594fSAndroid Build Coastguard Worker         allocator_(other.allocator_),
123*795d594fSAndroid Build Coastguard Worker         expandable_(other.expandable_) {
124*795d594fSAndroid Build Coastguard Worker     other.storage_ = nullptr;
125*795d594fSAndroid Build Coastguard Worker     other.storage_size_ = 0u;
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   BitVector(uint32_t start_bits,
129*795d594fSAndroid Build Coastguard Worker             bool expandable,
130*795d594fSAndroid Build Coastguard Worker             Allocator* allocator);
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker   BitVector(bool expandable,
133*795d594fSAndroid Build Coastguard Worker             Allocator* allocator,
134*795d594fSAndroid Build Coastguard Worker             uint32_t storage_size,
135*795d594fSAndroid Build Coastguard Worker             uint32_t* storage);
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker   BitVector(const BitVector& src,
138*795d594fSAndroid Build Coastguard Worker             bool expandable,
139*795d594fSAndroid Build Coastguard Worker             Allocator* allocator);
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker   virtual ~BitVector();
142*795d594fSAndroid Build Coastguard Worker 
143*795d594fSAndroid Build Coastguard Worker   // The number of words necessary to encode bits.
BitsToWords(uint32_t bits)144*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t BitsToWords(uint32_t bits) {
145*795d594fSAndroid Build Coastguard Worker     return RoundUp(bits, kWordBits) / kWordBits;
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker   // Mark the specified bit as "set".
SetBit(uint32_t idx)149*795d594fSAndroid Build Coastguard Worker   void SetBit(uint32_t idx) {
150*795d594fSAndroid Build Coastguard Worker     /*
151*795d594fSAndroid Build Coastguard Worker      * TUNING: this could have pathologically bad growth/expand behavior.  Make sure we're
152*795d594fSAndroid Build Coastguard Worker      * not using it badly or change resize mechanism.
153*795d594fSAndroid Build Coastguard Worker      */
154*795d594fSAndroid Build Coastguard Worker     if (idx >= storage_size_ * kWordBits) {
155*795d594fSAndroid Build Coastguard Worker       EnsureSize(idx);
156*795d594fSAndroid Build Coastguard Worker     }
157*795d594fSAndroid Build Coastguard Worker     storage_[WordIndex(idx)] |= BitMask(idx);
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   // Mark the specified bit as "unset".
ClearBit(uint32_t idx)161*795d594fSAndroid Build Coastguard Worker   void ClearBit(uint32_t idx) {
162*795d594fSAndroid Build Coastguard Worker     // If the index is over the size, we don't have to do anything, it is cleared.
163*795d594fSAndroid Build Coastguard Worker     if (idx < storage_size_ * kWordBits) {
164*795d594fSAndroid Build Coastguard Worker       // Otherwise, go ahead and clear it.
165*795d594fSAndroid Build Coastguard Worker       storage_[WordIndex(idx)] &= ~BitMask(idx);
166*795d594fSAndroid Build Coastguard Worker     }
167*795d594fSAndroid Build Coastguard Worker   }
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   // Determine whether or not the specified bit is set.
IsBitSet(uint32_t idx)170*795d594fSAndroid Build Coastguard Worker   bool IsBitSet(uint32_t idx) const {
171*795d594fSAndroid Build Coastguard Worker     // If the index is over the size, whether it is expandable or not, this bit does not exist:
172*795d594fSAndroid Build Coastguard Worker     // thus it is not set.
173*795d594fSAndroid Build Coastguard Worker     return (idx < (storage_size_ * kWordBits)) && IsBitSet(storage_, idx);
174*795d594fSAndroid Build Coastguard Worker   }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker   // Mark all bits bit as "clear".
177*795d594fSAndroid Build Coastguard Worker   void ClearAllBits();
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker   // Mark specified number of bits as "set". Cannot set all bits like ClearAll since there might
180*795d594fSAndroid Build Coastguard Worker   // be unused bits - setting those to one will confuse the iterator.
181*795d594fSAndroid Build Coastguard Worker   void SetInitialBits(uint32_t num_bits);
182*795d594fSAndroid Build Coastguard Worker 
183*795d594fSAndroid Build Coastguard Worker   void Copy(const BitVector* src);
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   // Intersect with another bit vector.
186*795d594fSAndroid Build Coastguard Worker   void Intersect(const BitVector* src2);
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker   // Union with another bit vector.
189*795d594fSAndroid Build Coastguard Worker   bool Union(const BitVector* src);
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker   // Set bits of union_with that are not in not_in.
192*795d594fSAndroid Build Coastguard Worker   bool UnionIfNotIn(const BitVector* union_with, const BitVector* not_in);
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   void Subtract(const BitVector* src);
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker   // Are we equal to another bit vector?  Note: expandability attributes must also match.
197*795d594fSAndroid Build Coastguard Worker   bool Equal(const BitVector* src) const;
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker   /**
200*795d594fSAndroid Build Coastguard Worker    * @brief Are all the bits set the same?
201*795d594fSAndroid Build Coastguard Worker    * @details expandability and size can differ as long as the same bits are set.
202*795d594fSAndroid Build Coastguard Worker    */
203*795d594fSAndroid Build Coastguard Worker   bool SameBitsSet(const BitVector *src) const;
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   bool IsSubsetOf(const BitVector *other) const;
206*795d594fSAndroid Build Coastguard Worker 
207*795d594fSAndroid Build Coastguard Worker   // Count the number of bits that are set.
208*795d594fSAndroid Build Coastguard Worker   uint32_t NumSetBits() const;
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   // Count the number of bits that are set in range [0, end).
211*795d594fSAndroid Build Coastguard Worker   uint32_t NumSetBits(uint32_t end) const;
212*795d594fSAndroid Build Coastguard Worker 
Indexes()213*795d594fSAndroid Build Coastguard Worker   IndexContainer Indexes() const {
214*795d594fSAndroid Build Coastguard Worker     return IndexContainer(this);
215*795d594fSAndroid Build Coastguard Worker   }
216*795d594fSAndroid Build Coastguard Worker 
GetStorageSize()217*795d594fSAndroid Build Coastguard Worker   uint32_t GetStorageSize() const {
218*795d594fSAndroid Build Coastguard Worker     return storage_size_;
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker 
IsExpandable()221*795d594fSAndroid Build Coastguard Worker   bool IsExpandable() const {
222*795d594fSAndroid Build Coastguard Worker     return expandable_;
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker 
GetRawStorageWord(size_t idx)225*795d594fSAndroid Build Coastguard Worker   uint32_t GetRawStorageWord(size_t idx) const {
226*795d594fSAndroid Build Coastguard Worker     return storage_[idx];
227*795d594fSAndroid Build Coastguard Worker   }
228*795d594fSAndroid Build Coastguard Worker 
GetRawStorage()229*795d594fSAndroid Build Coastguard Worker   uint32_t* GetRawStorage() {
230*795d594fSAndroid Build Coastguard Worker     return storage_;
231*795d594fSAndroid Build Coastguard Worker   }
232*795d594fSAndroid Build Coastguard Worker 
GetRawStorage()233*795d594fSAndroid Build Coastguard Worker   const uint32_t* GetRawStorage() const {
234*795d594fSAndroid Build Coastguard Worker     return storage_;
235*795d594fSAndroid Build Coastguard Worker   }
236*795d594fSAndroid Build Coastguard Worker 
GetSizeOf()237*795d594fSAndroid Build Coastguard Worker   size_t GetSizeOf() const {
238*795d594fSAndroid Build Coastguard Worker     return storage_size_ * kWordBytes;
239*795d594fSAndroid Build Coastguard Worker   }
240*795d594fSAndroid Build Coastguard Worker 
GetBitSizeOf()241*795d594fSAndroid Build Coastguard Worker   size_t GetBitSizeOf() const {
242*795d594fSAndroid Build Coastguard Worker     return storage_size_ * kWordBits;
243*795d594fSAndroid Build Coastguard Worker   }
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker   /**
246*795d594fSAndroid Build Coastguard Worker    * @return the highest bit set, -1 if none are set
247*795d594fSAndroid Build Coastguard Worker    */
248*795d594fSAndroid Build Coastguard Worker   int GetHighestBitSet() const;
249*795d594fSAndroid Build Coastguard Worker 
250*795d594fSAndroid Build Coastguard Worker   /**
251*795d594fSAndroid Build Coastguard Worker    * @return true if there are any bits set, false otherwise.
252*795d594fSAndroid Build Coastguard Worker    */
IsAnyBitSet()253*795d594fSAndroid Build Coastguard Worker   bool IsAnyBitSet() const {
254*795d594fSAndroid Build Coastguard Worker     return GetHighestBitSet() != -1;
255*795d594fSAndroid Build Coastguard Worker   }
256*795d594fSAndroid Build Coastguard Worker 
257*795d594fSAndroid Build Coastguard Worker   // Minimum number of bits required to store this vector, 0 if none are set.
GetNumberOfBits()258*795d594fSAndroid Build Coastguard Worker   size_t GetNumberOfBits() const {
259*795d594fSAndroid Build Coastguard Worker     return GetHighestBitSet() + 1;
260*795d594fSAndroid Build Coastguard Worker   }
261*795d594fSAndroid Build Coastguard Worker 
262*795d594fSAndroid Build Coastguard Worker   // Is bit set in storage. (No range check.)
IsBitSet(const uint32_t * storage,uint32_t idx)263*795d594fSAndroid Build Coastguard Worker   static bool IsBitSet(const uint32_t* storage, uint32_t idx) {
264*795d594fSAndroid Build Coastguard Worker     return (storage[WordIndex(idx)] & BitMask(idx)) != 0;
265*795d594fSAndroid Build Coastguard Worker   }
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   // Number of bits set in range [0, end) in storage. (No range check.)
268*795d594fSAndroid Build Coastguard Worker   static uint32_t NumSetBits(const uint32_t* storage, uint32_t end);
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   // Fill given memory region with the contents of the vector and zero padding.
CopyTo(void * dst,size_t len)271*795d594fSAndroid Build Coastguard Worker   void CopyTo(void* dst, size_t len) const {
272*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(static_cast<size_t>(GetHighestBitSet() + 1), len * kBitsPerByte);
273*795d594fSAndroid Build Coastguard Worker     size_t vec_len = GetSizeOf();
274*795d594fSAndroid Build Coastguard Worker     if (vec_len < len) {
275*795d594fSAndroid Build Coastguard Worker       void* dst_padding = reinterpret_cast<uint8_t*>(dst) + vec_len;
276*795d594fSAndroid Build Coastguard Worker       memcpy(dst, storage_, vec_len);
277*795d594fSAndroid Build Coastguard Worker       memset(dst_padding, 0, len - vec_len);
278*795d594fSAndroid Build Coastguard Worker     } else {
279*795d594fSAndroid Build Coastguard Worker       memcpy(dst, storage_, len);
280*795d594fSAndroid Build Coastguard Worker     }
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker   void Dump(std::ostream& os, const char* prefix) const;
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   Allocator* GetAllocator() const;
286*795d594fSAndroid Build Coastguard Worker 
287*795d594fSAndroid Build Coastguard Worker  private:
288*795d594fSAndroid Build Coastguard Worker   /**
289*795d594fSAndroid Build Coastguard Worker    * @brief Dump the bitvector into buffer in a 00101..01 format.
290*795d594fSAndroid Build Coastguard Worker    * @param buffer the ostringstream used to dump the bitvector into.
291*795d594fSAndroid Build Coastguard Worker    */
292*795d594fSAndroid Build Coastguard Worker   void DumpHelper(const char* prefix, std::ostringstream& buffer) const;
293*795d594fSAndroid Build Coastguard Worker 
294*795d594fSAndroid Build Coastguard Worker   // Ensure there is space for a bit at idx.
295*795d594fSAndroid Build Coastguard Worker   void EnsureSize(uint32_t idx);
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker   // The index of the word within storage.
WordIndex(uint32_t idx)298*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t WordIndex(uint32_t idx) {
299*795d594fSAndroid Build Coastguard Worker     return idx >> 5;
300*795d594fSAndroid Build Coastguard Worker   }
301*795d594fSAndroid Build Coastguard Worker 
302*795d594fSAndroid Build Coastguard Worker   // A bit mask to extract the bit for the given index.
BitMask(uint32_t idx)303*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t BitMask(uint32_t idx) {
304*795d594fSAndroid Build Coastguard Worker     return 1 << (idx & 0x1f);
305*795d594fSAndroid Build Coastguard Worker   }
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker   uint32_t*  storage_;            // The storage for the bit vector.
308*795d594fSAndroid Build Coastguard Worker   uint32_t   storage_size_;       // Current size, in 32-bit words.
309*795d594fSAndroid Build Coastguard Worker   Allocator* const allocator_;    // Allocator if expandable.
310*795d594fSAndroid Build Coastguard Worker   const bool expandable_;         // Should the bitmap expand if too small?
311*795d594fSAndroid Build Coastguard Worker };
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker }  // namespace art
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBARTBASE_BASE_BIT_VECTOR_H_
316