9719c952c30fe93367cbc8d18ad915d1d3a39d61
[WebKit-https.git] / Source / JavaScriptCore / heap / IncrementalSweeper.cpp
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "IncrementalSweeper.h"
28
29 #include "APIShims.h"
30 #include "Heap.h"
31 #include "JSObject.h"
32 #include "JSString.h"
33 #include "MarkedBlock.h"
34
35 #include <wtf/HashSet.h>
36 #include <wtf/WTFThreadData.h>
37
38 namespace JSC {
39
40 #if USE(CF) || PLATFORM(BLACKBERRY)
41
42 static const double sweepTimeSlice = .01; // seconds
43 static const double sweepTimeTotal = .10;
44 static const double sweepTimeMultiplier = 1.0 / sweepTimeTotal;
45
46 #if USE(CF)
47     
48 IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
49     : HeapTimer(heap->globalData(), runLoop)
50     , m_currentBlockToSweepIndex(0)
51 {
52 }
53
54 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
55 {
56     return new IncrementalSweeper(heap, CFRunLoopGetCurrent());
57 }
58
59 void IncrementalSweeper::scheduleTimer()
60 {
61     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + (sweepTimeSlice * sweepTimeMultiplier));
62 }
63
64 void IncrementalSweeper::cancelTimer()
65 {
66     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
67 }
68
69 #elif PLATFORM(BLACKBERRY)
70    
71 IncrementalSweeper::IncrementalSweeper(Heap* heap)
72     : HeapTimer(heap->globalData())
73     , m_currentBlockToSweepIndex(0)
74 {
75 }
76
77 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
78 {
79     return new IncrementalSweeper(heap);
80 }
81
82 void IncrementalSweeper::scheduleTimer()
83 {
84     m_timer.start(sweepTimeSlice * sweepTimeMultiplier);
85 }
86
87 void IncrementalSweeper::cancelTimer()
88 {
89     m_timer.stop();
90 }
91
92 #endif
93
94 void IncrementalSweeper::doWork()
95 {
96     doSweep(WTF::monotonicallyIncreasingTime());
97 }
98
99 void IncrementalSweeper::doSweep(double sweepBeginTime)
100 {
101     while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
102         sweepNextBlock();
103
104         double elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime;
105         if (elapsedTime < sweepTimeSlice)
106             continue;
107
108         scheduleTimer();
109         return;
110     }
111
112     m_blocksToSweep.clear();
113     cancelTimer();
114 }
115
116 void IncrementalSweeper::sweepNextBlock()
117 {
118     while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
119         MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
120
121         if (!block->needsSweeping())
122             continue;
123
124         block->sweep();
125         m_globalData->heap.objectSpace().freeOrShrinkBlock(block);
126         return;
127     }
128 }
129
130 void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>& blockSnapshot)
131 {
132     m_blocksToSweep.resize(blockSnapshot.size());
133     CopyFunctor functor(m_blocksToSweep);
134     m_globalData->heap.objectSpace().forEachBlock(functor);
135     m_currentBlockToSweepIndex = 0;
136     scheduleTimer();
137 }
138
139 void IncrementalSweeper::willFinishSweeping()
140 {
141     m_currentBlockToSweepIndex = 0;
142     m_blocksToSweep.clear();
143     if (m_globalData)
144         cancelTimer();
145 }
146
147 #else
148
149 IncrementalSweeper::IncrementalSweeper(JSGlobalData* globalData)
150     : HeapTimer(globalData)
151 {
152 }
153
154 void IncrementalSweeper::doWork()
155 {
156 }
157
158 IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
159 {
160     return new IncrementalSweeper(heap->globalData());
161 }
162
163 void IncrementalSweeper::startSweeping(const HashSet<MarkedBlock*>&)
164 {
165 }
166
167 void IncrementalSweeper::willFinishSweeping()
168 {
169 }
170
171 void IncrementalSweeper::sweepNextBlock()
172 {
173 }
174
175 #endif
176
177 } // namespace JSC