/src/mozilla-central/js/src/jit/BitSet.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 | | * vim: set ts=8 sts=4 et sw=4 tw=99: |
3 | | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef jit_BitSet_h |
8 | | #define jit_BitSet_h |
9 | | |
10 | | #include "mozilla/MathAlgorithms.h" |
11 | | |
12 | | #include "jit/JitAllocPolicy.h" |
13 | | |
14 | | namespace js { |
15 | | namespace jit { |
16 | | |
17 | | // Provides constant time set insertion and removal, and fast linear |
18 | | // set operations such as intersection, difference, and union. |
19 | | // N.B. All set operations must be performed on sets with the same number |
20 | | // of bits. |
21 | | class BitSet |
22 | | { |
23 | | public: |
24 | | static const size_t BitsPerWord = 8 * sizeof(uint32_t); |
25 | | |
26 | 1.80k | static size_t RawLengthForBits(size_t bits) { |
27 | 1.80k | return (bits + BitsPerWord - 1) / BitsPerWord; |
28 | 1.80k | } |
29 | | |
30 | | private: |
31 | | uint32_t* bits_; |
32 | | const unsigned int numBits_; |
33 | | |
34 | 4.66k | static inline uint32_t bitForValue(unsigned int value) { |
35 | 4.66k | return 1l << uint32_t(value % BitsPerWord); |
36 | 4.66k | } |
37 | | |
38 | 4.66k | static inline unsigned int wordForValue(unsigned int value) { |
39 | 4.66k | return value / BitsPerWord; |
40 | 4.66k | } |
41 | | |
42 | 1.69k | inline unsigned int numWords() const { |
43 | 1.69k | return RawLengthForBits(numBits_); |
44 | 1.69k | } |
45 | | |
46 | | BitSet(const BitSet&) = delete; |
47 | | void operator=(const BitSet&) = delete; |
48 | | |
49 | | public: |
50 | | class Iterator; |
51 | | |
52 | | explicit BitSet(unsigned int numBits) : |
53 | | bits_(nullptr), |
54 | 98 | numBits_(numBits) {} |
55 | | |
56 | | MOZ_MUST_USE bool init(TempAllocator& alloc); |
57 | | |
58 | 0 | unsigned int getNumBits() const { |
59 | 0 | return numBits_; |
60 | 0 | } |
61 | | |
62 | | // O(1): Check if this set contains the given value. |
63 | 294 | bool contains(unsigned int value) const { |
64 | 294 | MOZ_ASSERT(bits_); |
65 | 294 | MOZ_ASSERT(value < numBits_); |
66 | 294 | |
67 | 294 | return !!(bits_[wordForValue(value)] & bitForValue(value)); |
68 | 294 | } |
69 | | |
70 | | // O(numBits): Check if this set contains any value. |
71 | | bool empty() const; |
72 | | |
73 | | // O(1): Insert the given value into this set. |
74 | 3.84k | void insert(unsigned int value) { |
75 | 3.84k | MOZ_ASSERT(bits_); |
76 | 3.84k | MOZ_ASSERT(value < numBits_); |
77 | 3.84k | |
78 | 3.84k | bits_[wordForValue(value)] |= bitForValue(value); |
79 | 3.84k | } |
80 | | |
81 | | // O(numBits): Insert every element of the given set into this set. |
82 | | void insertAll(const BitSet& other); |
83 | | |
84 | | // O(1): Remove the given value from this set. |
85 | 523 | void remove(unsigned int value) { |
86 | 523 | MOZ_ASSERT(bits_); |
87 | 523 | MOZ_ASSERT(value < numBits_); |
88 | 523 | |
89 | 523 | bits_[wordForValue(value)] &= ~bitForValue(value); |
90 | 523 | } |
91 | | |
92 | | // O(numBits): Remove the every element of the given set from this set. |
93 | | void removeAll(const BitSet& other); |
94 | | |
95 | | // O(numBits): Intersect this set with the given set. |
96 | | void intersect(const BitSet& other); |
97 | | |
98 | | // O(numBits): Intersect this set with the given set; return whether the |
99 | | // intersection caused the set to change. |
100 | | bool fixedPointIntersect(const BitSet& other); |
101 | | |
102 | | // O(numBits): Does inplace complement of the set. |
103 | | void complement(); |
104 | | |
105 | | // O(numBits): Clear this set. |
106 | | void clear(); |
107 | | |
108 | 552 | uint32_t* raw() const { |
109 | 552 | return bits_; |
110 | 552 | } |
111 | 552 | size_t rawLength() const { |
112 | 552 | return numWords(); |
113 | 552 | } |
114 | | }; |
115 | | |
116 | | class BitSet::Iterator |
117 | | { |
118 | | private: |
119 | | BitSet& set_; |
120 | | unsigned index_; |
121 | | unsigned word_; |
122 | | uint32_t value_; |
123 | | |
124 | 224 | void skipEmpty() { |
125 | 224 | // Skip words containing only zeros. |
126 | 224 | unsigned numWords = set_.numWords(); |
127 | 224 | const uint32_t* bits = set_.bits_; |
128 | 280 | while (value_ == 0) { |
129 | 112 | word_++; |
130 | 112 | if (word_ == numWords) { |
131 | 56 | return; |
132 | 56 | } |
133 | 56 | |
134 | 56 | index_ = word_ * BitSet::BitsPerWord; |
135 | 56 | value_ = bits[word_]; |
136 | 56 | } |
137 | 224 | |
138 | 224 | // Be careful: the result of CountTrailingZeroes32 is undefined if the |
139 | 224 | // input is 0. |
140 | 224 | int numZeros = mozilla::CountTrailingZeroes32(value_); |
141 | 168 | index_ += numZeros; |
142 | 168 | value_ >>= numZeros; |
143 | 168 | |
144 | 168 | MOZ_ASSERT_IF(index_ < set_.numBits_, set_.contains(index_)); |
145 | 168 | } |
146 | | |
147 | | public: |
148 | | explicit Iterator(BitSet& set) : |
149 | | set_(set), |
150 | | index_(0), |
151 | | word_(0), |
152 | | value_(set.bits_[0]) |
153 | 56 | { |
154 | 56 | skipEmpty(); |
155 | 56 | } |
156 | | |
157 | 224 | inline bool more() const { |
158 | 224 | return word_ < set_.numWords(); |
159 | 224 | } |
160 | 224 | explicit operator bool() const { |
161 | 224 | return more(); |
162 | 224 | } |
163 | | |
164 | 168 | inline void operator++() { |
165 | 168 | MOZ_ASSERT(more()); |
166 | 168 | MOZ_ASSERT(index_ < set_.numBits_); |
167 | 168 | |
168 | 168 | index_++; |
169 | 168 | value_ >>= 1; |
170 | 168 | |
171 | 168 | skipEmpty(); |
172 | 168 | } |
173 | | |
174 | 168 | unsigned int operator*() { |
175 | 168 | MOZ_ASSERT(index_ < set_.numBits_); |
176 | 168 | return index_; |
177 | 168 | } |
178 | | }; |
179 | | |
180 | | } // namespace jit |
181 | | } // namespace js |
182 | | |
183 | | #endif /* jit_BitSet_h */ |