Incremetal sweeper added to improve memory usage
[framework/web/webkit-efl.git] / Source / JavaScriptCore / heap / HeapTimer.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 "HeapTimer.h"
28
29 #include "APIShims.h"
30 #include "JSObject.h"
31 #include "JSString.h"
32 #include "ScopeChain.h"
33 #include <wtf/Threading.h>
34
35 #if PLATFORM(EFL)
36 #include <Ecore.h>
37 #endif
38
39 namespace JSC {
40
41 #if USE(CF)
42     
43 const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
44
45 HeapTimer::HeapTimer(JSGlobalData* globalData, CFRunLoopRef runLoop)
46     : m_globalData(globalData)
47     , m_runLoop(runLoop)
48 {
49     memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
50     m_context.info = this;
51     m_timer.adoptCF(CFRunLoopTimerCreate(0, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));
52     CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
53 }
54
55 HeapTimer::~HeapTimer()
56 {
57     CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
58     CFRunLoopTimerInvalidate(m_timer.get());
59 }
60
61 void HeapTimer::synchronize()
62 {
63     if (CFRunLoopGetCurrent() == m_runLoop.get())
64         return;
65     CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
66     m_runLoop = CFRunLoopGetCurrent();
67     CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
68 }
69
70 void HeapTimer::invalidate()
71 {
72     m_globalData = 0;
73     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() - s_decade);
74 }
75
76 void HeapTimer::didStartVMShutdown()
77 {
78     if (CFRunLoopGetCurrent() == m_runLoop.get()) {
79         invalidate();
80         delete this;
81         return;
82     }
83     ASSERT(!m_globalData->apiLock().currentThreadIsHoldingLock());
84     MutexLocker locker(m_shutdownMutex);
85     invalidate();
86 }
87
88 void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* info)
89 {
90     HeapTimer* agent = static_cast<HeapTimer*>(info);
91     agent->m_shutdownMutex.lock();
92     if (!agent->m_globalData) {
93         agent->m_shutdownMutex.unlock();
94         delete agent;
95         return;
96     }
97     {
98         // We don't ref here to prevent us from resurrecting the ref count of a "dead" JSGlobalData.
99         APIEntryShim shim(agent->m_globalData, APIEntryShimWithoutLock::DontRefGlobalData);
100         agent->doWork();
101     }
102     agent->m_shutdownMutex.unlock();
103 }
104
105 #elif PLATFORM(BLACKBERRY)
106
107 HeapTimer::HeapTimer(JSGlobalData* globalData)
108     : m_globalData(globalData)
109     , m_timer(this, &HeapTimer::timerDidFire)
110 {
111 }
112
113 HeapTimer::~HeapTimer()
114 {
115 }
116
117 void HeapTimer::timerDidFire()
118 {
119     doWork();
120 }
121
122 void HeapTimer::synchronize()
123 {
124 }
125
126 void HeapTimer::invalidate()
127 {
128 }
129
130 void HeapTimer::didStartVMShutdown()
131 {
132     delete this;
133 }
134
135 #elif PLATFORM(EFL)
136
137 HeapTimer::HeapTimer(JSGlobalData* globalData)
138     : m_globalData(globalData)
139     , m_timer(0)
140 {
141     ecore_init();
142 }
143
144 HeapTimer::~HeapTimer()
145 {
146     stop();
147     ecore_shutdown();
148 }
149
150 void HeapTimer::didStartVMShutdown()
151 {
152     delete this;
153 }
154
155 void HeapTimer::synchronize()
156 {
157 }
158
159 void HeapTimer::invalidate()
160 {
161 }
162
163 Ecore_Timer* HeapTimer::add(double delay, void* agent)
164 {
165     return ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerEvent), agent);
166 }
167
168 void HeapTimer::stop()
169 {
170     if (!m_timer)
171         return;
172
173     ecore_timer_del(m_timer);
174     m_timer = 0;
175 }
176
177 bool HeapTimer::timerEvent(void* info)
178 {
179     HeapTimer* agent = static_cast<HeapTimer*>(info);
180
181     APIEntryShim shim(agent->m_globalData);
182     agent->doWork();
183     agent->m_timer = 0;
184
185     return ECORE_CALLBACK_CANCEL;
186 }
187
188 #else
189
190 HeapTimer::HeapTimer(JSGlobalData* globalData)
191     : m_globalData(globalData)
192 {
193 }
194
195 HeapTimer::~HeapTimer()
196 {
197 }
198
199 void HeapTimer::didStartVMShutdown()
200 {
201     delete this;
202 }
203
204 void HeapTimer::synchronize()
205 {
206 }
207
208 void HeapTimer::invalidate()
209 {
210 }
211
212 #endif
213     
214
215 } // namespace JSC