]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/HeapTimer.cpp
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / heap / HeapTimer.cpp
CommitLineData
93a37866
A
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 "HeapTimer.h"
28
29#include "APIShims.h"
30#include "JSObject.h"
31#include "JSString.h"
32
33#include <wtf/MainThread.h>
34#include <wtf/Threading.h>
35
36#if PLATFORM(QT)
37#include <QCoreApplication>
38#include <QMutexLocker>
39#include <QThread>
40#include <QTimerEvent>
41#elif PLATFORM(EFL)
42#include <Ecore.h>
43#endif
44
45namespace JSC {
46
47#if USE(CF)
48
49const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
50
51static const void* retainAPILock(const void* info)
52{
53 static_cast<JSLock*>(const_cast<void*>(info))->ref();
54 return info;
55}
56
57static void releaseAPILock(const void* info)
58{
59 static_cast<JSLock*>(const_cast<void*>(info))->deref();
60}
61
62HeapTimer::HeapTimer(VM* vm, CFRunLoopRef runLoop)
63 : m_vm(vm)
64 , m_runLoop(runLoop)
65{
66 memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
67 m_context.info = &vm->apiLock();
68 m_context.retain = retainAPILock;
69 m_context.release = releaseAPILock;
70 m_timer = adoptCF(CFRunLoopTimerCreate(0, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));
71 CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
72}
73
74HeapTimer::~HeapTimer()
75{
76 CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
77 CFRunLoopTimerInvalidate(m_timer.get());
78}
79
80void HeapTimer::timerDidFire(CFRunLoopTimerRef timer, void* context)
81{
82 JSLock* apiLock = static_cast<JSLock*>(context);
83 apiLock->lock();
84
85 VM* vm = apiLock->vm();
86 // The VM has been destroyed, so we should just give up.
87 if (!vm) {
88 apiLock->unlock();
89 return;
90 }
91
92 HeapTimer* heapTimer = 0;
93#if PLATFORM(IOS)
94 if (vm->heap.activityCallback() && vm->heap.activityCallback()->m_timer.get() == timer)
95 heapTimer = vm->heap.activityCallback();
96#else
97 if (vm->heap.activityCallback()->m_timer.get() == timer)
98 heapTimer = vm->heap.activityCallback();
99#endif // PLATFORM(IOS)
100 else if (vm->heap.sweeper()->m_timer.get() == timer)
101 heapTimer = vm->heap.sweeper();
102 else
103 RELEASE_ASSERT_NOT_REACHED();
104
105 {
106 APIEntryShim shim(vm);
107 heapTimer->doWork();
108 }
109
110 apiLock->unlock();
111}
112
113#elif PLATFORM(BLACKBERRY)
114
115HeapTimer::HeapTimer(VM* vm)
116 : m_vm(vm)
117 , m_timer(this, &HeapTimer::timerDidFire)
118{
119 // FIXME: Implement HeapTimer for other threads.
120 if (WTF::isMainThread() && !m_timer.tryCreateClient())
121 CRASH();
122}
123
124HeapTimer::~HeapTimer()
125{
126}
127
128void HeapTimer::timerDidFire()
129{
130 doWork();
131}
132
133void HeapTimer::invalidate()
134{
135}
136
137#elif PLATFORM(QT)
138
139HeapTimer::HeapTimer(VM* vm)
140 : m_vm(vm)
141 , m_newThread(0)
142 , m_mutex(QMutex::NonRecursive)
143{
144 // The HeapTimer might be created before the runLoop is started,
145 // but we need to ensure the thread has an eventDispatcher already.
146 QEventLoop fakeLoop(this);
147}
148
149HeapTimer::~HeapTimer()
150{
151 QMutexLocker lock(&m_mutex);
152 m_timer.stop();
153}
154
155void HeapTimer::timerEvent(QTimerEvent*)
156{
157 QMutexLocker lock(&m_mutex);
158 if (m_newThread) {
159 // We need to wait with processing until we are on the right thread.
160 return;
161 }
162
163 APIEntryShim shim(m_vm);
164 doWork();
165}
166
167void HeapTimer::customEvent(QEvent*)
168{
169 ASSERT(m_newThread);
170 QMutexLocker lock(&m_mutex);
171 moveToThread(m_newThread);
172 m_newThread = 0;
173}
174
175#elif PLATFORM(EFL)
176
177HeapTimer::HeapTimer(VM* vm)
178 : m_vm(vm)
179 , m_timer(0)
180{
181}
182
183HeapTimer::~HeapTimer()
184{
185 stop();
186}
187
188Ecore_Timer* HeapTimer::add(double delay, void* agent)
189{
190 return ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerEvent), agent);
191}
192
193void HeapTimer::stop()
194{
195 if (!m_timer)
196 return;
197
198 ecore_timer_del(m_timer);
199 m_timer = 0;
200}
201
202bool HeapTimer::timerEvent(void* info)
203{
204 HeapTimer* agent = static_cast<HeapTimer*>(info);
205
206 APIEntryShim shim(agent->m_vm);
207 agent->doWork();
208 agent->m_timer = 0;
209
210 return ECORE_CALLBACK_CANCEL;
211}
212
213#else
214HeapTimer::HeapTimer(VM* vm)
215 : m_vm(vm)
216{
217}
218
219HeapTimer::~HeapTimer()
220{
221}
222
223void HeapTimer::invalidate()
224{
225}
226
227#endif
228
229
230} // namespace JSC