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

Reply via email to