Coverage Report

Created: 2018-09-25 14:53

/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 */