diff options
author | Kostya Serebryany <kcc@google.com> | 2014-02-13 12:39:21 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2014-02-13 12:39:21 +0000 |
commit | d0caa6e878b2cd55343aaff572a96453ae4d9a64 (patch) | |
tree | 55f51da52fcad34d71f056018f897e5eb9c9ec7b /lib/sanitizer_common/sanitizer_bitvector.h | |
parent | 95e0ee58ffc6afc09f0a7a29b4a8fe02c74297bc (diff) |
[sanitizer] address some of the dvyukov's comments on previous commits
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@201322 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_bitvector.h')
-rw-r--r-- | lib/sanitizer_common/sanitizer_bitvector.h | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/lib/sanitizer_common/sanitizer_bitvector.h b/lib/sanitizer_common/sanitizer_bitvector.h index 5def7e1e6..cf7b8ccba 100644 --- a/lib/sanitizer_common/sanitizer_bitvector.h +++ b/lib/sanitizer_common/sanitizer_bitvector.h @@ -23,24 +23,29 @@ template <class basic_int_t = uptr> class BasicBitVector { public: enum SizeEnum { kSize = sizeof(basic_int_t) * 8 }; + uptr size() const { return kSize; } // No CTOR. void clear() { bits_ = 0; } void setAll() { bits_ = ~(basic_int_t)0; } bool empty() const { return bits_ == 0; } + // Returns true if the bit has changed from 0 to 1. bool setBit(uptr idx) { basic_int_t old = bits_; bits_ |= mask(idx); return bits_ != old; } + // Returns true if the bit has changed from 1 to 0. bool clearBit(uptr idx) { basic_int_t old = bits_; bits_ &= ~mask(idx); return bits_ != old; } + bool getBit(uptr idx) const { return bits_ & mask(idx); } + uptr getAndClearFirstOne() { CHECK(!empty()); // FIXME: change to LeastSignificantSetBitIndex? @@ -61,18 +66,17 @@ class BasicBitVector { // Returns true if 'this' intersects with 'v'. bool intersectsWith(const BasicBitVector &v) const { return bits_ & v.bits_; } - private: basic_int_t mask(uptr idx) const { - CHECK_LE(idx, size()); + CHECK_LT(idx, size()); return (basic_int_t)1UL << idx; } basic_int_t bits_; }; // Fixed size bit vector of (kLevel1Size*BV::kSize**2) bits. -// The implementation is optimized for a sparse bit vector, i.e. the one -// that has few set bits. +// The implementation is optimized for better performance on +// sparse bit vectors, i.e. the those with few set bits. template <uptr kLevel1Size = 1, class BV = BasicBitVector<> > class TwoLevelBitVector { // This is essentially a 2-level bit vector. @@ -83,11 +87,14 @@ class TwoLevelBitVector { public: enum SizeEnum { kSize = BV::kSize * BV::kSize * kLevel1Size }; // No CTOR. + uptr size() const { return kSize; } + void clear() { for (uptr i = 0; i < kLevel1Size; i++) l1_[i].clear(); } + void setAll() { for (uptr i0 = 0; i0 < kLevel1Size; i0++) { l1_[i0].setAll(); @@ -95,12 +102,14 @@ class TwoLevelBitVector { l2_[i0][i1].setAll(); } } + bool empty() { for (uptr i = 0; i < kLevel1Size; i++) if (!l1_[i].empty()) return false; return true; } + // Returns true if the bit has changed from 0 to 1. bool setBit(uptr idx) { check(idx); @@ -116,6 +125,7 @@ class TwoLevelBitVector { // idx, i0, i1, i2, res); return res; } + bool clearBit(uptr idx) { check(idx); uptr i0 = idx0(idx); @@ -129,6 +139,7 @@ class TwoLevelBitVector { } return res; } + bool getBit(uptr idx) const { check(idx); uptr i0 = idx0(idx); @@ -137,6 +148,7 @@ class TwoLevelBitVector { // Printf("%s: %zd => %zd %zd %zd\n", __FUNCTION__, idx, i0, i1, i2); return l1_[i0].getBit(i1) && l2_[i0][i1].getBit(i2); } + uptr getAndClearFirstOne() { for (uptr i0 = 0; i0 < kLevel1Size; i0++) { if (l1_[i0].empty()) continue; @@ -151,6 +163,7 @@ class TwoLevelBitVector { CHECK(0); return 0; } + // Do "this |= v" and return whether new bits have been added. bool setUnion(const TwoLevelBitVector &v) { bool res = false; @@ -176,6 +189,7 @@ class TwoLevelBitVector { bool intersectsWith(const TwoLevelBitVector &v) const { for (uptr i0 = 0; i0 < kLevel1Size; i0++) { BV t = l1_[i0]; + // FIXME: optimization: t &= v.l1_[i0] while (!t.empty()) { uptr i1 = t.getAndClearFirstOne(); if (!v.l1_[i0].getBit(i1)) continue; @@ -188,16 +202,19 @@ class TwoLevelBitVector { private: void check(uptr idx) const { CHECK_LE(idx, size()); } + uptr idx0(uptr idx) const { uptr res = idx / (BV::kSize * BV::kSize); CHECK_LE(res, kLevel1Size); return res; } + uptr idx1(uptr idx) const { uptr res = (idx / BV::kSize) % BV::kSize; CHECK_LE(res, BV::kSize); return res; } + uptr idx2(uptr idx) const { uptr res = idx % BV::kSize; CHECK_LE(res, BV::kSize); |