summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap/GCActivityCallback.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/heap/GCActivityCallback.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/heap/GCActivityCallback.cpp')
-rw-r--r--Source/JavaScriptCore/heap/GCActivityCallback.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/GCActivityCallback.cpp b/Source/JavaScriptCore/heap/GCActivityCallback.cpp
new file mode 100644
index 000000000..02dc0ef8b
--- /dev/null
+++ b/Source/JavaScriptCore/heap/GCActivityCallback.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GCActivityCallback.h"
+
+#include "Heap.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "VM.h"
+
+#include <wtf/RetainPtr.h>
+#include <wtf/WTFThreadData.h>
+
+#if PLATFORM(EFL)
+#include <wtf/MainThread.h>
+#elif USE(GLIB) && !PLATFORM(QT)
+#include <glib.h>
+#endif
+
+namespace JSC {
+
+bool GCActivityCallback::s_shouldCreateGCTimer = true;
+
+#if USE(CF) || USE(GLIB) || PLATFORM(QT)
+
+const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
+
+#if USE(CF)
+GCActivityCallback::GCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm(), CFRunLoopGetCurrent())
+{
+}
+
+GCActivityCallback::GCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+ : GCActivityCallback(heap->vm(), runLoop)
+{
+}
+#elif PLATFORM(EFL)
+GCActivityCallback::GCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm(), WTF::isMainThread())
+{
+}
+#elif PLATFORM(QT) || USE(GLIB)
+GCActivityCallback::GCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm())
+{
+}
+#endif
+
+void GCActivityCallback::doWork()
+{
+ Heap* heap = &m_vm->heap;
+ if (!isEnabled())
+ return;
+
+ JSLockHolder locker(m_vm);
+ if (heap->isDeferred()) {
+ scheduleTimer(0);
+ return;
+ }
+
+ doCollection();
+}
+
+#if USE(CF)
+void GCActivityCallback::scheduleTimer(double newDelay)
+{
+ if (newDelay * timerSlop > m_delay)
+ return;
+ double delta = m_delay - newDelay;
+ m_delay = newDelay;
+ m_nextFireTime = WTF::currentTime() + newDelay;
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta);
+}
+
+void GCActivityCallback::cancelTimer()
+{
+ m_delay = s_decade;
+ m_nextFireTime = 0;
+ CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
+}
+#elif PLATFORM(EFL)
+void GCActivityCallback::scheduleTimer(double newDelay)
+{
+ if (newDelay * timerSlop > m_delay)
+ return;
+
+ stop();
+ m_delay = newDelay;
+
+ ASSERT(!m_timer);
+ m_timer = add(newDelay, this);
+}
+
+void GCActivityCallback::cancelTimer()
+{
+ m_delay = s_hour;
+ stop();
+}
+#elif PLATFORM(QT)
+void GCActivityCallback::scheduleTimer(double newDelay)
+{
+ if (newDelay * timerSlop > m_delay)
+ return;
+ m_delay = newDelay;
+ m_timer.start(newDelay * 1000, this);
+}
+
+void GCActivityCallback::cancelTimer()
+{
+ m_delay = s_hour;
+ m_timer.stop();
+}
+#elif USE(GLIB)
+void GCActivityCallback::scheduleTimer(double newDelay)
+{
+ ASSERT(newDelay >= 0);
+ if (m_delay != -1 && newDelay * timerSlop > m_delay)
+ return;
+
+ m_delay = newDelay;
+ if (!m_delay) {
+ g_source_set_ready_time(m_timer.get(), 0);
+ return;
+ }
+
+ auto delayDuration = std::chrono::duration<double>(m_delay);
+ auto safeDelayDuration = std::chrono::microseconds::max();
+ if (delayDuration < safeDelayDuration)
+ safeDelayDuration = std::chrono::duration_cast<std::chrono::microseconds>(delayDuration);
+ gint64 currentTime = g_get_monotonic_time();
+ gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, safeDelayDuration.count());
+ ASSERT(targetTime >= currentTime);
+ g_source_set_ready_time(m_timer.get(), targetTime);
+}
+
+void GCActivityCallback::cancelTimer()
+{
+ m_delay = -1;
+ g_source_set_ready_time(m_timer.get(), -1);
+}
+#endif
+
+void GCActivityCallback::didAllocate(size_t bytes)
+{
+#if PLATFORM(EFL)
+ if (!isEnabled())
+ return;
+
+ ASSERT(WTF::isMainThread());
+#endif
+
+ // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate.
+ // We pretend it's one byte so that we don't ignore this allocation entirely.
+ if (!bytes)
+ bytes = 1;
+ double bytesExpectedToReclaim = static_cast<double>(bytes) * deathRate();
+ double newDelay = lastGCLength() / gcTimeSlice(bytesExpectedToReclaim);
+ scheduleTimer(newDelay);
+}
+
+void GCActivityCallback::willCollect()
+{
+ cancelTimer();
+}
+
+void GCActivityCallback::cancel()
+{
+ cancelTimer();
+}
+
+#else
+
+GCActivityCallback::GCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm())
+{
+}
+
+void GCActivityCallback::doWork()
+{
+}
+
+void GCActivityCallback::didAllocate(size_t)
+{
+}
+
+void GCActivityCallback::willCollect()
+{
+}
+
+void GCActivityCallback::cancel()
+{
+}
+
+#endif
+
+}
+