Title: [215223] trunk/Source
Revision
215223
Author
[email protected]
Date
2017-04-11 02:34:36 -0700 (Tue, 11 Apr 2017)

Log Message

[JSC] Enable JSRunLoopTimer for JSCOnly and Windows
https://bugs.webkit.org/show_bug.cgi?id=170655

Reviewed by Carlos Garcia Campos.

Source/_javascript_Core:

* runtime/JSRunLoopTimer.cpp:
(JSC::JSRunLoopTimer::JSRunLoopTimer):
(JSC::JSRunLoopTimer::scheduleTimer):
(JSC::JSRunLoopTimer::cancelTimer):
* runtime/JSRunLoopTimer.h:

Source/WTF:

This patch makes RunLoop::Timer in Generic and Windows thread-safe to use it
in JSC's JSRunLoopTimer. Eventually, we would like to replace JSRunLoopTimer's
platform-dependent implementation to WTF::RunLoop::Timer.

* wtf/RunLoop.h:
* wtf/cf/RunLoopCF.cpp:
(WTF::RunLoop::TimerBase::start):
* wtf/generic/RunLoopGeneric.cpp:
(WTF::RunLoop::TimerBase::ScheduledTask::EarliestSchedule::operator()):
(WTF::RunLoop::populateTasks):
(WTF::RunLoop::runImpl):
(WTF::RunLoop::schedule):
(WTF::RunLoop::scheduleAndWakeUp):
(WTF::RunLoop::TimerBase::~TimerBase):
(WTF::RunLoop::TimerBase::start):
(WTF::RunLoop::TimerBase::stop):
(WTF::RunLoop::TimerBase::isActive):
* wtf/glib/RunLoopGLib.cpp:
(WTF::RunLoop::TimerBase::TimerBase):
* wtf/win/RunLoopWin.cpp:
(WTF::RunLoop::TimerBase::timerFired):
(WTF::RunLoop::TimerBase::start):
(WTF::RunLoop::TimerBase::stop):
(WTF::RunLoop::TimerBase::isActive):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (215222 => 215223)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-11 09:34:36 UTC (rev 215223)
@@ -1,3 +1,16 @@
+2017-04-11  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Enable JSRunLoopTimer for JSCOnly and Windows
+        https://bugs.webkit.org/show_bug.cgi?id=170655
+
+        Reviewed by Carlos Garcia Campos.
+
+        * runtime/JSRunLoopTimer.cpp:
+        (JSC::JSRunLoopTimer::JSRunLoopTimer):
+        (JSC::JSRunLoopTimer::scheduleTimer):
+        (JSC::JSRunLoopTimer::cancelTimer):
+        * runtime/JSRunLoopTimer.h:
+
 2017-04-10  Alex Christensen  <[email protected]>
 
         Revert r215217

Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp (215222 => 215223)


--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp	2017-04-11 09:34:36 UTC (rev 215223)
@@ -161,10 +161,17 @@
     g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC);
     m_isScheduled = false;
 }
+
 #else
+
+const Seconds JSRunLoopTimer::s_decade { 60 * 60 * 24 * 365 * 10 };
+
 JSRunLoopTimer::JSRunLoopTimer(VM* vm)
     : m_vm(vm)
+    , m_apiLock(&vm->apiLock())
+    , m_timer(RunLoop::current(), this, &JSRunLoopTimer::timerDidFire)
 {
+    m_timer.startOneShot(s_decade);
 }
 
 JSRunLoopTimer::~JSRunLoopTimer()
@@ -171,13 +178,18 @@
 {
 }
 
-void JSRunLoopTimer::scheduleTimer(double)
+void JSRunLoopTimer::scheduleTimer(double intervalInSeconds)
 {
+    m_timer.startOneShot(intervalInSeconds);
+    m_isScheduled = true;
 }
 
 void JSRunLoopTimer::cancelTimer()
 {
+    m_timer.startOneShot(s_decade);
+    m_isScheduled = false;
 }
+
 #endif
-    
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h (215222 => 215223)


--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h	2017-04-11 09:34:36 UTC (rev 215223)
@@ -28,6 +28,7 @@
 #include <wtf/Lock.h>
 #include <wtf/RefPtr.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/RunLoop.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/Threading.h>
 
@@ -79,6 +80,9 @@
 #elif USE(GLIB)
     static const long s_decade;
     GRefPtr<GSource> m_timer;
+#else
+    static const Seconds s_decade;
+    RunLoop::Timer<JSRunLoopTimer> m_timer;
 #endif
     
 private:

Modified: trunk/Source/WTF/ChangeLog (215222 => 215223)


--- trunk/Source/WTF/ChangeLog	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/ChangeLog	2017-04-11 09:34:36 UTC (rev 215223)
@@ -1,3 +1,35 @@
+2017-04-11  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Enable JSRunLoopTimer for JSCOnly and Windows
+        https://bugs.webkit.org/show_bug.cgi?id=170655
+
+        Reviewed by Carlos Garcia Campos.
+
+        This patch makes RunLoop::Timer in Generic and Windows thread-safe to use it
+        in JSC's JSRunLoopTimer. Eventually, we would like to replace JSRunLoopTimer's
+        platform-dependent implementation to WTF::RunLoop::Timer.
+
+        * wtf/RunLoop.h:
+        * wtf/cf/RunLoopCF.cpp:
+        (WTF::RunLoop::TimerBase::start):
+        * wtf/generic/RunLoopGeneric.cpp:
+        (WTF::RunLoop::TimerBase::ScheduledTask::EarliestSchedule::operator()):
+        (WTF::RunLoop::populateTasks):
+        (WTF::RunLoop::runImpl):
+        (WTF::RunLoop::schedule):
+        (WTF::RunLoop::scheduleAndWakeUp):
+        (WTF::RunLoop::TimerBase::~TimerBase):
+        (WTF::RunLoop::TimerBase::start):
+        (WTF::RunLoop::TimerBase::stop):
+        (WTF::RunLoop::TimerBase::isActive):
+        * wtf/glib/RunLoopGLib.cpp:
+        (WTF::RunLoop::TimerBase::TimerBase):
+        * wtf/win/RunLoopWin.cpp:
+        (WTF::RunLoop::TimerBase::timerFired):
+        (WTF::RunLoop::TimerBase::start):
+        (WTF::RunLoop::TimerBase::stop):
+        (WTF::RunLoop::TimerBase::isActive):
+
 2017-04-11  Zan Dobersek  <[email protected]>
 
         REGRESSION(r213645): It made JSC tests super slow and timeout on AArch64 Linux

Modified: trunk/Source/WTF/wtf/RunLoop.h (215222 => 215223)


--- trunk/Source/WTF/wtf/RunLoop.h	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/RunLoop.h	2017-04-11 09:34:36 UTC (rev 215223)
@@ -103,7 +103,7 @@
     private:
         WTF_EXPORT_PRIVATE void start(double nextFireInterval, bool repeat);
 
-        RunLoop& m_runLoop;
+        Ref<RunLoop> m_runLoop;
 
 #if USE(WINDOWS_EVENT_LOOP)
         static void timerFired(RunLoop*, uint64_t ID);
@@ -118,6 +118,9 @@
         bool m_isRepeating { false };
         Seconds m_fireInterval { 0 };
 #elif USE(GENERIC_EVENT_LOOP)
+        bool isActive(const AbstractLocker&) const;
+        void stop(const AbstractLocker&);
+
         class ScheduledTask;
         RefPtr<ScheduledTask> m_scheduledTask;
 #endif
@@ -159,6 +162,7 @@
     HWND m_runLoopMessageWindow;
 
     typedef HashMap<uint64_t, TimerBase*> TimerMap;
+    Lock m_activeTimersLock;
     TimerMap m_activeTimers;
 #elif USE(COCOA_EVENT_LOOP)
     static void performWork(void*);
@@ -172,7 +176,7 @@
     void schedule(Ref<TimerBase::ScheduledTask>&&);
     void schedule(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&&);
     void wakeUp(const AbstractLocker&);
-    void scheduleAndWakeUp(Ref<TimerBase::ScheduledTask>&&);
+    void scheduleAndWakeUp(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&&);
 
     enum class RunMode {
         Iterate,
@@ -184,12 +188,14 @@
         Stopping,
     };
     void runImpl(RunMode);
-    bool populateTasks(RunMode, Status&, Deque<Ref<TimerBase::ScheduledTask>>&);
+    bool populateTasks(RunMode, Status&, Deque<RefPtr<TimerBase::ScheduledTask>>&);
 
+    friend class TimerBase;
+
     Lock m_loopLock;
     Condition m_readyToRun;
     Condition m_stopCondition;
-    Vector<Ref<TimerBase::ScheduledTask>> m_schedules;
+    Vector<RefPtr<TimerBase::ScheduledTask>> m_schedules;
     Vector<Status*> m_mainLoops;
     bool m_shutdown { false };
     bool m_pendingTasks { false };

Modified: trunk/Source/WTF/wtf/cf/RunLoopCF.cpp (215222 => 215223)


--- trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2017-04-11 09:34:36 UTC (rev 215223)
@@ -102,7 +102,7 @@
     CFRunLoopTimerContext context = { 0, this, 0, 0, 0 };
     CFTimeInterval repeatInterval = repeat ? nextFireInterval : 0;
     m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context));
-    CFRunLoopAddTimer(m_runLoop.m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+    CFRunLoopAddTimer(m_runLoop->m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
 }
 
 void RunLoop::TimerBase::stop()

Modified: trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp (215222 => 215223)


--- trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/generic/RunLoopGeneric.cpp	2017-04-11 09:34:36 UTC (rev 215223)
@@ -73,7 +73,7 @@
     }
 
     struct EarliestSchedule {
-        bool operator()(const Ref<ScheduledTask>& lhs, const Ref<ScheduledTask>& rhs)
+        bool operator()(const RefPtr<ScheduledTask>& lhs, const RefPtr<ScheduledTask>& rhs)
         {
             return lhs->scheduledTimePoint() > rhs->scheduledTimePoint();
         }
@@ -112,7 +112,7 @@
         m_stopCondition.wait(m_loopLock);
 }
 
-inline bool RunLoop::populateTasks(RunMode runMode, Status& statusOfThisLoop, Deque<Ref<TimerBase::ScheduledTask>>& firedTimers)
+inline bool RunLoop::populateTasks(RunMode runMode, Status& statusOfThisLoop, Deque<RefPtr<TimerBase::ScheduledTask>>& firedTimers)
 {
     LockHolder locker(m_loopLock);
 
@@ -139,7 +139,7 @@
     // Check expired timers.
     MonotonicTime now = MonotonicTime::now();
     while (!m_schedules.isEmpty()) {
-        Ref<TimerBase::ScheduledTask> earliest = m_schedules.first().copyRef();
+        RefPtr<TimerBase::ScheduledTask> earliest = m_schedules.first();
         if (earliest->scheduledTimePoint() > now)
             break;
         std::pop_heap(m_schedules.begin(), m_schedules.end(), TimerBase::ScheduledTask::EarliestSchedule());
@@ -160,7 +160,7 @@
         m_mainLoops.append(&statusOfThisLoop);
     }
 
-    Deque<Ref<TimerBase::ScheduledTask>> firedTimers;
+    Deque<RefPtr<TimerBase::ScheduledTask>> firedTimers;
     while (true) {
         if (!populateTasks(runMode, statusOfThisLoop, firedTimers))
             return;
@@ -167,12 +167,12 @@
 
         // Dispatch scheduled timers.
         while (!firedTimers.isEmpty()) {
-            Ref<TimerBase::ScheduledTask> task = firedTimers.takeFirst();
+            RefPtr<TimerBase::ScheduledTask> task = firedTimers.takeFirst();
             if (task->fired()) {
                 // Reschedule because the timer requires repeating.
                 // Since we will query the timers' time points before sleeping,
                 // we do not call wakeUp() here.
-                schedule(WTFMove(task));
+                schedule(*task);
             }
         }
         performWork();
@@ -220,7 +220,7 @@
 
 void RunLoop::schedule(const AbstractLocker&, Ref<TimerBase::ScheduledTask>&& task)
 {
-    m_schedules.append(WTFMove(task));
+    m_schedules.append(task.ptr());
     std::push_heap(m_schedules.begin(), m_schedules.end(), TimerBase::ScheduledTask::EarliestSchedule());
 }
 
@@ -230,9 +230,8 @@
     schedule(locker, WTFMove(task));
 }
 
-void RunLoop::scheduleAndWakeUp(Ref<TimerBase::ScheduledTask>&& task)
+void RunLoop::scheduleAndWakeUp(const AbstractLocker& locker, Ref<TimerBase::ScheduledTask>&& task)
 {
-    LockHolder locker(m_loopLock);
     schedule(locker, WTFMove(task));
     wakeUp(locker);
 }
@@ -247,11 +246,6 @@
 
 // Since RunLoop does not own the registered TimerBase,
 // TimerBase and its owner should manage these lifetime.
-//
-// And more importantly, TimerBase operations are not thread-safe.
-// So threads that do not belong to the ScheduledTask's RunLoop
-// should not operate the RunLoop::TimerBase.
-// This is the same to the RunLoopWin, which is RunLoop for Windows.
 RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
     : m_runLoop(runLoop)
     , m_scheduledTask(nullptr)
@@ -260,19 +254,21 @@
 
 RunLoop::TimerBase::~TimerBase()
 {
-    stop();
+    LockHolder locker(m_runLoop->m_loopLock);
+    stop(locker);
 }
 
 void RunLoop::TimerBase::start(double interval, bool repeating)
 {
-    stop();
+    LockHolder locker(m_runLoop->m_loopLock);
+    stop(locker);
     m_scheduledTask = ScheduledTask::create([this] {
         fired();
     }, Seconds(interval), repeating);
-    m_runLoop.scheduleAndWakeUp(*m_scheduledTask);
+    m_runLoop->scheduleAndWakeUp(locker, *m_scheduledTask);
 }
 
-void RunLoop::TimerBase::stop()
+void RunLoop::TimerBase::stop(const AbstractLocker&)
 {
     if (m_scheduledTask) {
         m_scheduledTask->deactivate();
@@ -280,8 +276,20 @@
     }
 }
 
+void RunLoop::TimerBase::stop()
+{
+    LockHolder locker(m_runLoop->m_loopLock);
+    stop(locker);
+}
+
 bool RunLoop::TimerBase::isActive() const
 {
+    LockHolder locker(m_runLoop->m_loopLock);
+    return isActive(locker);
+}
+
+bool RunLoop::TimerBase::isActive(const AbstractLocker&) const
+{
     return m_scheduledTask;
 }
 

Modified: trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp (215222 => 215223)


--- trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/glib/RunLoopGLib.cpp	2017-04-11 09:34:36 UTC (rev 215223)
@@ -168,7 +168,7 @@
             timer->updateReadyTime();
         return G_SOURCE_CONTINUE;
     }, this, nullptr);
-    g_source_attach(m_source.get(), m_runLoop.m_mainContext.get());
+    g_source_attach(m_source.get(), m_runLoop->m_mainContext.get());
 }
 
 RunLoop::TimerBase::~TimerBase()

Modified: trunk/Source/WTF/wtf/win/RunLoopWin.cpp (215222 => 215223)


--- trunk/Source/WTF/wtf/win/RunLoopWin.cpp	2017-04-11 09:20:16 UTC (rev 215222)
+++ trunk/Source/WTF/wtf/win/RunLoopWin.cpp	2017-04-11 09:34:36 UTC (rev 215223)
@@ -117,17 +117,21 @@
 
 void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID)
 {
-    TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
-    if (it == runLoop->m_activeTimers.end()) {
-        // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
-        return;
-    }
+    TimerBase* timer = nullptr;
+    {
+        LockHolder locker(runLoop->m_activeTimersLock);
+        TimerMap::iterator it = runLoop->m_activeTimers.find(ID);
+        if (it == runLoop->m_activeTimers.end()) {
+            // The timer must have been stopped after the WM_TIMER message was posted to the message queue.
+            return;
+        }
 
-    TimerBase* timer = it->value;
+        timer = it->value;
 
-    if (!timer->m_isRepeating) {
-        runLoop->m_activeTimers.remove(it);
-        ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+        if (!timer->m_isRepeating) {
+            runLoop->m_activeTimers.remove(it);
+            ::KillTimer(runLoop->m_runLoopMessageWindow, ID);
+        }
     }
 
     timer->fired();
@@ -153,24 +157,27 @@
 
 void RunLoop::TimerBase::start(double nextFireInterval, bool repeat)
 {
+    LockHolder locker(m_runLoop->m_activeTimersLock);
     m_isRepeating = repeat;
-    m_runLoop.m_activeTimers.set(m_ID, this);
-    ::SetTimer(m_runLoop.m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
+    m_runLoop->m_activeTimers.set(m_ID, this);
+    ::SetTimer(m_runLoop->m_runLoopMessageWindow, m_ID, nextFireInterval * 1000, 0);
 }
 
 void RunLoop::TimerBase::stop()
 {
-    TimerMap::iterator it = m_runLoop.m_activeTimers.find(m_ID);
-    if (it == m_runLoop.m_activeTimers.end())
+    LockHolder locker(m_runLoop->m_activeTimersLock);
+    TimerMap::iterator it = m_runLoop->m_activeTimers.find(m_ID);
+    if (it == m_runLoop->m_activeTimers.end())
         return;
 
-    m_runLoop.m_activeTimers.remove(it);
-    ::KillTimer(m_runLoop.m_runLoopMessageWindow, m_ID);
+    m_runLoop->m_activeTimers.remove(it);
+    ::KillTimer(m_runLoop->m_runLoopMessageWindow, m_ID);
 }
 
 bool RunLoop::TimerBase::isActive() const
 {
-    return m_runLoop.m_activeTimers.contains(m_ID);
+    LockHolder locker(m_runLoop->m_activeTimersLock);
+    return m_runLoop->m_activeTimers.contains(m_ID);
 }
 
 } // namespace WTF
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to