[heap] Fix mark bits for partially compacted pages.
See bug report. R=ulan@chromium.org BUG=chromium:538567 LOG=N Review URL: https://codereview.chromium.org/1393293002 Cr-Commit-Position: refs/heads/master@{#31179}
This commit is contained in:
parent
9d2e21775c
commit
3feba64470
@ -3349,6 +3349,12 @@ bool MarkCompactCollector::EvacuateLiveObjectsFromPage(
|
||||
HeapObject* target_object = nullptr;
|
||||
AllocationResult allocation = target_space->AllocateRaw(size, alignment);
|
||||
if (!allocation.To(&target_object)) {
|
||||
// We need to abort compaction for this page. Make sure that we reset
|
||||
// the mark bits for objects that have already been migrated.
|
||||
if (i > 0) {
|
||||
p->markbits()->ClearRange(p->AddressToMarkbitIndex(p->area_start()),
|
||||
p->AddressToMarkbitIndex(object_addr));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -165,6 +165,10 @@ class Bitmap {
|
||||
return index >> kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
V8_INLINE static uint32_t IndexInCell(uint32_t index) {
|
||||
return index & kBitIndexMask;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t CellToIndex(uint32_t index)) {
|
||||
return index << kBitsPerCellLog2;
|
||||
}
|
||||
@ -184,7 +188,7 @@ class Bitmap {
|
||||
}
|
||||
|
||||
inline MarkBit MarkBitFromIndex(uint32_t index) {
|
||||
MarkBit::CellType mask = 1 << (index & kBitIndexMask);
|
||||
MarkBit::CellType mask = 1u << IndexInCell(index);
|
||||
MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
|
||||
return MarkBit(cell, mask);
|
||||
}
|
||||
@ -256,6 +260,23 @@ class Bitmap {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clears all bits starting from {cell_base_index} up to and excluding
|
||||
// {index}. Note that {cell_base_index} is required to be cell aligned.
|
||||
void ClearRange(uint32_t cell_base_index, uint32_t index) {
|
||||
DCHECK_EQ(IndexInCell(cell_base_index), 0);
|
||||
DCHECK_GE(index, cell_base_index);
|
||||
uint32_t start_cell_index = IndexToCell(cell_base_index);
|
||||
uint32_t end_cell_index = IndexToCell(index);
|
||||
DCHECK_GE(end_cell_index, start_cell_index);
|
||||
// Clear all cells till the cell containing the last index.
|
||||
for (uint32_t i = start_cell_index; i < end_cell_index; i++) {
|
||||
cells()[i] = 0;
|
||||
}
|
||||
// Clear all bits in the last cell till the last bit before index.
|
||||
uint32_t clear_mask = ~((1u << IndexInCell(index)) - 1);
|
||||
cells()[end_cell_index] &= clear_mask;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
107
test/unittests/heap/bitmap-unittest.cc
Normal file
107
test/unittests/heap/bitmap-unittest.cc
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/heap/spaces.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using v8::internal::Bitmap;
|
||||
|
||||
class BitmapTest : public ::testing::Test {
|
||||
public:
|
||||
static const uint32_t kBlackCell;
|
||||
static const uint32_t kWhiteCell;
|
||||
static const uint32_t kBlackByte;
|
||||
static const uint32_t kWhiteByte;
|
||||
|
||||
BitmapTest() : memory_(new uint8_t[Bitmap::kSize]) {
|
||||
memset(memory_, 0, Bitmap::kSize);
|
||||
}
|
||||
|
||||
virtual ~BitmapTest() { delete[] memory_; }
|
||||
|
||||
Bitmap* bitmap() { return reinterpret_cast<Bitmap*>(memory_); }
|
||||
uint8_t* raw_bitmap() { return memory_; }
|
||||
|
||||
private:
|
||||
uint8_t* memory_;
|
||||
};
|
||||
|
||||
|
||||
const uint32_t BitmapTest::kBlackCell = 0xAAAAAAAA;
|
||||
const uint32_t BitmapTest::kWhiteCell = 0x00000000;
|
||||
const uint32_t BitmapTest::kBlackByte = 0xAA;
|
||||
const uint32_t BitmapTest::kWhiteByte = 0x00;
|
||||
|
||||
|
||||
TEST_F(BitmapTest, IsZeroInitialized) {
|
||||
// We require all tests to start from a zero-initialized bitmap. Manually
|
||||
// verify this invariant here.
|
||||
for (size_t i = 0; i < Bitmap::kSize; i++) {
|
||||
EXPECT_EQ(raw_bitmap()[i], kWhiteByte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BitmapTest, Cells) {
|
||||
Bitmap* bm = bitmap();
|
||||
bm->cells()[1] = kBlackCell;
|
||||
uint8_t* raw = raw_bitmap();
|
||||
int second_cell_base = Bitmap::kBytesPerCell;
|
||||
for (size_t i = 0; i < Bitmap::kBytesPerCell; i++) {
|
||||
EXPECT_EQ(raw[second_cell_base + i], kBlackByte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BitmapTest, CellsCount) {
|
||||
int last_cell_index = bitmap()->CellsCount() - 1;
|
||||
bitmap()->cells()[last_cell_index] = kBlackCell;
|
||||
// Manually verify on raw memory.
|
||||
uint8_t* raw = raw_bitmap();
|
||||
for (size_t i = 0; i < Bitmap::kSize; i++) {
|
||||
// Last cell should be set.
|
||||
if (i >= (Bitmap::kSize - Bitmap::kBytesPerCell)) {
|
||||
EXPECT_EQ(raw[i], kBlackByte);
|
||||
} else {
|
||||
EXPECT_EQ(raw[i], kWhiteByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BitmapTest, IsClean) {
|
||||
Bitmap* bm = bitmap();
|
||||
EXPECT_TRUE(bm->IsClean());
|
||||
bm->cells()[0] = kBlackCell;
|
||||
EXPECT_FALSE(bm->IsClean());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BitmapTest, ClearRange1) {
|
||||
Bitmap* bm = bitmap();
|
||||
bm->cells()[0] = kBlackCell;
|
||||
bm->cells()[1] = kBlackCell;
|
||||
bm->cells()[2] = kBlackCell;
|
||||
bm->ClearRange(0, Bitmap::kBitsPerCell + Bitmap::kBitsPerCell / 2);
|
||||
EXPECT_EQ(bm->cells()[0], kWhiteCell);
|
||||
EXPECT_EQ(bm->cells()[1], 0xAAAA0000);
|
||||
EXPECT_EQ(bm->cells()[2], kBlackCell);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(BitmapTest, ClearRange2) {
|
||||
Bitmap* bm = bitmap();
|
||||
bm->cells()[0] = kBlackCell;
|
||||
bm->cells()[1] = kBlackCell;
|
||||
bm->cells()[2] = kBlackCell;
|
||||
bm->ClearRange(Bitmap::kBitsPerCell,
|
||||
Bitmap::kBitsPerCell + Bitmap::kBitsPerCell / 2);
|
||||
EXPECT_EQ(bm->cells()[0], kBlackCell);
|
||||
EXPECT_EQ(bm->cells()[1], 0xAAAA0000);
|
||||
EXPECT_EQ(bm->cells()[2], kBlackCell);
|
||||
}
|
||||
|
||||
} // namespace
|
@ -103,6 +103,7 @@
|
||||
'libplatform/default-platform-unittest.cc',
|
||||
'libplatform/task-queue-unittest.cc',
|
||||
'libplatform/worker-thread-unittest.cc',
|
||||
'heap/bitmap-unittest.cc',
|
||||
'heap/gc-idle-time-handler-unittest.cc',
|
||||
'heap/memory-reducer-unittest.cc',
|
||||
'heap/heap-unittest.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user