Title: [264696] trunk/Source
Revision
264696
Author
[email protected]
Date
2020-07-22 08:07:01 -0700 (Wed, 22 Jul 2020)

Log Message

JSRunLoopTimer should use WTF::RunLoop rather than custom CF code
https://bugs.webkit.org/show_bug.cgi?id=214102

Unreviewed, re-landing r264242 with crash fixed.

Source/_javascript_Core:

We needed to synchronize timer destruction with timer firing.


* runtime/DeferredWorkTimer.cpp:
(JSC::DeferredWorkTimer::doWork):
(JSC::DeferredWorkTimer::runRunLoop):
* runtime/JSRunLoopTimer.cpp:
(JSC::epochTime):
(JSC::JSRunLoopTimer::Manager::PerVMData::PerVMData):
(JSC::JSRunLoopTimer::Manager::timerDidFireCallback):
(JSC::JSRunLoopTimer::Manager::PerVMData::~PerVMData):
(JSC::JSRunLoopTimer::Manager::timerDidFire):
(JSC::JSRunLoopTimer::Manager::registerVM):
(JSC::JSRunLoopTimer::Manager::scheduleTimer):
(JSC::JSRunLoopTimer::Manager::cancelTimer):
(JSC::JSRunLoopTimer::Manager::PerVMData::setRunLoop): Deleted.
(JSC::JSRunLoopTimer::Manager::didChangeRunLoop): Deleted.
* runtime/JSRunLoopTimer.h:
(JSC::JSRunLoopTimer::Manager::PerVMData::PerVMData): Deleted.
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::create):
(JSC::VM::tryCreate):
(JSC::VM::setRunLoop): Deleted.
* runtime/VM.h:
(JSC::VM::runLoop const):

Source/WebCore:

Since I was here, I applied Darin's previous review feedback that I had
missed.


* bindings/js/CommonVM.cpp:
(WebCore::commonVMSlow):

Source/WTF:

To support JSC using external locking around a RunLoop timer, we needed
to avoid modifying unsynchronized timer state while firing.


* wtf/cf/RunLoopCF.cpp:
(WTF::RunLoop::TimerBase::start):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (264695 => 264696)


--- trunk/Source/_javascript_Core/ChangeLog	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-07-22 15:07:01 UTC (rev 264696)
@@ -1,3 +1,36 @@
+2020-07-22  Geoffrey Garen  <[email protected]>
+
+        JSRunLoopTimer should use WTF::RunLoop rather than custom CF code
+        https://bugs.webkit.org/show_bug.cgi?id=214102
+
+        Unreviewed, re-landing r264242 with crash fixed.
+
+        We needed to synchronize timer destruction with timer firing.
+
+        * runtime/DeferredWorkTimer.cpp:
+        (JSC::DeferredWorkTimer::doWork):
+        (JSC::DeferredWorkTimer::runRunLoop):
+        * runtime/JSRunLoopTimer.cpp:
+        (JSC::epochTime):
+        (JSC::JSRunLoopTimer::Manager::PerVMData::PerVMData):
+        (JSC::JSRunLoopTimer::Manager::timerDidFireCallback):
+        (JSC::JSRunLoopTimer::Manager::PerVMData::~PerVMData):
+        (JSC::JSRunLoopTimer::Manager::timerDidFire):
+        (JSC::JSRunLoopTimer::Manager::registerVM):
+        (JSC::JSRunLoopTimer::Manager::scheduleTimer):
+        (JSC::JSRunLoopTimer::Manager::cancelTimer):
+        (JSC::JSRunLoopTimer::Manager::PerVMData::setRunLoop): Deleted.
+        (JSC::JSRunLoopTimer::Manager::didChangeRunLoop): Deleted.
+        * runtime/JSRunLoopTimer.h:
+        (JSC::JSRunLoopTimer::Manager::PerVMData::PerVMData): Deleted.
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::create):
+        (JSC::VM::tryCreate):
+        (JSC::VM::setRunLoop): Deleted.
+        * runtime/VM.h:
+        (JSC::VM::runLoop const):
+
 2020-07-21  Mark Lam  <[email protected]>
 
         Simplify DisallowScope, DisallowGC, and DisallowVMReentry implementations.

Modified: trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp (264695 => 264696)


--- trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp	2020-07-22 15:07:01 UTC (rev 264696)
@@ -81,13 +81,8 @@
         }
     }
 
-    if (m_pendingTickets.isEmpty() && m_shouldStopRunLoopWhenAllTicketsFinish) {
-#if USE(CF)
-        CFRunLoopStop(vm.runLoop());
-#else
+    if (m_pendingTickets.isEmpty() && m_shouldStopRunLoopWhenAllTicketsFinish)
         RunLoop::current().stop();
-#endif
-    }
 
     m_taskLock.unlock();
 }
@@ -95,17 +90,10 @@
 void DeferredWorkTimer::runRunLoop()
 {
     ASSERT(!m_apiLock->vm()->currentThreadIsHoldingAPILock());
-#if USE(CF)
-    ASSERT(CFRunLoopGetCurrent() == m_apiLock->vm()->runLoop());
-#endif
+    ASSERT(&RunLoop::current() == &m_apiLock->vm()->runLoop());
     m_shouldStopRunLoopWhenAllTicketsFinish = true;
-    if (m_pendingTickets.size()) {
-#if USE(CF)
-        CFRunLoopRun();
-#else
+    if (m_pendingTickets.size())
         RunLoop::run();
-#endif
-    }
 }
 
 void DeferredWorkTimer::addPendingWork(VM& vm, Ticket ticket, Vector<Strong<JSCell>>&& dependencies)

Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp (264695 => 264696)


--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.cpp	2020-07-22 15:07:01 UTC (rev 264696)
@@ -40,47 +40,13 @@
 
 static inline JSRunLoopTimer::Manager::EpochTime epochTime(Seconds delay)
 {
-#if USE(CF)
-    return Seconds { CFAbsoluteTimeGetCurrent() + delay.value() };
-#else
     return MonotonicTime::now().secondsSinceEpoch() + delay;
-#endif
 }
 
-#if USE(CF)
-void JSRunLoopTimer::Manager::timerDidFireCallback(CFRunLoopTimerRef, void* contextPtr)
+JSRunLoopTimer::Manager::PerVMData::PerVMData(Manager& manager, RunLoop& runLoop)
+    : runLoop(runLoop)
+    , timer(makeUnique<RunLoop::Timer<Manager>>(runLoop, &manager, &JSRunLoopTimer::Manager::timerDidFireCallback))
 {
-    static_cast<JSRunLoopTimer::Manager*>(contextPtr)->timerDidFire();
-}
-
-void JSRunLoopTimer::Manager::PerVMData::setRunLoop(Manager* manager, CFRunLoopRef newRunLoop)
-{
-    if (runLoop) {
-        CFRunLoopRemoveTimer(runLoop.get(), timer.get(), kCFRunLoopCommonModes);
-        CFRunLoopTimerInvalidate(timer.get());
-        runLoop.clear();
-        timer.clear();
-    }
-
-    if (newRunLoop) {
-        runLoop = newRunLoop;
-        memset(&context, 0, sizeof(CFRunLoopTimerContext));
-        RELEASE_ASSERT(manager);
-        context.info = manager;
-        timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + s_decade.seconds(), CFAbsoluteTimeGetCurrent() + s_decade.seconds(), 0, 0, JSRunLoopTimer::Manager::timerDidFireCallback, &context));
-        CFRunLoopAddTimer(runLoop.get(), timer.get(), kCFRunLoopCommonModes);
-
-        EpochTime scheduleTime = epochTime(s_decade);
-        for (auto& pair : timers)
-            scheduleTime = std::min(pair.second, scheduleTime);
-        CFRunLoopTimerSetNextFireDate(timer.get(), scheduleTime.value());
-    }
-}
-#else
-JSRunLoopTimer::Manager::PerVMData::PerVMData(Manager& manager)
-    : runLoop(&RunLoop::current())
-    , timer(makeUnique<RunLoop::Timer<Manager>>(*runLoop, &manager, &JSRunLoopTimer::Manager::timerDidFireCallback))
-{
 #if USE(GLIB_EVENT_LOOP)
     timer->setPriority(RunLoopSourcePriority::_javascript_Timer);
     timer->setName("[_javascript_Core] JSRunLoopTimer");
@@ -91,13 +57,14 @@
 {
     timerDidFire();
 }
-#endif
 
 JSRunLoopTimer::Manager::PerVMData::~PerVMData()
 {
-#if USE(CF)
-    setRunLoop(nullptr, nullptr);
-#endif
+    // Because RunLoop::Timer is not reference counted, we need to deallocate it
+    // on the same thread on which it fires; otherwise, we might deallocate it
+    // while it's firing.
+    runLoop->dispatch([timer = WTFMove(timer)] {
+    });
 }
 
 void JSRunLoopTimer::Manager::timerDidFire()
@@ -106,21 +73,12 @@
 
     {
         auto locker = holdLock(m_lock);
-#if USE(CF)
-        CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
-#else
         RunLoop* currentRunLoop = &RunLoop::current();
-#endif
         EpochTime nowEpochTime = epochTime(0_s);
         for (auto& entry : m_mapping) {
             PerVMData& data = ""
-#if USE(CF)
-            if (data.runLoop.get() != currentRunLoop)
+            if (data.runLoop.ptr() != currentRunLoop)
                 continue;
-#else
-            if (data.runLoop != currentRunLoop)
-                continue;
-#endif
             
             EpochTime scheduleTime = epochTime(s_decade);
             for (size_t i = 0; i < data.timers.size(); ++i) {
@@ -140,11 +98,7 @@
                 timersToFire.append(WTFMove(pair.first));
             }
 
-#if USE(CF)
-            CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value());
-#else
             data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch()));
-#endif
         }
     }
 
@@ -164,10 +118,7 @@
 
 void JSRunLoopTimer::Manager::registerVM(VM& vm)
 {
-    auto data = ""
-#if USE(CF)
-    data->setRunLoop(this, vm.runLoop());
-#endif
+    auto data = "" vm.runLoop());
 
     auto locker = holdLock(m_lock);
     auto addResult = m_mapping.add({ vm.apiLock() }, WTFMove(data));
@@ -205,11 +156,7 @@
     if (!found)
         data.timers.append({ timer, fireEpochTime });
 
-#if USE(CF)
-    CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value());
-#else
     data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch()));
-#endif
 }
 
 void JSRunLoopTimer::Manager::cancelTimer(JSRunLoopTimer& timer)
@@ -240,11 +187,7 @@
         scheduleTime = std::min(scheduleTime, data.timers[i].second);
     }
 
-#if USE(CF)
-    CFRunLoopTimerSetNextFireDate(data.timer.get(), scheduleTime.value());
-#else
     data.timer->startOneShot(std::max(0_s, scheduleTime - MonotonicTime::now().secondsSinceEpoch()));
-#endif
 }
 
 Optional<Seconds> JSRunLoopTimer::Manager::timeUntilFire(JSRunLoopTimer& timer)
@@ -264,18 +207,6 @@
     return WTF::nullopt;
 }
 
-#if USE(CF)
-void JSRunLoopTimer::Manager::didChangeRunLoop(VM& vm, CFRunLoopRef newRunLoop)
-{
-    auto locker = holdLock(m_lock);
-    auto iter = m_mapping.find({ vm.apiLock() });
-    RELEASE_ASSERT(iter != m_mapping.end());
-
-    PerVMData& data = ""
-    data.setRunLoop(this, newRunLoop);
-}
-#endif
-
 void JSRunLoopTimer::timerDidFire()
 {
     NO_TAIL_CALLS();

Modified: trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h (264695 => 264696)


--- trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/runtime/JSRunLoopTimer.h	2020-07-22 15:07:01 UTC (rev 264696)
@@ -33,10 +33,6 @@
 #include <wtf/SharedTask.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
-#if USE(CF)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
 namespace JSC {
 
 class JSLock;
@@ -50,11 +46,8 @@
     class Manager {
         WTF_MAKE_FAST_ALLOCATED;
         WTF_MAKE_NONCOPYABLE(Manager);
-#if USE(CF)
-        static void timerDidFireCallback(CFRunLoopTimerRef, void*);
-#else
         void timerDidFireCallback();
-#endif
+
         Manager() = default;
 
         void timerDidFire();
@@ -70,10 +63,6 @@
 
         Optional<Seconds> timeUntilFire(JSRunLoopTimer&);
 
-#if USE(CF)
-        void didChangeRunLoop(VM&, CFRunLoopRef newRunLoop);
-#endif
-
     private:
         Lock m_lock;
 
@@ -81,22 +70,11 @@
             WTF_MAKE_FAST_ALLOCATED;
             WTF_MAKE_NONCOPYABLE(PerVMData);
         public:
-#if USE(CF)
-            PerVMData(Manager&) { }
-#else
-            PerVMData(Manager&);
-#endif
+            PerVMData(Manager&, WTF::RunLoop&);
             ~PerVMData();
 
-#if USE(CF)
-            void setRunLoop(Manager*, CFRunLoopRef);
-            RetainPtr<CFRunLoopTimerRef> timer;
-            RetainPtr<CFRunLoopRef> runLoop;
-            CFRunLoopTimerContext context;
-#else
-            RunLoop* runLoop;
+            Ref<WTF::RunLoop> runLoop;
             std::unique_ptr<RunLoop::Timer<Manager>> timer;
-#endif
             Vector<std::pair<Ref<JSRunLoopTimer>, EpochTime>> timers;
         };
 

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (264695 => 264696)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2020-07-22 15:07:01 UTC (rev 264696)
@@ -264,12 +264,10 @@
 
 static bool vmCreationShouldCrash = false;
 
-VM::VM(VMType vmType, HeapType heapType, bool* success)
+VM::VM(VMType vmType, HeapType heapType, WTF::RunLoop* runLoop, bool* success)
     : m_id(nextID())
     , m_apiLock(adoptRef(new JSLock(this)))
-#if USE(CF)
-    , m_runLoop(CFRunLoopGetCurrent())
-#endif // USE(CF)
+    , m_runLoop(runLoop ? *runLoop : WTF::RunLoop::current())
     , m_random(Options::seedOfVMRandomForFuzzer() ? Options::seedOfVMRandomForFuzzer() : cryptographicallyRandomNumber())
     , m_integrityRandom(*this)
     , heap(*this, heapType)
@@ -681,15 +679,15 @@
     return adoptRef(*new VM(APIContextGroup, heapType));
 }
 
-Ref<VM> VM::create(HeapType heapType)
+Ref<VM> VM::create(HeapType heapType, WTF::RunLoop* runLoop)
 {
-    return adoptRef(*new VM(Default, heapType));
+    return adoptRef(*new VM(Default, heapType, runLoop));
 }
 
-RefPtr<VM> VM::tryCreate(HeapType heapType)
+RefPtr<VM> VM::tryCreate(HeapType heapType, WTF::RunLoop* runLoop)
 {
     bool success = true;
-    RefPtr<VM> vm = adoptRef(new VM(Default, heapType, &success));
+    RefPtr<VM> vm = adoptRef(new VM(Default, heapType, runLoop, &success));
     if (!success) {
         // Here, we're destructing a partially constructed VM and we know that
         // no one else can be using it at the same time. So, acquiring the lock
@@ -1387,15 +1385,6 @@
 }
 #endif
 
-#if USE(CF)
-void VM::setRunLoop(CFRunLoopRef runLoop)
-{
-    ASSERT(runLoop);
-    m_runLoop = runLoop;
-    JSRunLoopTimer::Manager::shared().didChangeRunLoop(*this, runLoop);
-}
-#endif // USE(CF)
-
 ScratchBuffer* VM::scratchBufferForSize(size_t size)
 {
     if (!size)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (264695 => 264696)


--- trunk/Source/_javascript_Core/runtime/VM.h	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2020-07-22 15:07:01 UTC (rev 264696)
@@ -95,6 +95,7 @@
 #endif
 
 namespace WTF {
+class RunLoop;
 class SimpleStats;
 } // namespace WTF
 using WTF::SimpleStats;
@@ -314,8 +315,8 @@
     JS_EXPORT_PRIVATE static bool sharedInstanceExists();
     JS_EXPORT_PRIVATE static VM& sharedInstance();
 
-    JS_EXPORT_PRIVATE static Ref<VM> create(HeapType = SmallHeap);
-    JS_EXPORT_PRIVATE static RefPtr<VM> tryCreate(HeapType = SmallHeap);
+    JS_EXPORT_PRIVATE static Ref<VM> create(HeapType = SmallHeap, WTF::RunLoop* = nullptr);
+    JS_EXPORT_PRIVATE static RefPtr<VM> tryCreate(HeapType = SmallHeap, WTF::RunLoop* = nullptr);
     static Ref<VM> createContextGroup(HeapType = SmallHeap);
     JS_EXPORT_PRIVATE ~VM();
 
@@ -356,10 +357,7 @@
 
     unsigned m_id;
     RefPtr<JSLock> m_apiLock;
-#if USE(CF)
-    // These need to be initialized before heap below.
-    RetainPtr<CFRunLoopRef> m_runLoop;
-#endif
+    Ref<WTF::RunLoop> m_runLoop;
 
     WeakRandom m_random;
     Integrity::Random m_integrityRandom;
@@ -1087,10 +1085,7 @@
     bool needExceptionCheck() const { return m_needExceptionCheck; }
 #endif
 
-#if USE(CF)
-    CFRunLoopRef runLoop() const { return m_runLoop.get(); }
-    JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
-#endif // USE(CF)
+    WTF::RunLoop& runLoop() const { return m_runLoop; }
 
     static void setCrashOnVMCreation(bool);
 
@@ -1114,7 +1109,7 @@
 private:
     friend class LLIntOffsetsExtractor;
 
-    VM(VMType, HeapType, bool* success = nullptr);
+    VM(VMType, HeapType, WTF::RunLoop* = nullptr, bool* success = nullptr);
     static VM*& sharedInstanceInternal();
     void createNativeThunk();
 

Modified: trunk/Source/WTF/ChangeLog (264695 => 264696)


--- trunk/Source/WTF/ChangeLog	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/WTF/ChangeLog	2020-07-22 15:07:01 UTC (rev 264696)
@@ -1,3 +1,16 @@
+2020-07-22  Geoffrey Garen  <[email protected]>
+
+        JSRunLoopTimer should use WTF::RunLoop rather than custom CF code
+        https://bugs.webkit.org/show_bug.cgi?id=214102
+
+        Unreviewed, re-landing r264242 with crash fixed.
+
+        To support JSC using external locking around a RunLoop timer, we needed
+        to avoid modifying unsynchronized timer state while firing.
+
+        * wtf/cf/RunLoopCF.cpp:
+        (WTF::RunLoop::TimerBase::start):
+
 2020-07-21  Eric Carlson  <[email protected]>
 
         Use AVRoutePickerView when available for choosing AirPlay devices

Modified: trunk/Source/WTF/wtf/cf/RunLoopCF.cpp (264695 => 264696)


--- trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/WTF/wtf/cf/RunLoopCF.cpp	2020-07-22 15:07:01 UTC (rev 264696)
@@ -121,7 +121,7 @@
 
         auto timer = static_cast<TimerBase*>(context);
         if (!CFRunLoopTimerDoesRepeat(cfTimer))
-            timer->stop();
+            CFRunLoopTimerInvalidate(cfTimer);
 
         timer->fired();
     }, this);

Modified: trunk/Source/WebCore/ChangeLog (264695 => 264696)


--- trunk/Source/WebCore/ChangeLog	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/WebCore/ChangeLog	2020-07-22 15:07:01 UTC (rev 264696)
@@ -1,3 +1,16 @@
+2020-07-22  Geoffrey Garen  <[email protected]>
+
+        JSRunLoopTimer should use WTF::RunLoop rather than custom CF code
+        https://bugs.webkit.org/show_bug.cgi?id=214102
+
+        Unreviewed, re-landing r264242 with crash fixed.
+
+        Since I was here, I applied Darin's previous review feedback that I had
+        missed.
+
+        * bindings/js/CommonVM.cpp:
+        (WebCore::commonVMSlow):
+
 2020-07-19  Darin Adler  <[email protected]>
 
         Remove live ranges from Editor.h and EditorClient.h

Modified: trunk/Source/WebCore/bindings/js/CommonVM.cpp (264695 => 264696)


--- trunk/Source/WebCore/bindings/js/CommonVM.cpp	2020-07-22 12:22:44 UTC (rev 264695)
+++ trunk/Source/WebCore/bindings/js/CommonVM.cpp	2020-07-22 15:07:01 UTC (rev 264696)
@@ -56,8 +56,14 @@
     // Also, initializeMainThread() does nothing on iOS.
     ScriptController::initializeMainThread();
 
-    auto& vm = JSC::VM::create(JSC::LargeHeap).leakRef();
+#if PLATFORM(IOS_FAMILY)
+    RunLoop* runLoop = RunLoop::webIfExists();
+#else
+    RunLoop* runLoop = nullptr;
+#endif
 
+    auto& vm = JSC::VM::create(JSC::LargeHeap, runLoop).leakRef();
+
     g_commonVMOrNull = &vm;
 
     vm.heap.acquireAccess(); // At any time, we may do things that affect the GC.
@@ -65,7 +71,6 @@
 #if PLATFORM(IOS_FAMILY)
     if (WebThreadIsEnabled())
         vm.apiLock().makeWebThreadAware();
-    vm.setRunLoop(WebThreadRunLoop());
     vm.heap.machineThreads().addCurrentThread();
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to