Reviewers: Erik Corry,

Description:
Guard against rare case of allocation failure during evacuation.

This fixes flakiness of mjsunit/regress/regress-524 (crash always reproducible
with --always-compact).

[email protected]
BUG=v8:1556


Please review this at http://codereview.chromium.org/7870003/

SVN Base: https://v8.googlecode.com/svn/branches/experimental/gc

Affected files:
  M src/mark-compact.cc
  M src/spaces.h
  M src/spaces.cc


Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 176c9d906c5a3a937d19db67be61975e91b3efdb..a19df8eb3ba3a10c13df44492d905e44a82e8b15 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2576,10 +2576,16 @@ void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) {

       int size = object->Size();

-      // This should never fail as we are in always allocate scope.
-      Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
+      MaybeObject* target = space->AllocateRaw(size);
+      if (target->IsFailure()) {
+        // OS refused to give us memory.
+        V8::FatalProcessOutOfMemory("Evacuation");
+        return;
+      }

-      MigrateObject(HeapObject::cast(target)->address(),
+      Object* target_object = target->ToObjectUnchecked();
+
+      MigrateObject(HeapObject::cast(target_object)->address(),
                     object_addr,
                     size,
                     space->identity());
@@ -2599,7 +2605,19 @@ void MarkCompactCollector::EvacuatePages() {
     ASSERT(p->IsEvacuationCandidate() ||
            p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
     if (p->IsEvacuationCandidate()) {
-      EvacuateLiveObjectsFromPage(p);
+      // During compaction we might have to request a new page.
+      // Check that space still have room for that.
+      if (static_cast<PagedSpace*>(p->owner())->CanExpand()) {
+        EvacuateLiveObjectsFromPage(p);
+      } else {
+ // Without room for expansion evacuation is not guaranteed to succeed.
+        // Pessimistically abandon unevacuated pages.
+        for (int j = i; j < npages; j++) {
+          evacuation_candidates_[j]->ClearEvacuationCandidate();
+          evacuation_candidates_[j]->SetFlag(Page::RESCAN_ON_EVACUATION);
+        }
+        return;
+      }
     }
   }
 }
@@ -2807,10 +2825,14 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
       PagedSpace* space = static_cast<PagedSpace*>(p->owner());
       p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION);

-      SweepPrecisely(space,
-                     p,
-                     SWEEP_AND_VISIT_LIVE_OBJECTS,
-                     &updating_visitor);
+      if (space->identity() == OLD_DATA_SPACE) {
+        SweepConservatively(space, p);
+      } else {
+        SweepPrecisely(space,
+                       p,
+                       SWEEP_AND_VISIT_LIVE_OBJECTS,
+                       &updating_visitor);
+      }
     }
   }

Index: src/spaces.cc
diff --git a/src/spaces.cc b/src/spaces.cc
index 8e7a947f171e86b7693bc682f71ed702e9644980..d2572d9a2cd3f42ba67001952bab6e666bce066e 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -721,8 +721,7 @@ MaybeObject* PagedSpace::FindObject(Address addr) {
   return Failure::Exception();
 }

-
-bool PagedSpace::Expand() {
+bool PagedSpace::CanExpand() {
   ASSERT(max_capacity_ % Page::kObjectAreaSize == 0);
   ASSERT(Capacity() % Page::kObjectAreaSize == 0);

@@ -733,6 +732,12 @@ bool PagedSpace::Expand() {
   // Are we going to exceed capacity for this space?
   if ((Capacity() + Page::kPageSize) > max_capacity_) return false;

+  return true;
+}
+
+bool PagedSpace::Expand() {
+  if (!CanExpand()) return false;
+
   Page* p = heap()->isolate()->memory_allocator()->
       AllocatePage(this, executable());
   if (p == NULL) return false;
Index: src/spaces.h
diff --git a/src/spaces.h b/src/spaces.h
index 0df15351b8adb1390d4c955afe92a075fe68bb49..dc68ca58dd1c3fef57e5a030706208c1c80299ae 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1492,6 +1492,8 @@ class PagedSpace : public Space {

   void EvictEvacuationCandidatesFromFreeLists();

+  bool CanExpand();
+
  protected:
   // Maximum capacity of this space.
   intptr_t max_capacity_;


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to