Fix transferal of marking bits on array trimming.

R=vegorov@chromium.org
BUG=v8:1708
TEST=mjsunit/regress/regress-1708

Review URL: http://codereview.chromium.org/7979038

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9394 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c6a3422c
...@@ -382,41 +382,40 @@ bool Marking::TransferMark(Address old_start, Address new_start) { ...@@ -382,41 +382,40 @@ bool Marking::TransferMark(Address old_start, Address new_start) {
// This is only used when resizing an object. // This is only used when resizing an object.
ASSERT(MemoryChunk::FromAddress(old_start) == ASSERT(MemoryChunk::FromAddress(old_start) ==
MemoryChunk::FromAddress(new_start)); MemoryChunk::FromAddress(new_start));
// If the mark doesn't move, we don't check the color of the object. // If the mark doesn't move, we don't check the color of the object.
// It doesn't matter whether the object is black, since it hasn't changed // It doesn't matter whether the object is black, since it hasn't changed
// size, so the adjustment to the live data count will be zero anyway. // size, so the adjustment to the live data count will be zero anyway.
if (old_start == new_start) return false; if (old_start == new_start) return false;
MarkBit new_mark_bit = MarkBitFrom(new_start); MarkBit new_mark_bit = MarkBitFrom(new_start);
MarkBit old_mark_bit = MarkBitFrom(old_start);
if (heap_->incremental_marking()->IsMarking()) {
MarkBit old_mark_bit = MarkBitFrom(old_start);
#ifdef DEBUG #ifdef DEBUG
ObjectColor old_color = Color(old_mark_bit); ObjectColor old_color = Color(old_mark_bit);
#endif #endif
if (Marking::IsBlack(old_mark_bit)) {
Marking::MarkBlack(new_mark_bit); if (Marking::IsBlack(old_mark_bit)) {
old_mark_bit.Clear(); old_mark_bit.Clear();
return true; ASSERT(IsWhite(old_mark_bit));
} else if (Marking::IsGrey(old_mark_bit)) { Marking::MarkBlack(new_mark_bit);
old_mark_bit.Next().Clear(); return true;
heap_->incremental_marking()->WhiteToGreyAndPush( } else if (Marking::IsGrey(old_mark_bit)) {
HeapObject::FromAddress(new_start), new_mark_bit); ASSERT(heap_->incremental_marking()->IsMarking());
heap_->incremental_marking()->RestartIfNotMarking(); old_mark_bit.Clear();
} old_mark_bit.Next().Clear();
ASSERT(IsWhite(old_mark_bit));
heap_->incremental_marking()->WhiteToGreyAndPush(
HeapObject::FromAddress(new_start), new_mark_bit);
heap_->incremental_marking()->RestartIfNotMarking();
}
#ifdef DEBUG #ifdef DEBUG
ObjectColor new_color = Color(new_mark_bit); ObjectColor new_color = Color(new_mark_bit);
ASSERT(new_color == old_color); ASSERT(new_color == old_color);
#endif #endif
return false;
} return false;
MarkBit old_mark_bit = MarkBitFrom(old_start);
if (!old_mark_bit.Get()) {
return false;
}
new_mark_bit.Set();
return true;
} }
...@@ -3254,6 +3253,9 @@ static inline Address DigestFreeStart(Address approximate_free_start, ...@@ -3254,6 +3253,9 @@ static inline Address DigestFreeStart(Address approximate_free_start,
uint32_t free_start_cell) { uint32_t free_start_cell) {
ASSERT(free_start_cell != 0); ASSERT(free_start_cell != 0);
// No consecutive 1 bits.
ASSERT((free_start_cell & (free_start_cell << 1)) == 0);
int offsets[16]; int offsets[16];
uint32_t cell = free_start_cell; uint32_t cell = free_start_cell;
int offset_of_last_live; int offset_of_last_live;
...@@ -3284,6 +3286,9 @@ static inline Address DigestFreeStart(Address approximate_free_start, ...@@ -3284,6 +3286,9 @@ static inline Address DigestFreeStart(Address approximate_free_start,
static inline Address StartOfLiveObject(Address block_address, uint32_t cell) { static inline Address StartOfLiveObject(Address block_address, uint32_t cell) {
ASSERT(cell != 0); ASSERT(cell != 0);
// No consecutive 1 bits.
ASSERT((cell & (cell << 1)) == 0);
int offsets[16]; int offsets[16];
if (cell == 0x80000000u) { // Avoid overflow below. if (cell == 0x80000000u) { // Avoid overflow below.
return block_address + 31 * kPointerSize; return block_address + 31 * kPointerSize;
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Regression test of a very rare corner case where left-trimming an
// array caused invalid marking bit patterns on lazily swept pages.
// Flags: --expose-gc --noincremental-marking --max-new-space-size 1000
(function() {
var head = new Array(1);
var tail = head;
// Fill heap to increase old-space size and trigger lazy sweeping on
// some of the old-space pages.
for (var i = 0; i < 200; i++) {
tail[1] = new Array(1000);
tail = tail[1];
}
array = new Array(100);
gc(); gc();
// At this point "array" should have been promoted to old-space and be
// located in a lazy swept page with intact marking bits. Now shift
// the array to trigger left-trimming operations.
assertEquals(100, array.length);
for (var i = 0; i < 50; i++) {
array.shift();
}
assertEquals(50, array.length);
// At this point "array" should have been trimmed from the left with
// marking bits being correctly transfered to the new object start.
// Scavenging operations cause lazy sweeping to advance and verify
// that marking bit patterns are still sane.
for (var i = 0; i < 200; i++) {
tail[1] = new Array(1000);
tail = tail[1];
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment