Reviewers: Erik Corry,
Description:
Fix several bugs in compaction:
- when evicting evacuation candidates from free list create filler covering
[top, limit) to ensure that page will remain iterable if it was iterable.
this
is important for Code space pages.
- we should not split typed slots between two slots buffers because we
traverse
them in opposite order.
- when recording reloc slot ensure that reloc host is not null before
checking
host's page flags.
[email protected]
BUG=
TEST=
Please review this at http://codereview.chromium.org/7841036/
SVN Base: https://v8.googlecode.com/svn/branches/experimental/gc
Affected files:
M src/flag-definitions.h
M src/mark-compact.h
M src/mark-compact.cc
M src/objects-visiting-inl.h
M src/spaces.cc
Index: src/flag-definitions.h
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index
a8b7b5d79a7433076c076ddbb84c0665e82c53be..98547305101514a8d9944f44fe381207d23f9906
100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -252,6 +252,8 @@ DEFINE_bool(print_cumulative_gc_stat, false,
"print cumulative GC statistics in name=value format on exit")
DEFINE_bool(trace_gc_verbose, false,
"print more details following each garbage collection")
+DEFINE_bool(trace_fragmentation, false,
+ "report fragmentation for old pointer and data pages")
DEFINE_bool(collect_maps, true,
"garbage collect maps from which no objects can be reached")
DEFINE_bool(flush_code, false,
@@ -457,8 +459,6 @@ DEFINE_bool(debug_serialization, false,
DEFINE_bool(collect_heap_spill_statistics, false,
"report heap spill statistics along with heap_stats "
"(requires heap_stats)")
-DEFINE_bool(trace_fragmentation, false,
- "report fragmentation for old pointer and data pages")
DEFINE_bool(trace_isolates, false, "trace isolate state changes")
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index
5359d8d3a2bb399086407b16a8bd6ca742c306d7..bdc891015fc0514e2dd6c86a67c215378174ee16
100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -426,7 +426,6 @@ void
MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) {
void MarkCompactCollector::Prepare(GCTracer* tracer) {
FLAG_flush_code = false;
- FLAG_always_compact = false;
// Disable collection of maps if incremental marking is enabled.
// Map collection algorithm relies on a special map transition tree
traversal
@@ -3415,16 +3414,19 @@ bool SlotsBuffer::AddTo(SlotsBufferAllocator*
allocator,
SlotType type,
Address addr,
AdditionMode mode) {
- if(!AddTo(allocator,
- buffer_address,
- reinterpret_cast<ObjectSlot>(type),
- mode)) {
- return false;
+ SlotsBuffer* buffer = *buffer_address;
+ if (buffer == NULL || !buffer->HasSpaceForTypedSlot()) {
+ if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) {
+ allocator->DeallocateChain(buffer_address);
+ return false;
+ }
+ buffer = allocator->AllocateBuffer(buffer);
+ *buffer_address = buffer;
}
- return AddTo(allocator,
- buffer_address,
- reinterpret_cast<ObjectSlot>(addr),
- mode);
+ ASSERT(buffer->HasSpaceForTypedSlot());
+ buffer->Add(reinterpret_cast<ObjectSlot>(type));
+ buffer->Add(reinterpret_cast<ObjectSlot>(addr));
+ return true;
}
@@ -3437,7 +3439,7 @@ static inline SlotsBuffer::SlotType
SlotTypeForRMode(RelocInfo::Mode rmode) {
return SlotsBuffer::JS_RETURN_SLOT;
}
UNREACHABLE();
- return SlotsBuffer::NONE;
+ return SlotsBuffer::NUMBER_OF_SLOT_TYPES;
}
@@ -3445,7 +3447,8 @@ void MarkCompactCollector::RecordRelocSlot(RelocInfo*
rinfo, Code* target) {
Page* target_page = Page::FromAddress(
reinterpret_cast<Address>(target));
if (target_page->IsEvacuationCandidate() &&
- !ShouldSkipEvacuationSlotRecording(rinfo->host())) {
+ (rinfo->host() == NULL ||
+ !ShouldSkipEvacuationSlotRecording(rinfo->host()))) {
if (!SlotsBuffer::AddTo(&slots_buffer_allocator_,
target_page->slots_buffer_address(),
SlotTypeForRMode(rinfo->rmode()),
@@ -3479,32 +3482,21 @@ static inline SlotsBuffer::SlotType DecodeSlotType(
}
-SlotsBuffer::SlotType SlotsBuffer::UpdateSlots(
- Heap* heap,
- SlotsBuffer::SlotType pending) {
+void SlotsBuffer::UpdateSlots(Heap* heap) {
PointersUpdatingVisitor v(heap);
- if (pending != NONE) {
- UpdateSlot(&v, pending, reinterpret_cast<Address>(slots_[0]));
- }
-
for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) {
ObjectSlot slot = slots_[slot_idx];
if (!IsTypedSlot(slot)) {
UpdateSlot(slot);
} else {
++slot_idx;
- if (slot_idx < idx_) {
- UpdateSlot(&v,
- DecodeSlotType(slot),
- reinterpret_cast<Address>(slots_[slot_idx]));
- } else {
- return DecodeSlotType(slot);
- }
+ ASSERT(slot_idx < idx_);
+ UpdateSlot(&v,
+ DecodeSlotType(slot),
+ reinterpret_cast<Address>(slots_[slot_idx]));
}
}
-
- return SlotsBuffer::NONE;
}
Index: src/mark-compact.h
diff --git a/src/mark-compact.h b/src/mark-compact.h
index
1b60e2ad83ade0ea27b426f9e4d56063c08470c5..4efd60553f8ed147ca3e0ffa45fdc4ba8e1a368f
100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -308,7 +308,6 @@ class SlotsBuffer {
}
enum SlotType {
- NONE,
RELOCATED_CODE_OBJECT,
CODE_TARGET_SLOT,
CODE_ENTRY_SLOT,
@@ -317,16 +316,7 @@ class SlotsBuffer {
NUMBER_OF_SLOT_TYPES
};
- // Typed slot might be splitted between two SlotsBuffers: slot's type
- // is recorded in one buffer and type address is recorded as the first
- // slot in the next buffer.
- //
- // If the first address recorded in this buffer is address of the typed
- // slot then it's type will be passed as pending argument.
- //
- // If this buffer ends on slot's type and the next buffer is expected to
- // contain address of a typed slot then the function returns that type.
- SlotType UpdateSlots(Heap* heap, SlotType pending);
+ void UpdateSlots(Heap* heap);
SlotsBuffer* next() { return next_; }
@@ -340,10 +330,13 @@ class SlotsBuffer {
return idx_ == kNumberOfElements;
}
+ inline bool HasSpaceForTypedSlot() {
+ return idx_ < kNumberOfElements - 1;
+ }
+
static void UpdateSlotsRecordedIn(Heap* heap, SlotsBuffer* buffer) {
- SlotType pending = NONE;
while (buffer != NULL) {
- pending = buffer->UpdateSlots(heap, pending);
+ buffer->UpdateSlots(heap);
buffer = buffer->next();
}
}
@@ -353,15 +346,17 @@ class SlotsBuffer {
IGNORE_OVERFLOW
};
+ static bool ChainLengthThresholdReached(SlotsBuffer* buffer) {
+ return buffer != NULL && buffer->chain_length_ >=
kChainLengthThreshold;
+ }
+
static bool AddTo(SlotsBufferAllocator* allocator,
SlotsBuffer** buffer_address,
ObjectSlot slot,
AdditionMode mode) {
SlotsBuffer* buffer = *buffer_address;
if (buffer == NULL || buffer->IsFull()) {
- if (mode == FAIL_ON_OVERFLOW &&
- buffer != NULL &&
- buffer->chain_length_ >= kChainLengthThreshold) {
+ if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer))
{
allocator->DeallocateChain(buffer_address);
return false;
}
Index: src/objects-visiting-inl.h
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index
f77ebc4306cede20cdb31b5b8d8d0a4b3311d205..f6f15e796e33126efd742b1fc674524e8a56f191
100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -99,13 +99,10 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
- // Use the relocation info pointer before it is visited by
- // the heap compaction in the next statement.
- RelocIterator it(this, mode_mask);
-
IteratePointer(v, kRelocationInfoOffset);
IteratePointer(v, kDeoptimizationDataOffset);
+ RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) {
it.rinfo()->Visit(v);
}
@@ -122,10 +119,6 @@ void Code::CodeIterateBody(Heap* heap) {
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
- // Use the relocation info pointer before it is visited by
- // the heap compaction in the next statement.
- RelocIterator it(this, mode_mask);
-
StaticVisitor::VisitPointer(
heap,
reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
@@ -133,6 +126,7 @@ void Code::CodeIterateBody(Heap* heap) {
heap,
reinterpret_cast<Object**>(this->address() +
kDeoptimizationDataOffset));
+ RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) {
it.rinfo()->template Visit<StaticVisitor>(heap);
}
Index: src/spaces.cc
diff --git a/src/spaces.cc b/src/spaces.cc
index
62323bafe104a1bd1f5fd68d548a784fa7e6c641..8e7a947f171e86b7693bc682f71ed702e9644980
100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -2020,8 +2020,13 @@ void
PagedSpace::EvictEvacuationCandidatesFromFreeLists() {
if (allocation_info_.top >= allocation_info_.limit) return;
if (Page::FromAddress(allocation_info_.top)->IsEvacuationCandidate()) {
- allocation_info_.top = NULL;
- allocation_info_.limit = NULL;
+ // Create filler object to keep page iterable if it was iterable.
+ int remaining =
+ static_cast<int>(allocation_info_.limit - allocation_info_.top);
+ heap()->CreateFillerObjectAt(allocation_info_.top, remaining);
+
+ allocation_info_.top = NULL;
+ allocation_info_.limit = NULL;
}
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev