Index: Source/platform/heap/ThreadState.cpp |
diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp |
index 9d552de2b04b487780f2488bd62458f8907cd17a..dff6eeb5c3bbcd95ea1a0ec9a2253b70adc9504c 100644 |
--- a/Source/platform/heap/ThreadState.cpp |
+++ b/Source/platform/heap/ThreadState.cpp |
@@ -606,13 +606,35 @@ void ThreadState::performIdleGC(double deadlineSeconds) |
Heap::collectGarbage(NoHeapPointersOnStack, GCWithoutSweep, Heap::IdleGC); |
} |
-void ThreadState::performIdleCompleteSweep(double deadlineSeconds) |
+void ThreadState::performIdleLazySweep(double deadlineSeconds) |
{ |
ASSERT(isMainThread()); |
- // The completeSweep() does nothing if the sweeping is already done. |
- // TODO(haraken): Split the sweeping task into chunks so that each chunk fits |
- // in the deadlineSeconds. |
- completeSweep(); |
+ |
+ // If we are not in a sweeping phase, there is nothing to do here. |
+ if (!isSweepingInProgress()) |
+ return; |
+ |
+ // This check is here to prevent performIdleLazySweep() from being called |
+ // recursively. I'm not sure if it can happen but it would be safer to have |
+ // the check just in case. |
+ if (sweepForbidden()) |
+ return; |
+ |
+ ThreadState::SweepForbiddenScope scope(this); |
+ { |
+ for (int i = 0; i < NumberOfHeaps; i++) { |
+ double remainingBudget = deadlineSeconds - Platform::current()->monotonicallyIncreasingTime(); |
+ if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadlineSeconds)) { |
+ // We couldn't finish the sweeping within the deadline. |
+ // We request another idle task for the remaining sweeping. |
+ scheduleIdleLazySweep(); |
+ return; |
+ } |
+ } |
+ } |
+ |
+ // Now we have finished the sweeping. |
+ postSweep(); |
} |
void ThreadState::scheduleIdleGC() |
@@ -630,18 +652,15 @@ void ThreadState::scheduleIdleGC() |
setGCState(IdleGCScheduled); |
} |
-void ThreadState::scheduleIdleCompleteSweep() |
+void ThreadState::scheduleIdleLazySweep() |
{ |
// Idle complete sweep is supported only in the main thread. |
if (!isMainThread()) |
return; |
- // TODO(haraken): Temporarily disable complete sweeping in idle tasks |
- // because it turned out that it has a risk of violating the idle task |
- // deadline and thus regressing queueing_durations. We'll enable this |
- // once we finish collecting performance numbers. |
-#if 0 |
- Scheduler::shared()->postIdleTask(FROM_HERE, WTF::bind<double>(&ThreadState::performIdleCompleteSweep, this)); |
+ // TODO(haraken): Remove this. Lazy sweeping is not yet enabled in non-oilpan builds. |
+#if ENABLE(OILPAN) |
+ Scheduler::shared()->postIdleTask(FROM_HERE, WTF::bind<double>(&ThreadState::performIdleLazySweep, this)); |
#endif |
} |
@@ -795,6 +814,11 @@ void ThreadState::completeSweep() |
} |
} |
+ postSweep(); |
+} |
+ |
+void ThreadState::postSweep() |
+{ |
if (isMainThread() && m_allocatedObjectSizeBeforeGC) { |
// FIXME: Heap::markedObjectSize() may not be accurate because other |
// threads may not have finished sweeping. |
@@ -1056,7 +1080,7 @@ void ThreadState::preSweep() |
} else { |
// The default behavior is lazy sweeping. |
setGCState(Sweeping); |
- scheduleIdleCompleteSweep(); |
+ scheduleIdleLazySweep(); |
} |
#else |
// FIXME: For now, we disable lazy sweeping in non-oilpan builds |