Index: runtime/vm/bitmap.cc |
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc |
index 479c780546c495db9e288d449a92f310c0c7ad7c..ae114d8f74416b9ace72d2b6273690b00cd65fef 100644 |
--- a/runtime/vm/bitmap.cc |
+++ b/runtime/vm/bitmap.cc |
@@ -9,49 +9,58 @@ |
namespace dart { |
-bool BitmapBuilder::Get(intptr_t bit_offset) const { |
- if (!InRange(bit_offset)) { |
- return false; |
- } |
- return GetBit(bit_offset); |
-} |
- |
- |
-void BitmapBuilder::Set(intptr_t bit_offset, bool value) { |
- while (!InRange(bit_offset)) { |
- intptr_t new_size = size_in_bytes_ + kIncrementSizeInBytes; |
- ASSERT(new_size > 0); |
- uint8_t* new_bit_list = |
- Isolate::Current()->current_zone()->Alloc<uint8_t>(new_size); |
- ASSERT(new_bit_list != NULL); |
- ASSERT(bit_list_ != NULL); |
- uint8_t* old_bit_list = bit_list_; |
- memmove(new_bit_list, old_bit_list, size_in_bytes_); |
- memset((new_bit_list + size_in_bytes_), 0, kIncrementSizeInBytes); |
- size_in_bytes_ = new_size; |
- bit_list_ = new_bit_list; |
+void BitmapBuilder::SetLength(intptr_t new_length) { |
+ // When this function is used to shorten the length, affected bits in the |
+ // backing store need to be cleared because the implementation assumes it. |
+ if (new_length < length_) { |
+ // Byte offset containing the first bit to be cleared. |
+ intptr_t byte_offset = new_length >> kBitsPerByteLog2; |
+ if (byte_offset < data_size_in_bytes_) { |
+ // First bit index (in the byte) to be cleared. |
+ intptr_t bit_index = new_length & (kBitsPerByte - 1); |
+ intptr_t mask = (1 << bit_index) - 1; |
+ data_[byte_offset] &= mask; |
+ // Clear the rest. |
+ ++byte_offset; |
+ if (byte_offset < data_size_in_bytes_) { |
+ memset(&data_[byte_offset], 0, data_size_in_bytes_ - byte_offset); |
+ } |
+ } |
} |
- SetBit(bit_offset, value); |
+ length_ = new_length; |
} |
-// Return the bit offset of the highest bit set. |
-intptr_t BitmapBuilder::Maximum() const { |
- intptr_t bound = SizeInBits(); |
- for (intptr_t i = (bound - 1); i >= 0; i--) { |
- if (Get(i)) return i; |
- } |
- return Stackmap::kNoMaximum; |
+bool BitmapBuilder::Get(intptr_t bit_offset) const { |
+ ASSERT(InRange(bit_offset)); |
+ intptr_t byte_offset = bit_offset >> kBitsPerByteLog2; |
+ // Bits not covered by the backing store are implicitly false. |
+ return (byte_offset < data_size_in_bytes_) && GetBit(bit_offset); |
} |
-// Return the bit offset of the lowest bit set. |
-intptr_t BitmapBuilder::Minimum() const { |
- intptr_t bound = SizeInBits(); |
- for (intptr_t i = 0; i < bound; i++) { |
- if (Get(i)) return i; |
+void BitmapBuilder::Set(intptr_t bit_offset, bool value) { |
+ ASSERT(bit_offset >= 0); |
+ if (!InRange(bit_offset)) { |
+ length_ = bit_offset + 1; |
+ // Bits not covered by the backing store are implicitly false. |
+ if (!value) return; |
+ // Grow the backing store if necessary. |
+ intptr_t byte_offset = bit_offset >> kBitsPerByteLog2; |
+ if (byte_offset >= data_size_in_bytes_) { |
+ uint8_t* old_data = data_; |
+ intptr_t old_size = data_size_in_bytes_; |
+ data_size_in_bytes_ = |
+ Utils::RoundUp(byte_offset + 1, kIncrementSizeInBytes); |
+ ASSERT(data_size_in_bytes_ > 0); |
+ data_ = Isolate::Current()->current_zone()->Alloc<uint8_t>( |
+ data_size_in_bytes_); |
+ ASSERT(data_ != NULL); |
+ memmove(data_, old_data, old_size); |
+ memset(&data_[old_size], 0, (data_size_in_bytes_ - old_size)); |
+ } |
} |
- return Stackmap::kNoMinimum; |
+ SetBit(bit_offset, value); |
} |
@@ -64,26 +73,26 @@ void BitmapBuilder::SetRange(intptr_t min, intptr_t max, bool value) { |
bool BitmapBuilder::GetBit(intptr_t bit_offset) const { |
ASSERT(InRange(bit_offset)); |
- int byte_offset = bit_offset >> kBitsPerByteLog2; |
- int bit_remainder = bit_offset & (kBitsPerByte - 1); |
+ intptr_t byte_offset = bit_offset >> kBitsPerByteLog2; |
+ ASSERT(byte_offset < data_size_in_bytes_); |
+ intptr_t bit_remainder = bit_offset & (kBitsPerByte - 1); |
uint8_t mask = 1U << bit_remainder; |
- ASSERT(bit_list_ != NULL); |
- return ((bit_list_[byte_offset] & mask) != 0); |
+ ASSERT(data_ != NULL); |
+ return ((data_[byte_offset] & mask) != 0); |
} |
void BitmapBuilder::SetBit(intptr_t bit_offset, bool value) { |
ASSERT(InRange(bit_offset)); |
int byte_offset = bit_offset >> kBitsPerByteLog2; |
+ ASSERT(byte_offset < data_size_in_bytes_); |
int bit_remainder = bit_offset & (kBitsPerByte - 1); |
uint8_t mask = 1U << bit_remainder; |
- uint8_t* byte_addr; |
- ASSERT(bit_list_ != NULL); |
- byte_addr = &(bit_list_[byte_offset]); |
+ ASSERT(data_ != NULL); |
if (value) { |
- *byte_addr |= mask; |
+ data_[byte_offset] |= mask; |
} else { |
- *byte_addr &= ~mask; |
+ data_[byte_offset] &= ~mask; |
} |
} |