[heap] Fix more data races in bitmap SetRange and ClearRange.

This patch also changes String body descriptor to use synchronized
length and adds atomic live_bytes accessor.

BUG=chromium:694255

Change-Id: I41233b2097ec5c6a4ea2c45d4b8febf7ffca155e
Reviewed-on: https://chromium-review.googlesource.com/527093
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45761}
This commit is contained in:
Ulan Degenbaev 2017-06-07 14:21:43 +02:00 committed by Commit Bot
parent f2cd359ac9
commit 25f970370a
4 changed files with 26 additions and 13 deletions

View File

@ -197,10 +197,9 @@ class Bitmap {
// cell with 1s.
SetBitsInCell<mode>(start_cell_index, ~(start_index_mask - 1));
// Then fill all in between cells with 1s.
base::Atomic32* cell_base = reinterpret_cast<base::Atomic32*>(cells());
for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) {
// The callers must ensure that the inner cells in the range are not
// accessed concurrently.
cells()[i] = ~0u;
base::Relaxed_Store(cell_base + i, ~0u);
}
// Finally, fill all bits until the end address in the last cell with 1s.
SetBitsInCell<mode>(end_cell_index, (end_index_mask - 1));
@ -227,10 +226,9 @@ class Bitmap {
// cell with 0s.
ClearBitsInCell<mode>(start_cell_index, ~(start_index_mask - 1));
// Then fill all in between cells with 0s.
base::Atomic32* cell_base = reinterpret_cast<base::Atomic32*>(cells());
for (unsigned int i = start_cell_index + 1; i < end_cell_index; i++) {
// The callers must ensure that the inner cells in the range are not
// accessed concurrently.
cells()[i] = 0;
base::Relaxed_Store(cell_base + i, 0);
}
// Finally, set all bits until the end address in the last cell with 0s.
ClearBitsInCell<mode>(end_cell_index, (end_index_mask - 1));

View File

@ -1504,9 +1504,11 @@ void PagedSpace::EmptyAllocationInfo() {
// Clear the bits in the unused black area.
if (current_top != current_limit) {
MarkingState::Internal(page).bitmap()->ClearRange(
page->AddressToMarkbitIndex(current_top),
page->AddressToMarkbitIndex(current_limit));
MarkingState::Internal(page)
.bitmap()
->ClearRange<IncrementalMarking::kAtomicity>(
page->AddressToMarkbitIndex(current_top),
page->AddressToMarkbitIndex(current_limit));
MarkingState::Internal(page)
.IncrementLiveBytes<IncrementalMarking::kAtomicity>(
-static_cast<int>(current_limit - current_top));
@ -1595,7 +1597,8 @@ void PagedSpace::Verify(ObjectVisitor* visitor) {
CHECK(object->address() + size <= top);
end_of_previous_object = object->address() + size;
}
CHECK_LE(black_size, MarkingState::Internal(page).live_bytes());
CHECK_LE(black_size,
MarkingState::Internal(page).live_bytes<MarkBit::ATOMIC>());
}
CHECK(allocation_pointer_found_in_space);
}

View File

@ -695,7 +695,9 @@ class MarkingState {
}
Bitmap* bitmap() const { return bitmap_; }
intptr_t live_bytes() const { return *live_bytes_; }
template <MarkBit::AccessMode mode = MarkBit::NON_ATOMIC>
inline intptr_t live_bytes() const;
private:
Bitmap* bitmap_;
@ -714,6 +716,16 @@ inline void MarkingState::IncrementLiveBytes<MarkBit::ATOMIC>(
reinterpret_cast<base::AtomicNumber<intptr_t>*>(live_bytes_)->Increment(by);
}
template <>
inline intptr_t MarkingState::live_bytes<MarkBit::NON_ATOMIC>() const {
return *live_bytes_;
}
template <>
inline intptr_t MarkingState::live_bytes<MarkBit::ATOMIC>() const {
return reinterpret_cast<base::AtomicNumber<intptr_t>*>(live_bytes_)->Value();
}
// -----------------------------------------------------------------------------
// A page is a memory chunk of a size 1MB. Large object pages may be larger.
//

View File

@ -546,7 +546,7 @@ class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
static inline int SizeOf(Map* map, HeapObject* obj) {
SeqOneByteString* string = SeqOneByteString::cast(obj);
return string->SizeFor(string->length());
return string->SizeFor(string->synchronized_length());
}
};
@ -563,7 +563,7 @@ class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
static inline int SizeOf(Map* map, HeapObject* obj) {
SeqTwoByteString* string = SeqTwoByteString::cast(obj);
return string->SizeFor(string->length());
return string->SizeFor(string->synchronized_length());
}
};