diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/HeapTimer.cpp')
-rw-r--r-- | Source/JavaScriptCore/heap/HeapTimer.cpp | 160 |
1 files changed, 92 insertions, 68 deletions
diff --git a/Source/JavaScriptCore/heap/HeapTimer.cpp b/Source/JavaScriptCore/heap/HeapTimer.cpp index 1331b0ac0..9c8b30252 100644 --- a/Source/JavaScriptCore/heap/HeapTimer.cpp +++ b/Source/JavaScriptCore/heap/HeapTimer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,116 +26,137 @@ #include "config.h" #include "HeapTimer.h" -#include "APIShims.h" +#include "GCActivityCallback.h" +#include "IncrementalSweeper.h" #include "JSObject.h" #include "JSString.h" - +#include "JSCInlines.h" #include <wtf/MainThread.h> #include <wtf/Threading.h> -#if PLATFORM(EFL) -#include <Ecore.h> +#if USE(GLIB) +#include <glib.h> #endif namespace JSC { +void HeapTimer::timerDidFire() +{ + m_apiLock->lock(); + + RefPtr<VM> vm = m_apiLock->vm(); + if (!vm) { + // The VM has been destroyed, so we should just give up. + m_apiLock->unlock(); + return; + } + + { + JSLockHolder locker(vm.get()); + doWork(); + } + + m_apiLock->unlock(); +} + #if USE(CF) const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10; -static const void* retainAPILock(const void* info) +HeapTimer::HeapTimer(VM* vm) + : m_vm(vm) + , m_apiLock(&vm->apiLock()) { - static_cast<JSLock*>(const_cast<void*>(info))->ref(); - return info; + setRunLoop(vm->heap.runLoop()); } -static void releaseAPILock(const void* info) +void HeapTimer::setRunLoop(CFRunLoopRef runLoop) { - static_cast<JSLock*>(const_cast<void*>(info))->deref(); + if (m_runLoop) { + CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); + CFRunLoopTimerInvalidate(m_timer.get()); + m_runLoop.clear(); + m_timer.clear(); + } + + if (runLoop) { + m_runLoop = runLoop; + memset(&m_context, 0, sizeof(CFRunLoopTimerContext)); + m_context.info = this; + m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, s_decade, s_decade, 0, 0, HeapTimer::timerDidFireCallback, &m_context)); + CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); + } } -HeapTimer::HeapTimer(VM* vm, CFRunLoopRef runLoop) - : m_vm(vm) - , m_runLoop(runLoop) +HeapTimer::~HeapTimer() { - memset(&m_context, 0, sizeof(CFRunLoopTimerContext)); - m_context.info = &vm->apiLock(); - m_context.retain = retainAPILock; - m_context.release = releaseAPILock; - m_timer = adoptCF(CFRunLoopTimerCreate(0, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context)); - CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); + setRunLoop(0); } -HeapTimer::~HeapTimer() +void HeapTimer::timerDidFireCallback(CFRunLoopTimerRef, void* contextPtr) { - CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); - CFRunLoopTimerInvalidate(m_timer.get()); + static_cast<JSRunLoopTimer*>(contextPtr)->timerDidFire(); } -void HeapTimer::timerDidFire(CFRunLoopTimerRef timer, void* context) +void HeapTimer::scheduleTimer(double intervalInSeconds) { - JSLock* apiLock = static_cast<JSLock*>(context); - apiLock->lock(); - - VM* vm = apiLock->vm(); - // The VM has been destroyed, so we should just give up. - if (!vm) { - apiLock->unlock(); - return; - } + CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds); + m_isScheduled = true; +} - HeapTimer* heapTimer = 0; - if (vm->heap.activityCallback() && vm->heap.activityCallback()->m_timer.get() == timer) - heapTimer = vm->heap.activityCallback(); - else if (vm->heap.sweeper()->m_timer.get() == timer) - heapTimer = vm->heap.sweeper(); - else - RELEASE_ASSERT_NOT_REACHED(); +void HeapTimer::cancelTimer() +{ + CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade); + m_isScheduled = false; +} - { - APIEntryShim shim(vm); - heapTimer->doWork(); - } +#elif USE(GLIB) - apiLock->unlock(); -} +const long HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10; -#elif PLATFORM(EFL) +static GSourceFuncs heapTimerSourceFunctions = { + nullptr, // prepare + nullptr, // check + // dispatch + [](GSource*, GSourceFunc callback, gpointer userData) -> gboolean + { + return callback(userData); + }, + nullptr, // finalize + nullptr, // closure_callback + nullptr, // closure_marshall +}; HeapTimer::HeapTimer(VM* vm) : m_vm(vm) - , m_timer(0) + , m_apiLock(&vm->apiLock()) + , m_timer(adoptGRef(g_source_new(&heapTimerSourceFunctions, sizeof(GSource)))) { + g_source_set_name(m_timer.get(), "[JavaScriptCore] HeapTimer"); + g_source_set_callback(m_timer.get(), [](gpointer userData) -> gboolean { + auto& heapTimer = *static_cast<HeapTimer*>(userData); + g_source_set_ready_time(heapTimer.m_timer.get(), g_get_monotonic_time() + HeapTimer::s_decade * G_USEC_PER_SEC); + heapTimer.timerDidFire(); + return G_SOURCE_CONTINUE; + }, this, nullptr); + g_source_attach(m_timer.get(), g_main_context_get_thread_default()); } HeapTimer::~HeapTimer() { - stop(); + g_source_destroy(m_timer.get()); } -Ecore_Timer* HeapTimer::add(double delay, void* agent) +void HeapTimer::scheduleTimer(double intervalInSeconds) { - return ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerEvent), agent); -} - -void HeapTimer::stop() -{ - if (!m_timer) - return; - - ecore_timer_del(m_timer); - m_timer = 0; + g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + intervalInSeconds * G_USEC_PER_SEC); + m_isScheduled = true; } -bool HeapTimer::timerEvent(void* info) +void HeapTimer::cancelTimer() { - HeapTimer* agent = static_cast<HeapTimer*>(info); - - APIEntryShim shim(agent->m_vm); - agent->doWork(); - agent->m_timer = 0; - - return ECORE_CALLBACK_CANCEL; + g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC); + m_isScheduled = false; } #else HeapTimer::HeapTimer(VM* vm) @@ -147,10 +168,13 @@ HeapTimer::~HeapTimer() { } -void HeapTimer::invalidate() +void HeapTimer::scheduleTimer(double) { } +void HeapTimer::cancelTimer() +{ +} #endif |