Index: src/mark-compact.cc |
diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
index 81361f02aae4023a3aa5d7b202ed89fd73828e7f..f75db472d2b53cb16279e61854b1cd2c551e083a 100644 |
--- a/src/mark-compact.cc |
+++ b/src/mark-compact.cc |
@@ -3106,6 +3106,12 @@ void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { |
HeapObject* target_object; |
AllocationResult allocation = space->AllocateRaw(size); |
if (!allocation.To(&target_object)) { |
+ // If allocation failed, use emergency memory and re-try allocation. |
+ CHECK(space->HasEmergencyMemory()); |
+ space->UseEmergencyMemory(); |
+ allocation = space->AllocateRaw(size); |
+ } |
+ if (!allocation.To(&target_object)) { |
// OS refused to give us memory. |
V8::FatalProcessOutOfMemory("Evacuation"); |
return; |
@@ -3130,10 +3136,16 @@ void MarkCompactCollector::EvacuatePages() { |
p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
ASSERT(static_cast<int>(p->parallel_sweeping()) == |
MemoryChunk::SWEEPING_DONE); |
+ PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
+ // Allocate emergency memory for the case when compaction fails due to out |
+ // of memory. |
+ if (!space->HasEmergencyMemory()) { |
+ space->CreateEmergencyMemory(); |
+ } |
if (p->IsEvacuationCandidate()) { |
- // 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()) { |
+ // During compaction we might have to request a new page. Check that we |
+ // have an emergency page and the space still has room for that. |
+ if (space->HasEmergencyMemory() && space->CanExpand()) { |
EvacuateLiveObjectsFromPage(p); |
} else { |
// Without room for expansion evacuation is not guaranteed to succeed. |
@@ -3144,7 +3156,17 @@ void MarkCompactCollector::EvacuatePages() { |
page->ClearEvacuationCandidate(); |
page->SetFlag(Page::RESCAN_ON_EVACUATION); |
} |
- return; |
+ break; |
+ } |
+ } |
+ } |
+ if (npages > 0) { |
+ // Release emergency memory. |
+ PagedSpaces spaces(heap()); |
+ for (PagedSpace* space = spaces.next(); space != NULL; |
+ space = spaces.next()) { |
+ if (space->HasEmergencyMemory()) { |
+ space->FreeEmergencyMemory(); |
} |
} |
} |