Revision: 9251
Author:   [email protected]
Date:     Tue Sep 13 02:24:38 2011
Log:      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

Review URL: http://codereview.chromium.org/7870003
http://code.google.com/p/v8/source/detail?r=9251

Modified:
 /branches/experimental/gc/src/mark-compact.cc
 /branches/experimental/gc/src/spaces.cc
 /branches/experimental/gc/src/spaces.h

=======================================
--- /branches/experimental/gc/src/mark-compact.cc       Sat Sep 10 07:48:09 2011
+++ /branches/experimental/gc/src/mark-compact.cc       Tue Sep 13 02:24:38 2011
@@ -2576,10 +2576,16 @@

       int size = object->Size();

-      // This should never fail as we are in always allocate scope.
-      Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
-
-      MigrateObject(HeapObject::cast(target)->address(),
+      MaybeObject* target = space->AllocateRaw(size);
+      if (target->IsFailure()) {
+        // OS refused to give us memory.
+        V8::FatalProcessOutOfMemory("Evacuation");
+        return;
+      }
+
+      Object* target_object = target->ToObjectUnchecked();
+
+      MigrateObject(HeapObject::cast(target_object)->address(),
                     object_addr,
                     size,
                     space->identity());
@@ -2599,7 +2605,19 @@
     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 @@
       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);
+      }
     }
   }

=======================================
--- /branches/experimental/gc/src/spaces.cc     Thu Sep  8 05:15:24 2011
+++ /branches/experimental/gc/src/spaces.cc     Tue Sep 13 02:24:38 2011
@@ -721,8 +721,7 @@
   return Failure::Exception();
 }

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

@@ -733,6 +732,12 @@
   // 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;
=======================================
--- /branches/experimental/gc/src/spaces.h      Tue Sep  6 08:11:38 2011
+++ /branches/experimental/gc/src/spaces.h      Tue Sep 13 02:24:38 2011
@@ -1492,6 +1492,8 @@

   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