|  | // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | #ifndef RUNTIME_VM_BIT_SET_H_ | 
|  | #define RUNTIME_VM_BIT_SET_H_ | 
|  |  | 
|  | #include "platform/utils.h" | 
|  | #include "vm/globals.h" | 
|  |  | 
|  | namespace dart { | 
|  |  | 
|  | // Just like its namesake in the STL, a BitSet object contains a fixed | 
|  | // length sequence of bits. | 
|  | template <intptr_t N> | 
|  | class BitSet { | 
|  | public: | 
|  | BitSet() { Reset(); } | 
|  |  | 
|  | void Set(intptr_t i, bool value) { | 
|  | ASSERT(i >= 0); | 
|  | ASSERT(i < N); | 
|  | uword mask = (static_cast<uword>(1) << (i & (kBitsPerWord - 1))); | 
|  | if (value) { | 
|  | data_[i >> kBitsPerWordLog2] |= mask; | 
|  | } else { | 
|  | data_[i >> kBitsPerWordLog2] &= ~mask; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool Test(intptr_t i) const { | 
|  | ASSERT(i >= 0); | 
|  | ASSERT(i < N); | 
|  | uword mask = (static_cast<uword>(1) << (i & (kBitsPerWord - 1))); | 
|  | return (data_[i >> kBitsPerWordLog2] & mask) != 0; | 
|  | } | 
|  |  | 
|  | intptr_t Next(intptr_t i) const { | 
|  | ASSERT(i >= 0); | 
|  | ASSERT(i < N); | 
|  | intptr_t w = i >> kBitsPerWordLog2; | 
|  | uword mask = ~static_cast<uword>(0) << (i & (kBitsPerWord - 1)); | 
|  | if ((data_[w] & mask) != 0) { | 
|  | uword tz = Utils::CountTrailingZerosWord(data_[w] & mask); | 
|  | return (w << kBitsPerWordLog2) + tz; | 
|  | } | 
|  | while (++w < kLengthInWords) { | 
|  | if (data_[w] != 0) { | 
|  | return (w << kBitsPerWordLog2) + | 
|  | Utils::CountTrailingZerosWord(data_[w]); | 
|  | } | 
|  | } | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | intptr_t Last() const { | 
|  | for (int w = kLengthInWords - 1; w >= 0; --w) { | 
|  | uword d = data_[w]; | 
|  | if (d != 0) { | 
|  | return ((w + 1) << kBitsPerWordLog2) - Utils::CountLeadingZerosWord(d) - | 
|  | 1; | 
|  | } | 
|  | } | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | intptr_t ClearLastAndFindPrevious(intptr_t current_last) { | 
|  | ASSERT(Test(current_last)); | 
|  | ASSERT(Last() == current_last); | 
|  | intptr_t w = current_last >> kBitsPerWordLog2; | 
|  | uword bits = data_[w]; | 
|  | // Clear the current last. | 
|  | bits ^= (static_cast<uword>(1) << (current_last & (kBitsPerWord - 1))); | 
|  | data_[w] = bits; | 
|  | // Search backwards for a non-zero word. | 
|  | while (bits == 0 && w > 0) { | 
|  | bits = data_[--w]; | 
|  | } | 
|  | if (bits == 0) { | 
|  | // None found. | 
|  | return -1; | 
|  | } else { | 
|  | // Bitlength incl. w, minus leading zeroes of w, minus 1 to 0-based index. | 
|  | return ((w + 1) << kBitsPerWordLog2) - | 
|  | Utils::CountLeadingZerosWord(bits) - 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | void Reset() { memset(data_, 0, sizeof(data_)); } | 
|  |  | 
|  | intptr_t Size() const { return N; } | 
|  |  | 
|  | private: | 
|  | static constexpr int kLengthInWords = 1 + ((N - 1) / kBitsPerWord); | 
|  | uword data_[kLengthInWords]; | 
|  | }; | 
|  |  | 
|  | }  // namespace dart | 
|  |  | 
|  | #endif  // RUNTIME_VM_BIT_SET_H_ |