Revision: 9338
Author: [email protected]
Date: Tue Sep 20 04:20:00 2011
Log: Fix calculation of live-bytes in pages.
The "live bytes" count is *really* a "marked black" count - i.e., the count
of bytes *known* to be live.
Fix aggravating bug on X64 where assembler code used a value that was off
by a factor of 2^31.
Ensure that sweeping clears live-bytes. Added other missing increments.
Added print statements to trace live-byte modifications, under a flag.
Still a few cases of undercounting left.
(New issue to merge from GC branch to bleeding_edge)
Review URL: http://codereview.chromium.org/7970009
http://code.google.com/p/v8/source/detail?r=9338
Modified:
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/incremental-marking-inl.h
/branches/bleeding_edge/src/incremental-marking.cc
/branches/bleeding_edge/src/incremental-marking.h
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/mark-compact.h
/branches/bleeding_edge/src/spaces.cc
/branches/bleeding_edge/src/spaces.h
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/test/mjsunit/mjsunit.status
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/flag-definitions.h Tue Sep 20 04:20:00 2011
@@ -459,6 +459,9 @@
DEFINE_bool(trace_isolates, false, "trace isolate state changes")
+DEFINE_bool(trace_live_byte_count, false,
+ "trace updates to page live byte count")
+
// VM state
DEFINE_bool(log_state_changes, false, "Log state changes.")
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Sep 20
03:06:23 2011
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Sep 20
04:20:00 2011
@@ -2595,7 +2595,7 @@
ASSERT(SeqAsciiString::kMaxSize <=
static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
imul(length, FieldOperand(value, String::kLengthOffset));
- shr(length, 2 + kSmiTagSize);
+ shr(length, 2 + kSmiTagSize + kSmiShiftSize);
add(Operand(length),
Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
and_(Operand(length),
@@ -2609,6 +2609,11 @@
and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
length);
+ if (FLAG_debug_code) {
+ mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
+ cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
+ Check(less_equal, "Live Bytes Count overflow chunk size");
+ }
bind(&done);
}
=======================================
--- /branches/bleeding_edge/src/incremental-marking-inl.h Mon Sep 19
11:36:47 2011
+++ /branches/bleeding_edge/src/incremental-marking-inl.h Tue Sep 20
04:20:00 2011
@@ -114,8 +114,10 @@
ASSERT(obj->Size() >= 2*kPointerSize);
ASSERT(IsMarking());
Marking::BlackToGrey(mark_bit);
+ int obj_size = obj->Size();
+ MemoryChunk::IncrementLiveBytes(obj->address(), -obj_size);
int64_t old_bytes_rescanned = bytes_rescanned_;
- bytes_rescanned_ = old_bytes_rescanned + obj->Size();
+ bytes_rescanned_ = old_bytes_rescanned + obj_size;
if ((bytes_rescanned_ >> 20) != (old_bytes_rescanned >> 20)) {
if (bytes_rescanned_ > 2 * heap_->PromotedSpaceSize()) {
// If we have queued twice the heap size for rescanning then we are
=======================================
--- /branches/bleeding_edge/src/incremental-marking.cc Tue Sep 20 03:08:39
2011
+++ /branches/bleeding_edge/src/incremental-marking.cc Tue Sep 20 04:20:00
2011
@@ -403,7 +403,12 @@
static void MarkObjectGreyDoNotEnqueue(Object* obj) {
if (obj->IsHeapObject()) {
+ HeapObject* heap_obj = HeapObject::cast(obj);
MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj));
+ if (Marking::IsBlack(mark_bit)) {
+ MemoryChunk::IncrementLiveBytes(heap_obj->address(),
+ -heap_obj->Size());
+ }
Marking::AnyToGrey(mark_bit);
}
}
@@ -569,14 +574,20 @@
}
if (FLAG_cleanup_code_caches_at_gc) {
-
Marking::GreyToBlack(Marking::MarkBitFrom(heap_->polymorphic_code_cache()));
+ PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache();
+ Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache));
+ MemoryChunk::IncrementLiveBytes(poly_cache->address(),
+ PolymorphicCodeCache::kSize);
}
Object* context = heap_->global_contexts_list();
while (!context->IsUndefined()) {
NormalizedMapCache* cache =
Context::cast(context)->normalized_map_cache();
MarkBit mark_bit = Marking::MarkBitFrom(cache);
- if (Marking::IsGrey(mark_bit)) Marking::GreyToBlack(mark_bit);
+ if (Marking::IsGrey(mark_bit)) {
+ Marking::GreyToBlack(mark_bit);
+ MemoryChunk::IncrementLiveBytes(cache->address(), cache->Size());
+ }
context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
}
}
=======================================
--- /branches/bleeding_edge/src/incremental-marking.h Mon Sep 19 11:36:47
2011
+++ /branches/bleeding_edge/src/incremental-marking.h Tue Sep 20 04:20:00
2011
@@ -138,13 +138,16 @@
inline void WhiteToGrey(HeapObject* obj, MarkBit mark_bit);
- // Does white->black or grey->grey
+ // Does white->black or keeps gray or black color. Returns true if
converting
+ // white to black.
inline bool MarkBlackOrKeepGrey(MarkBit mark_bit) {
ASSERT(!Marking::IsImpossible(mark_bit));
- if (mark_bit.Get()) return false;
+ if (mark_bit.Get()) {
+ // Grey or black: Keep the color.
+ return false;
+ }
mark_bit.Set();
- ASSERT(!Marking::IsWhite(mark_bit));
- ASSERT(!Marking::IsImpossible(mark_bit));
+ ASSERT(Marking::IsBlack(mark_bit));
return true;
}
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Tue Sep 20 03:08:39 2011
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Sep 20 04:20:00 2011
@@ -295,7 +295,8 @@
while (it.has_next()) {
Page* p = it.next();
- ASSERT(p->markbits()->IsClean());
+ CHECK(p->markbits()->IsClean());
+ CHECK_EQ(0, p->LiveBytes());
}
}
@@ -304,7 +305,8 @@
while (it.has_next()) {
NewSpacePage* p = it.next();
- ASSERT(p->markbits()->IsClean());
+ CHECK(p->markbits()->IsClean());
+ CHECK_EQ(0, p->LiveBytes());
}
}
@@ -402,7 +404,7 @@
}
-static const char* AllocationSpaceName(AllocationSpace space) {
+const char* AllocationSpaceName(AllocationSpace space) {
switch (space) {
case NEW_SPACE: return "NEW_SPACE";
case OLD_POINTER_SPACE: return "OLD_POINTER_SPACE";
@@ -2528,9 +2530,10 @@
MarkBit mark_bit = Marking::MarkBitFrom(object);
if (mark_bit.Get()) {
mark_bit.Clear();
+ // Don't bother decrementing live bytes count. We'll discard the
+ // entire page at the end.
int size = object->Size();
survivors_size += size;
- MemoryChunk::IncrementLiveBytes(object->address(), -size);
// Aggressively promote young survivors to the old space.
if (TryPromoteObject(object, size)) {
@@ -2621,6 +2624,7 @@
// Clear marking bits for current cell.
cells[cell_index] = 0;
}
+ p->ResetLiveBytes();
}
@@ -2819,6 +2823,7 @@
if (free_start != p->ObjectAreaEnd()) {
space->Free(free_start, static_cast<int>(p->ObjectAreaEnd() -
free_start));
}
+ p->ResetLiveBytes();
}
@@ -3308,6 +3313,7 @@
if (cell_index == last_cell_index) {
freed_bytes += static_cast<int>(space->Free(p->ObjectAreaStart(),
static_cast<int>(size)));
+ ASSERT_EQ(0, p->LiveBytes());
return freed_bytes;
}
// Grow the size of the start-of-page free space a little to get up to
the
@@ -3364,6 +3370,7 @@
static_cast<int>(block_address -
free_start));
}
+ p->ResetLiveBytes();
return freed_bytes;
}
=======================================
--- /branches/bleeding_edge/src/mark-compact.h Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/mark-compact.h Tue Sep 20 04:20:00 2011
@@ -765,6 +765,8 @@
};
+const char* AllocationSpaceName(AllocationSpace space);
+
} } // namespace v8::internal
#endif // V8_MARK_COMPACT_H_
=======================================
--- /branches/bleeding_edge/src/spaces.cc Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/spaces.cc Tue Sep 20 04:20:00 2011
@@ -432,6 +432,7 @@
chunk->InitializeReservedMemory();
chunk->slots_buffer_ = NULL;
chunk->skip_list_ = NULL;
+ chunk->ResetLiveBytes();
Bitmap::Clear(chunk);
chunk->initialize_scan_on_scavenge(false);
chunk->SetFlag(WAS_SWEPT_PRECISELY);
@@ -822,8 +823,8 @@
ASSERT(object->address() + size <= top);
end_of_previous_object = object->address() + size;
}
- // TODO(1672): Page live bytes are off for some tests.
- // CHECK_LE(black_size, page->LiveBytes());
+
+ CHECK_LE(black_size, page->LiveBytes());
}
}
#endif
@@ -2504,6 +2505,31 @@
}
}
}
+
+
+void Page::Print() {
+ // Make a best-effort to print the objects in the page.
+ PrintF("Page@%p in %s\n",
+ this->address(),
+ AllocationSpaceName(this->owner()->identity()));
+ printf(" --------------------------------------\n");
+ HeapObjectIterator objects(this,
heap()->GcSafeSizeOfOldObjectFunction());
+ unsigned mark_size = 0;
+ for (HeapObject* object = objects.Next();
+ object != NULL;
+ object = objects.Next()) {
+ bool is_marked = Marking::MarkBitFrom(object).Get();
+ PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little.
+ if (is_marked) {
+ mark_size += heap()->GcSafeSizeOfOldObjectFunction()(object);
+ }
+ object->ShortPrint();
+ PrintF("\n");
+ }
+ printf(" --------------------------------------\n");
+ printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
+}
+
#endif // DEBUG
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/spaces.h Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/spaces.h Tue Sep 20 04:20:00 2011
@@ -452,12 +452,27 @@
// Manage live byte count (count of bytes known to be live,
// because they are marked black).
void ResetLiveBytes() {
+ if (FLAG_trace_live_byte_count) {
+ PrintF("ResetLiveBytes:%p:%x->0\n",
+ static_cast<void*>(this), live_byte_count_);
+ }
live_byte_count_ = 0;
}
void IncrementLiveBytes(int by) {
+ ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_);
+ if (FLAG_trace_live_byte_count) {
+ printf("UpdateLiveBytes:%p:%x%c=%x->%x\n",
+ static_cast<void*>(this), live_byte_count_,
+ ((by < 0) ? '-' : '+'), ((by < 0) ? -by : by),
+ live_byte_count_ + by);
+ }
live_byte_count_ += by;
- }
- int LiveBytes() { return live_byte_count_; }
+ ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_);
+ }
+ int LiveBytes() {
+ ASSERT(static_cast<unsigned>(live_byte_count_) <= size_);
+ return live_byte_count_;
+ }
static void IncrementLiveBytes(Address address, int by) {
MemoryChunk::FromAddress(address)->IncrementLiveBytes(by);
}
@@ -467,10 +482,11 @@
static const intptr_t kAlignmentMask = kAlignment - 1;
+ static const intptr_t kSizeOffset = kPointerSize + kPointerSize;
+
static const intptr_t kLiveBytesOffset =
- kPointerSize + kPointerSize + kPointerSize + kPointerSize +
- kPointerSize + kPointerSize + kPointerSize + kPointerSize +
- kIntSize;
+ kSizeOffset + kPointerSize + kPointerSize + kPointerSize +
+ kPointerSize + kPointerSize + kPointerSize + kIntSize;
static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize;
@@ -699,6 +715,10 @@
void ClearSweptPrecisely() { ClearFlag(WAS_SWEPT_PRECISELY); }
void ClearSweptConservatively() { ClearFlag(WAS_SWEPT_CONSERVATIVELY); }
+
+#ifdef DEBUG
+ void Print();
+#endif // DEBUG
friend class MemoryAllocator;
};
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Sep 20
03:06:23 2011
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Sep 20
04:20:00 2011
@@ -4184,7 +4184,7 @@
addq(length, Immediate(0x04));
// Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted
by 2.
imul(length, FieldOperand(value, String::kLengthOffset));
- shr(length, Immediate(2 + kSmiTagSize));
+ shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize));
addq(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
and_(length, Immediate(~kObjectAlignmentMask));
=======================================
--- /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Sep 20 00:00:59
2011
+++ /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Sep 20 04:20:00
2011
@@ -66,12 +66,7 @@
# Known failures after merge from the bleeding edge (issue 1672)
debug-scopes: PASS, SKIP if ($mode == debug)
mirror-object: PASS, SKIP if ($mode == debug)
-debug-return-value: PASS, SKIP if ($mode == debug)
-tickprocessor: PASS, SKIP if ($mode == debug)
-debug-blockscopes: PASS, SKIP if ($mode == debug)
-mirror-error: PASS, SKIP if ($mode == debug)
-mirror-array: PASS, SKIP if ($mode == debug)
-debug-return-value: PASS, SKIP if ($mode == debug)
+harmony/debug-blockscopes: PASS, SKIP if ($mode == debug)
##############################################################################
[ $arch == arm ]
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev