2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "IncrementalSweeper.h"
33 #include "MarkedBlock.h"
34 #include "ScopeChain.h"
35 #include <wtf/HashSet.h>
36 #include <wtf/WTFThreadData.h>
39 #include <wtf/MainThread.h>
46 static const CFTimeInterval sweepTimeSlice = .01; // seconds
47 static const CFTimeInterval sweepTimeTotal = .10;
48 static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeTotal;
50 void IncrementalSweeper::doWork()
52 doSweep(WTF::monotonicallyIncreasingTime());
55 IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
56 : HeapTimer(heap->globalData(), runLoop)
57 , m_currentBlockToSweepIndex(0)
58 , m_structuresCanBeSwept(false)
62 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
64 return new IncrementalSweeper(heap, CFRunLoopGetCurrent());
67 void IncrementalSweeper::scheduleTimer()
69 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + (sweepTimeSlice * sweepTimeMultiplier));
72 void IncrementalSweeper::cancelTimer()
74 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
77 void IncrementalSweeper::doSweep(double sweepBeginTime)
79 while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
82 CFTimeInterval elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime;
83 if (elapsedTime < sweepTimeSlice)
90 m_blocksToSweep.clear();
94 void IncrementalSweeper::sweepNextBlock()
96 while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
97 MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
98 if (block->onlyContainsStructures())
99 m_structuresCanBeSwept = true;
101 ASSERT(!m_structuresCanBeSwept);
103 if (!block->needsSweeping())
107 m_globalData->heap.objectSpace().freeOrShrinkBlock(block);
112 void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot)
114 m_blocksToSweep.resize(blockSnapshot.size());
115 CopyFunctor functor(m_blocksToSweep);
116 m_globalData->heap.objectSpace().forEachBlock(functor);
117 m_currentBlockToSweepIndex = 0;
118 m_structuresCanBeSwept = false;
122 void IncrementalSweeper::willFinishSweeping()
124 m_currentBlockToSweepIndex = 0;
125 m_structuresCanBeSwept = true;
126 m_blocksToSweep.clear();
133 static const double sweepTimeSlice = .01; // seconds
134 static const double sweepTimeTotal = .10;
135 static const double sweepTimeMultiplier = 1.0 / sweepTimeTotal;
137 IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
138 : HeapTimer(globalData)
139 , m_enabled(WTF::isMainThread())
140 , m_structuresCanBeSwept(false)
144 void IncrementalSweeper::doWork()
146 double startTime = WTF::monotonicallyIncreasingTime();
147 while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
150 double elapsedTime = WTF::monotonicallyIncreasingTime() - startTime;
151 if (elapsedTime < sweepTimeSlice)
157 m_blocksToSweep.clear();
161 void IncrementalSweeper::scheduleTimer()
164 m_timer = add(sweepTimeSlice * sweepTimeMultiplier, this);
167 void IncrementalSweeper::cancelTimer()
172 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
174 return new IncrementalSweeper(heap->globalData());
177 void IncrementalSweeper::sweepNextBlock()
179 while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
180 MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
181 if (block->onlyContainsStructures())
182 m_structuresCanBeSwept = true;
184 ASSERT(!m_structuresCanBeSwept);
186 if (!block->needsSweeping())
190 m_globalData->heap.objectSpace().freeOrShrinkBlock(block);
195 void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot)
200 m_blocksToSweep.resize(blockSnapshot.size());
201 CopyFunctor functor(m_blocksToSweep);
202 m_globalData->heap.objectSpace().forEachBlock(functor);
203 m_currentBlockToSweepIndex = 0;
204 m_structuresCanBeSwept = false;
208 void IncrementalSweeper::willFinishSweeping()
210 m_currentBlockToSweepIndex = 0;
211 m_structuresCanBeSwept = true;
212 m_blocksToSweep.clear();
218 IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
219 : HeapTimer(globalData)
220 , m_structuresCanBeSwept(false)
224 void IncrementalSweeper::doWork()
228 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
230 return new IncrementalSweeper(heap->globalData());
233 void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
235 m_structuresCanBeSwept = false;
238 void IncrementalSweeper::willFinishSweeping()
240 m_structuresCanBeSwept = true;
243 void IncrementalSweeper::sweepNextBlock()
249 bool IncrementalSweeper::structuresCanBeSwept()
251 return m_structuresCanBeSwept;