From 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 7 May 2012 11:21:11 +0200 Subject: Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286) --- .../runtime/GCActivityCallbackCF.cpp | 62 ++++++++++++++++++---- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp') diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 7f45f0746..8b690a480 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -45,21 +45,34 @@ namespace JSC { struct DefaultGCActivityCallbackPlatformData { - static void trigger(CFRunLoopTimerRef, void *info); + static void timerDidFire(CFRunLoopTimerRef, void *info); RetainPtr timer; RetainPtr runLoop; CFRunLoopTimerContext context; + double delay; }; +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 decade = 60 * 60 * 24 * 365 * 10; +const CFTimeInterval hour = 60 * 60; -void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info) +void DefaultGCActivityCallbackPlatformData::timerDidFire(CFRunLoopTimerRef, void *info) { Heap* heap = static_cast(info); APIEntryShim shim(heap->globalData()); +#if !PLATFORM(IOS) + double startTime = WTF::monotonicallyIncreasingTime(); + if (heap->isPagedOut(startTime + pagingTimeOut)) { + heap->activityCallback()->cancel(); + heap->increaseLastGCLength(pagingTimeOut); + return; + } +#endif heap->collectAllGarbage(); - CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade); } DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) @@ -76,9 +89,6 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback() { CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); CFRunLoopTimerInvalidate(d->timer.get()); - d->context.info = 0; - d->runLoop = 0; - d->timer = 0; } void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop) @@ -88,14 +98,41 @@ void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLo memset(&d->context, 0, sizeof(CFRunLoopTimerContext)); d->context.info = heap; d->runLoop = runLoop; - d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context)); + d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::timerDidFire, &d->context)); + d->delay = decade; CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); } -void DefaultGCActivityCallback::operator()() +static void scheduleTimer(DefaultGCActivityCallbackPlatformData* d, double newDelay) +{ + if (newDelay * timerSlop > d->delay) + return; + double delta = d->delay - newDelay; + d->delay = newDelay; + CFRunLoopTimerSetNextFireDate(d->timer.get(), CFRunLoopTimerGetNextFireDate(d->timer.get()) - delta); +} + +static void cancelTimer(DefaultGCActivityCallbackPlatformData* d) { - CFTimeInterval triggerInterval = static_cast(d->context.info)->lastGCLength() * 100.0; - CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval); + d->delay = decade; + CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + 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(d->context.info); + double gcTimeSlice = std::min((static_cast(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice); + double newDelay = heap->lastGCLength() / gcTimeSlice; + scheduleTimer(d.get(), newDelay); +} + +void DefaultGCActivityCallback::willCollect() +{ + cancelTimer(d.get()); } void DefaultGCActivityCallback::synchronize() @@ -107,4 +144,9 @@ void DefaultGCActivityCallback::synchronize() CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); } +void DefaultGCActivityCallback::cancel() +{ + cancelTimer(d.get()); +} + } -- cgit v1.2.1