diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/GCActivityCallback.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/GCActivityCallback.cpp | 94 |
1 files changed, 88 insertions, 6 deletions
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp index 6ec538f72..794d1545e 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp @@ -29,28 +29,108 @@ #include "config.h" #include "GCActivityCallback.h" +#include "APIShims.h" +#include "Heap.h" +#include "JSGlobalData.h" +#include "JSLock.h" +#include "JSObject.h" +#include "ScopeChain.h" +#include <wtf/RetainPtr.h> +#include <wtf/WTFThreadData.h> + namespace JSC { -struct DefaultGCActivityCallbackPlatformData { -}; +#if USE(CF) + +const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB +const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections. +const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer. +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. +const CFTimeInterval hour = 60 * 60; -DefaultGCActivityCallback::DefaultGCActivityCallback(Heap*) +DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) + : GCActivityCallback(heap->globalData(), CFRunLoopGetCurrent()) + , m_delay(s_decade) { } -DefaultGCActivityCallback::~DefaultGCActivityCallback() +DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop) + : GCActivityCallback(heap->globalData(), runLoop) + , m_delay(s_decade) { } -void DefaultGCActivityCallback::didAllocate(size_t) +void DefaultGCActivityCallback::doWork() +{ + Heap* heap = &m_globalData->heap; + if (!isEnabled()) + return; + + APIEntryShim shim(m_globalData); +#if !PLATFORM(IOS) + double startTime = WTF::monotonicallyIncreasingTime(); + if (heap->isPagedOut(startTime + pagingTimeOut)) { + heap->activityCallback()->cancel(); + heap->increaseLastGCLength(pagingTimeOut); + return; + } +#endif + heap->collectAllGarbage(); +} + +void DefaultGCActivityCallback::scheduleTimer(double newDelay) +{ + if (newDelay * timerSlop > m_delay) + return; + double delta = m_delay - newDelay; + m_delay = newDelay; + CFRunLoopTimerSetNextFireDate(m_timer.get(), CFRunLoopTimerGetNextFireDate(m_timer.get()) - delta); +} + +void DefaultGCActivityCallback::cancelTimer() +{ + m_delay = s_decade; + CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade); +} + +void DefaultGCActivityCallback::didAllocate(size_t bytes) { + // 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; + Heap* heap = static_cast<Heap*>(&m_globalData->heap); + double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice); + double newDelay = heap->lastGCLength() / gcTimeSlice; + scheduleTimer(newDelay); } void DefaultGCActivityCallback::willCollect() { + cancelTimer(); +} + +void DefaultGCActivityCallback::cancel() +{ + cancelTimer(); +} + +#else + +DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) + : GCActivityCallback(heap->globalData()) +{ +} + +void DefaultGCActivityCallback::doWork() +{ } -void DefaultGCActivityCallback::synchronize() +void DefaultGCActivityCallback::didAllocate(size_t) +{ +} + +void DefaultGCActivityCallback::willCollect() { } @@ -58,5 +138,7 @@ void DefaultGCActivityCallback::cancel() { } +#endif + } |