Index: Source/platform/heap/ThreadState.cpp |
diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp |
index 931f90e60524d9b4d641d7c38e2a854594ae0efe..ce2fc79e21c42f39a9d22b65e0e4a545ba34586f 100644 |
--- a/Source/platform/heap/ThreadState.cpp |
+++ b/Source/platform/heap/ThreadState.cpp |
@@ -529,6 +529,19 @@ Mutex& ThreadState::globalRootsMutex() |
return mutex; |
} |
+bool ThreadState::shouldForceMemoryPressureGC() |
+{ |
+ // Avoid potential overflow by truncating to Kb. |
+ size_t currentObjectSizeKb = (Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10; |
+ if (currentObjectSizeKb < 300 * 1024) |
+ return false; |
+ |
+ size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
+ // If we're consuming too much memory, trigger a conservative GC |
+ // aggressively. This is a safe guard to avoid OOM. |
+ return currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2; |
+} |
+ |
// TODO(haraken): We should improve the GC heuristics. |
// These heuristics affect performance significantly. |
bool ThreadState::shouldScheduleIdleGC() |
@@ -536,18 +549,19 @@ bool ThreadState::shouldScheduleIdleGC() |
if (gcState() != NoGCScheduled) |
return false; |
#if ENABLE(IDLE_GC) |
+ // Avoid potential overflow by truncating to Kb. |
+ size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; |
// The estimated size is updated when the main thread finishes lazy |
// sweeping. If this thread reaches here before the main thread finishes |
// lazy sweeping, the thread will use the estimated size of the last GC. |
- size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
- size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
+ size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
// Heap::markedObjectSize() may be underestimated if any thread has not |
// finished completeSweep(). |
- size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
+ size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
// Schedule an idle GC if Oilpan has allocated more than 1 MB since |
// the last GC and the current memory usage is >50% larger than |
// the estimated live memory usage. |
- return allocatedObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLiveObjectSize * 3 / 2; |
+ return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2; |
#else |
return false; |
#endif |
@@ -562,18 +576,19 @@ bool ThreadState::shouldSchedulePreciseGC() |
#if ENABLE(IDLE_GC) |
return false; |
#else |
+ // Avoid potential overflow by truncating to Kb. |
+ size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; |
// The estimated size is updated when the main thread finishes lazy |
// sweeping. If this thread reaches here before the main thread finishes |
// lazy sweeping, the thread will use the estimated size of the last GC. |
- size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
- size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
+ size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
// Heap::markedObjectSize() may be underestimated if any thread has not |
// finished completeSweep(). |
- size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
+ size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
// Schedule a precise GC if Oilpan has allocated more than 1 MB since |
// the last GC and the current memory usage is >50% larger than |
// the estimated live memory usage. |
- return allocatedObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLiveObjectSize * 3 / 2; |
+ return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2; |
#endif |
} |
@@ -584,24 +599,23 @@ bool ThreadState::shouldForceConservativeGC() |
if (UNLIKELY(isGCForbidden())) |
return false; |
+ if (shouldForceMemoryPressureGC()) |
+ return true; |
+ |
+ // Avoid potential overflow by truncating to Kb. |
+ size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; |
// The estimated size is updated when the main thread finishes lazy |
// sweeping. If this thread reaches here before the main thread finishes |
// lazy sweeping, the thread will use the estimated size of the last GC. |
- size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
- size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
+ size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
// Heap::markedObjectSize() may be underestimated if any thread has not |
// finished completeSweep(). |
- size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
- if (currentObjectSize >= 300 * 1024 * 1024) { |
- // If we're consuming too much memory, trigger a conservative GC |
- // aggressively. This is a safe guard to avoid OOM. |
- return currentObjectSize > estimatedLiveObjectSize * 3 / 2; |
- } |
+ size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
// Schedule a conservative GC if Oilpan has allocated more than 32 MB since |
// the last GC and the current memory usage is >400% larger than |
// the estimated live memory usage. |
// TODO(haraken): 400% is too large. Lower the heap growing factor. |
- return allocatedObjectSize >= 32 * 1024 * 1024 && currentObjectSize > 5 * estimatedLiveObjectSize; |
+ return allocatedObjectSizeKb >= 32 * 1024 && currentObjectSizeKb > 5 * estimatedLiveObjectSizeKb; |
} |
void ThreadState::scheduleGCIfNeeded() |
@@ -802,7 +816,7 @@ ThreadState::GCState ThreadState::gcState() const |
return m_gcState; |
} |
-void ThreadState::didV8GC() |
+void ThreadState::didV8MajorGC() |
{ |
checkThread(); |
if (isMainThread()) { |
@@ -810,6 +824,12 @@ void ThreadState::didV8GC() |
// expected to have collected a lot of DOM wrappers and dropped |
// references to their DOM objects. |
Heap::setEstimatedLiveObjectSize(Heap::estimatedLiveObjectSize() / 2); |
+ |
+ if (shouldForceMemoryPressureGC()) { |
+ // Under memory pressure, force a conservative GC. |
+ Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::ConservativeGC); |
+ return; |
+ } |
} |
} |