]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/GCActivityCallback.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / runtime / GCActivityCallback.cpp
1 /*
2 * Copyright (C) 2010 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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "GCActivityCallback.h"
31
32 #include "APIShims.h"
33 #include "Heap.h"
34 #include "VM.h"
35 #include "JSLock.h"
36 #include "JSObject.h"
37
38 #include <wtf/RetainPtr.h>
39 #include <wtf/WTFThreadData.h>
40
41 #if PLATFORM(EFL)
42 #include <wtf/MainThread.h>
43 #endif
44
45 namespace JSC {
46
47 #if USE(CF) || PLATFORM(QT) || PLATFORM(EFL)
48
49 #if PLATFORM(IOS)
50 bool GCActivityCallback::s_shouldCreateGCTimer = true;
51 #endif // PLATFORM(IOS)
52
53 const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
54 const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
55 const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
56 const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
57 const double hour = 60 * 60;
58
59 #if USE(CF)
60 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
61 : GCActivityCallback(heap->vm(), CFRunLoopGetCurrent())
62 , m_delay(s_decade)
63 {
64 }
65
66 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
67 : GCActivityCallback(heap->vm(), runLoop)
68 , m_delay(s_decade)
69 {
70 }
71 #elif PLATFORM(QT)
72 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
73 : GCActivityCallback(heap->vm())
74 , m_delay(hour)
75 {
76 }
77 #elif PLATFORM(EFL)
78 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
79 : GCActivityCallback(heap->vm(), WTF::isMainThread())
80 , m_delay(hour)
81 {
82 }
83 #endif
84
85 void DefaultGCActivityCallback::doWork()
86 {
87 Heap* heap = &m_vm->heap;
88 if (!isEnabled())
89 return;
90
91 APIEntryShim shim(m_vm);
92 #if !PLATFORM(IOS)
93 double startTime = WTF::monotonicallyIncreasingTime();
94 if (heap->isPagedOut(startTime + pagingTimeOut)) {
95 heap->activityCallback()->cancel();
96 heap->increaseLastGCLength(pagingTimeOut);
97 return;
98 }
99 #endif
100 heap->collect(Heap::DoNotSweep);
101 }
102
103 #if USE(CF)
104 void DefaultGCActivityCallback::scheduleTimer(double newDelay)
105 {
106 if (newDelay * timerSlop > m_delay)
107 return;
108 double delta = m_delay - newDelay;
109 m_delay = newDelay;
110 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta);
111 }
112
113 void DefaultGCActivityCallback::cancelTimer()
114 {
115 m_delay = s_decade;
116 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
117 }
118 #elif PLATFORM(QT)
119
120 void DefaultGCActivityCallback::scheduleTimer(double newDelay)
121 {
122 if (newDelay * timerSlop > m_delay)
123 return;
124 m_delay = newDelay;
125 m_timer.start(newDelay * 1000, this);
126 }
127
128 void DefaultGCActivityCallback::cancelTimer()
129 {
130 m_delay = hour;
131 m_timer.stop();
132 }
133 #elif PLATFORM(EFL)
134 void DefaultGCActivityCallback::scheduleTimer(double newDelay)
135 {
136 if (newDelay * timerSlop > m_delay)
137 return;
138
139 stop();
140 m_delay = newDelay;
141
142 ASSERT(!m_timer);
143 m_timer = add(newDelay, this);
144 }
145
146 void DefaultGCActivityCallback::cancelTimer()
147 {
148 m_delay = hour;
149 stop();
150 }
151 #endif
152
153 void DefaultGCActivityCallback::didAllocate(size_t bytes)
154 {
155 #if PLATFORM(EFL)
156 if (!isEnabled())
157 return;
158
159 ASSERT(WTF::isMainThread());
160 #endif
161
162 // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate.
163 // We pretend it's one byte so that we don't ignore this allocation entirely.
164 if (!bytes)
165 bytes = 1;
166 Heap* heap = static_cast<Heap*>(&m_vm->heap);
167 double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
168 double newDelay = heap->lastGCLength() / gcTimeSlice;
169 scheduleTimer(newDelay);
170 }
171
172 void DefaultGCActivityCallback::willCollect()
173 {
174 cancelTimer();
175 }
176
177 void DefaultGCActivityCallback::cancel()
178 {
179 cancelTimer();
180 }
181
182 #else
183
184 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
185 : GCActivityCallback(heap->vm())
186 {
187 }
188
189 void DefaultGCActivityCallback::doWork()
190 {
191 }
192
193 void DefaultGCActivityCallback::didAllocate(size_t)
194 {
195 }
196
197 void DefaultGCActivityCallback::willCollect()
198 {
199 }
200
201 void DefaultGCActivityCallback::cancel()
202 {
203 }
204
205 #endif
206
207 }
208