Ignore:
Timestamp:
Oct 25, 2016, 4:22:48 PM (9 years ago)
Author:
[email protected]
Message:

HeapTimer should not hardcode all of its subclasses and USE(CF) shouldn't be a bizarre special case
https://bugs.webkit.org/show_bug.cgi?id=163947

Reviewed by Geoffrey Garen.
Source/JavaScriptCore:


I want to introduce another HeapTimer. Prior to this change, that would have meant writing
exact copies of that timer's logic for each platform that has a HeapTimer (CF, GLIB, and
EFL). That logic would in turn be a duplicate of the logic already present in
IncrementalSweeper and GCActivityCallback: all of the subclasses of HeapTimer have their
own code for scheduling timers, so a new subclass would have to duplicate that code. Then,
to add insult to injury, the USE(CF) version of HeapTimer would have to have an extra case
for that new subclass since it doesn't use virtual methods effectively.

This changes HeapTimer on USE(CF) to know to get its runloop from Heap and to use virtual
methods effectively so that it doesn't have to know about all of its subclasses.

This also moves IncrementalSweeper's code for scheduling timers into HeapTimer. This means
that future subclasses of HeapTimer could simply use that logic.

This keeps changes to GCActivityCallback to a minimum. It still has a lot of
platform-specific code and I'm not sure that this code can be trivially deduplicated since
that code has more quirks. That's fine for now, since I mainly just need a sane way of
creating new timers that use IncrementalSweeper-like scheduling logic.

  • heap/EdenGCActivityCallback.cpp:
  • heap/EdenGCActivityCallback.h:
  • heap/FullGCActivityCallback.cpp:
  • heap/FullGCActivityCallback.h:
  • heap/GCActivityCallback.cpp:

(JSC::GCActivityCallback::GCActivityCallback):

  • heap/GCActivityCallback.h:
  • heap/Heap.cpp:

(JSC::Heap::Heap):

  • heap/Heap.h:

(JSC::Heap::runLoop):

  • heap/HeapTimer.cpp:

(JSC::HeapTimer::HeapTimer):
(JSC::HeapTimer::setRunLoop):
(JSC::HeapTimer::~HeapTimer):
(JSC::HeapTimer::timerDidFire):
(JSC::HeapTimer::scheduleTimer):
(JSC::HeapTimer::cancelTimer):
(JSC::retainAPILock): Deleted.
(JSC::releaseAPILock): Deleted.

  • heap/HeapTimer.h:
  • heap/IncrementalSweeper.cpp:

(JSC::IncrementalSweeper::scheduleTimer):
(JSC::IncrementalSweeper::cancelTimer): Deleted.

  • heap/IncrementalSweeper.h:

Source/WebCore:

No new tests because no new behavior.

  • platform/ios/WebSafeGCActivityCallbackIOS.h:
  • platform/ios/WebSafeIncrementalSweeperIOS.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/HeapTimer.cpp

    r201180 r207855  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4747const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
    4848
    49 static const void* retainAPILock(const void* info)
    50 {
    51     static_cast<JSLock*>(const_cast<void*>(info))->ref();
    52     return info;
    53 }
    54 
    55 static void releaseAPILock(const void* info)
    56 {
    57     static_cast<JSLock*>(const_cast<void*>(info))->deref();
    58 }
    59 
    60 HeapTimer::HeapTimer(VM* vm, CFRunLoopRef runLoop)
    61     : m_vm(vm)
    62     , m_runLoop(runLoop)
    63 {
    64     memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
    65     m_context.info = &vm->apiLock();
    66     m_context.retain = retainAPILock;
    67     m_context.release = releaseAPILock;
    68     m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));
    69     CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
    70 }
    71 
    72 HeapTimer::~HeapTimer()
    73 {
    74     CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
    75     CFRunLoopTimerInvalidate(m_timer.get());
    76 }
    77 
    78 void HeapTimer::timerDidFire(CFRunLoopTimerRef timer, void* context)
    79 {
    80     JSLock* apiLock = static_cast<JSLock*>(context);
    81     apiLock->lock();
    82 
    83     RefPtr<VM> vm = apiLock->vm();
     49HeapTimer::HeapTimer(VM* vm)
     50    : m_vm(vm)
     51    , m_apiLock(&vm->apiLock())
     52{
     53    setRunLoop(vm->heap.runLoop());
     54}
     55
     56void HeapTimer::setRunLoop(CFRunLoopRef runLoop)
     57{
     58    if (m_runLoop) {
     59        CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
     60        CFRunLoopTimerInvalidate(m_timer.get());
     61        m_runLoop.clear();
     62        m_timer.clear();
     63    }
     64   
     65    if (runLoop) {
     66        m_runLoop = runLoop;
     67        memset(&m_context, 0, sizeof(CFRunLoopTimerContext));
     68        m_context.info = this;
     69        m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));
     70        CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
     71    }
     72}
     73
     74HeapTimer::~HeapTimer()
     75{
     76    setRunLoop(0);
     77}
     78
     79void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* contextPtr)
     80{
     81    HeapTimer* timer = static_cast<HeapTimer*>(contextPtr);
     82    timer->m_apiLock->lock();
     83
     84    RefPtr<VM> vm = timer->m_apiLock->vm();
    8485    if (!vm) {
    8586        // The VM has been destroyed, so we should just give up.
    86         apiLock->unlock();
     87        timer->m_apiLock->unlock();
    8788        return;
    8889    }
    89 
    90     HeapTimer* heapTimer = 0;
    91     if (vm->heap.fullActivityCallback() && vm->heap.fullActivityCallback()->m_timer.get() == timer)
    92         heapTimer = vm->heap.fullActivityCallback();
    93     else if (vm->heap.edenActivityCallback() && vm->heap.edenActivityCallback()->m_timer.get() == timer)
    94         heapTimer = vm->heap.edenActivityCallback();
    95     else if (vm->heap.sweeper()->m_timer.get() == timer)
    96         heapTimer = vm->heap.sweeper();
    97     else
    98         RELEASE_ASSERT_NOT_REACHED();
    9990
    10091    {
    10192        JSLockHolder locker(vm.get());
    102         heapTimer->doWork();
    103     }
    104 
    105     apiLock->unlock();
     93        timer->doWork();
     94    }
     95
     96    timer->m_apiLock->unlock();
     97}
     98
     99void HeapTimer::scheduleTimer(double intervalInSeconds)
     100{
     101    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds);
     102}
     103
     104void HeapTimer::cancelTimer()
     105{
     106    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
    106107}
    107108
     
    110111HeapTimer::HeapTimer(VM* vm)
    111112    : m_vm(vm)
     113    , m_apiLock(&vm->apiLock())
    112114    , m_timer(0)
    113115{
     
    144146}
    145147
     148void HeapTimer::scheduleTimer(double intervalInSeconds)
     149{
     150    if (ecore_timer_freeze_get(m_timer))
     151        ecore_timer_thaw(m_timer);
     152
     153    double targetTime = currentTime() + intervalInSeconds;
     154    ecore_timer_interval_set(m_timer, targetTime);
     155}
     156
     157void HeapTimer::cancelTimer()
     158{
     159    ecore_timer_freeze(m_timer);
     160}
    146161#elif USE(GLIB)
    147162
     
    198213}
    199214
     215void HeapTimer::scheduleTimer(double intervalInSeconds)
     216{
     217    auto delayDuration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::duration<double>(intervalInSeconds));
     218    gint64 currentTime = g_get_monotonic_time();
     219    gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, delayDuration.count());
     220    ASSERT(targetTime >= currentTime);
     221    g_source_set_ready_time(m_timer.get(), targetTime);
     222}
     223
     224void HeapTimer::cancelTimer()
     225{
     226    g_source_set_ready_time(m_timer.get(), -1);
     227}
    200228#else
    201229HeapTimer::HeapTimer(VM* vm)
     
    212240}
    213241
     242void HeapTimer::scheduleTimer(double)
     243{
     244}
     245
     246void HeapTimer::cancelTimer()
     247{
     248}
    214249#endif
    215250   
Note: See TracChangeset for help on using the changeset viewer.