Title: [278251] trunk/Source
Revision
278251
Author
[email protected]
Date
2021-05-29 23:51:57 -0700 (Sat, 29 May 2021)

Log Message

Stop using UncheckedLock in JSC::VMInspector
https://bugs.webkit.org/show_bug.cgi?id=226427

Reviewed by Mark Lam.

Source/_javascript_Core:

Stop using UncheckedLock in JSC::VMInspector, as it is being phased out in favor
of Lock, which supports Clang thread safety analysis.

* tools/HeapVerifier.cpp:
(JSC::HeapVerifier::checkIfRecorded):
* tools/SigillCrashAnalyzer.cpp:
(JSC::SigillCrashAnalyzer::analyze):
* tools/VMInspector.cpp:
(JSC::VMInspector::isValidExecutableMemory):
(JSC::VMInspector::codeBlockForMachinePC):
(JSC::VMInspector::lock): Deleted.
* tools/VMInspector.h:
(JSC::VMInspector::WTF_RETURNS_LOCK):
(JSC::VMInspector::WTF_REQUIRES_LOCK):
(JSC::VMInspector::getLock): Deleted.
(JSC::VMInspector::iterate): Deleted.

Source/WTF:

Add Lock::tryLockWithTimeout(), similar to tryLock() but gives up after a
specified timeout. This used to be implemented in VMInspector but I think
Lock is a better place for it.

* wtf/Lock.cpp:
(WTF::Lock::tryLockWithTimeout):
* wtf/Lock.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (278250 => 278251)


--- trunk/Source/_javascript_Core/ChangeLog	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-05-30 06:51:57 UTC (rev 278251)
@@ -1,5 +1,29 @@
 2021-05-29  Chris Dumez  <[email protected]>
 
+        Stop using UncheckedLock in JSC::VMInspector
+        https://bugs.webkit.org/show_bug.cgi?id=226427
+
+        Reviewed by Mark Lam.
+
+        Stop using UncheckedLock in JSC::VMInspector, as it is being phased out in favor
+        of Lock, which supports Clang thread safety analysis.
+
+        * tools/HeapVerifier.cpp:
+        (JSC::HeapVerifier::checkIfRecorded):
+        * tools/SigillCrashAnalyzer.cpp:
+        (JSC::SigillCrashAnalyzer::analyze):
+        * tools/VMInspector.cpp:
+        (JSC::VMInspector::isValidExecutableMemory):
+        (JSC::VMInspector::codeBlockForMachinePC):
+        (JSC::VMInspector::lock): Deleted.
+        * tools/VMInspector.h:
+        (JSC::VMInspector::WTF_RETURNS_LOCK):
+        (JSC::VMInspector::WTF_REQUIRES_LOCK):
+        (JSC::VMInspector::getLock): Deleted.
+        (JSC::VMInspector::iterate): Deleted.
+
+2021-05-29  Chris Dumez  <[email protected]>
+
         Stop using UncheckedLock in JSC::ConcurrentJSLock
         https://bugs.webkit.org/show_bug.cgi?id=226428
 

Modified: trunk/Source/_javascript_Core/tools/HeapVerifier.cpp (278250 => 278251)


--- trunk/Source/_javascript_Core/tools/HeapVerifier.cpp	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/_javascript_Core/tools/HeapVerifier.cpp	2021-05-30 06:51:57 UTC (rev 278251)
@@ -442,16 +442,13 @@
 {
     HeapCell* candidateHeapCell = reinterpret_cast<HeapCell*>(candidateCell);
     
-    VMInspector& inspector = VMInspector::instance();
-    auto expectedLocker = inspector.lock(Seconds(2));
-    if (!expectedLocker) {
-        ASSERT(expectedLocker.error() == VMInspector::Error::TimedOut);
+    auto& inspector = VMInspector::instance();
+    if (!inspector.getLock().tryLockWithTimeout(2_s)) {
         dataLog("ERROR: Timed out while waiting to iterate VMs.");
         return;
     }
-
-    auto& locker = expectedLocker.value();
-    inspector.iterate(locker, [&] (VM& vm) {
+    Locker locker { AdoptLock, inspector.getLock() };
+    inspector.iterate([&] (VM& vm) {
         if (!vm.heap.m_verifier)
             return VMInspector::FunctorStatus::Continue;
         

Modified: trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp (278250 => 278251)


--- trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/_javascript_Core/tools/SigillCrashAnalyzer.cpp	2021-05-30 06:51:57 UTC (rev 278251)
@@ -226,20 +226,18 @@
         // itself crashes.
         context.dump();
 
-        VMInspector& inspector = VMInspector::instance();
+        auto& inspector = VMInspector::instance();
 
         // Use a timeout period of 2 seconds. The client is about to crash, and we don't
         // want to turn the crash into a hang by re-trying the lock for too long.
-        auto expectedLocker = inspector.lock(Seconds(2));
-        if (!expectedLocker) {
-            ASSERT(expectedLocker.error() == VMInspector::Error::TimedOut);
+        if (!inspector.getLock().tryLockWithTimeout(2_s)) {
             log("ERROR: Unable to analyze SIGILL. Timed out while waiting to iterate VMs.");
             break;
         }
-        auto& locker = expectedLocker.value();
+        Locker locker { AdoptLock, inspector.getLock() };
 
         void* pc = context.machinePC.untaggedExecutableAddress();
-        auto isInJITMemory = inspector.isValidExecutableMemory(locker, pc);
+        auto isInJITMemory = inspector.isValidExecutableMemory(pc);
         if (!isInJITMemory) {
             log("ERROR: Timed out: not able to determine if pc %p is in valid JIT executable memory", pc);
             break;
@@ -265,7 +263,7 @@
         log("instruction bits at pc %p is: 0x%08x", pc, wordAtPC);
 #endif
 
-        auto expectedCodeBlock = inspector.codeBlockForMachinePC(locker, pc);
+        auto expectedCodeBlock = inspector.codeBlockForMachinePC(pc);
         if (!expectedCodeBlock) {
             if (expectedCodeBlock.error() == VMInspector::Error::TimedOut)
                 log("ERROR: Timed out: not able to determine if pc %p is in a valid CodeBlock", pc);

Modified: trunk/Source/_javascript_Core/tools/VMInspector.cpp (278250 => 278251)


--- trunk/Source/_javascript_Core/tools/VMInspector.cpp	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/_javascript_Core/tools/VMInspector.cpp	2021-05-30 06:51:57 UTC (rev 278251)
@@ -36,10 +36,6 @@
 #include <mutex>
 #include <wtf/Expected.h>
 
-#if !OS(WINDOWS)
-#include <unistd.h>
-#endif
-
 namespace JSC {
 
 VMInspector& VMInspector::instance()
@@ -64,43 +60,16 @@
     m_vmList.remove(vm);
 }
 
-auto VMInspector::lock(Seconds timeout) -> Expected<UncheckedLockHolder, Error>
-{
-    // This function may be called from a signal handler (e.g. via visit()). Hence,
-    // it should only use APIs that are safe to call from signal handlers. This is
-    // why we use unistd.h's sleep() instead of its alternatives.
-
-    // We'll be doing sleep(1) between tries below. Hence, sleepPerRetry is 1.
-    unsigned maxRetries = (timeout < Seconds::infinity()) ? timeout.value() : UINT_MAX;
-
-    Expected<UncheckedLockHolder, Error> locker = UncheckedLockHolder::tryLock(m_lock);
-    unsigned tryCount = 0;
-    while (!locker && tryCount < maxRetries) {
-        // We want the version of sleep from unistd.h. Cast to disambiguate.
-#if !OS(WINDOWS)
-        (static_cast<unsigned (*)(unsigned)>(sleep))(1);
-#endif
-        locker = UncheckedLockHolder::tryLock(m_lock);
-    }
-
-    if (!locker)
-        return makeUnexpected(Error::TimedOut);
-    return locker;
-}
-
 #if ENABLE(JIT)
-template<typename LockType>
-static bool ensureIsSafeToLock(LockType& lock)
+static bool ensureIsSafeToLock(Lock& lock)
 {
-    unsigned maxRetries = 2;
+    static constexpr unsigned maxRetries = 2;
     unsigned tryCount = 0;
-    while (tryCount <= maxRetries) {
-        bool success = lock.tryLock();
-        if (success) {
+    while (tryCount++ <= maxRetries) {
+        if (lock.tryLock()) {
             lock.unlock();
             return true;
         }
-        tryCount++;
     }
     return false;
 }
@@ -113,7 +82,7 @@
     inspector.iterate(func);
 }
 
-auto VMInspector::isValidExecutableMemory(const UncheckedLockHolder&, void* machinePC) -> Expected<bool, Error>
+auto VMInspector::isValidExecutableMemory(void* machinePC) -> Expected<bool, Error>
 {
 #if ENABLE(JIT)
     bool found = false;
@@ -145,7 +114,7 @@
 #endif
 }
 
-auto VMInspector::codeBlockForMachinePC(const UncheckedLockHolder&, void* machinePC) -> Expected<CodeBlock*, Error>
+auto VMInspector::codeBlockForMachinePC(void* machinePC) -> Expected<CodeBlock*, Error>
 {
 #if ENABLE(JIT)
     CodeBlock* codeBlock = nullptr;

Modified: trunk/Source/_javascript_Core/tools/VMInspector.h (278250 => 278251)


--- trunk/Source/_javascript_Core/tools/VMInspector.h	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/_javascript_Core/tools/VMInspector.h	2021-05-30 06:51:57 UTC (rev 278251)
@@ -48,7 +48,7 @@
     void add(VM*);
     void remove(VM*);
 
-    UncheckedLock& getLock() { return m_lock; }
+    Lock& getLock() WTF_RETURNS_LOCK(m_lock) { return m_lock; }
 
     enum class FunctorStatus {
         Continue,
@@ -55,16 +55,20 @@
         Done
     };
 
-    template <typename Functor>
-    void iterate(const UncheckedLockHolder&, const Functor& functor) { iterate(functor); }
+    template <typename Functor> void iterate(const Functor& functor) WTF_REQUIRES_LOCK(m_lock)
+    {
+        for (VM* vm = m_vmList.head(); vm; vm = vm->next()) {
+            FunctorStatus status = functor(*vm);
+            if (status == FunctorStatus::Done)
+                return;
+        }
+    }
 
     JS_EXPORT_PRIVATE static void forEachVM(Function<FunctorStatus(VM&)>&&);
 
-    Expected<UncheckedLockHolder, Error> lock(Seconds timeout = Seconds::infinity());
+    Expected<bool, Error> isValidExecutableMemory(void*) WTF_REQUIRES_LOCK(m_lock);
+    Expected<CodeBlock*, Error> codeBlockForMachinePC(void*) WTF_REQUIRES_LOCK(m_lock);
 
-    Expected<bool, Error> isValidExecutableMemory(const UncheckedLockHolder&, void*);
-    Expected<CodeBlock*, Error> codeBlockForMachinePC(const UncheckedLockHolder&, void*);
-
     JS_EXPORT_PRIVATE static bool currentThreadOwnsJSLock(VM*);
     JS_EXPORT_PRIVATE static void gc(VM*);
     JS_EXPORT_PRIVATE static void edenGC(VM*);
@@ -92,17 +96,8 @@
     static bool verifyCell(VM&, JSCell*);
 
 private:
-    template <typename Functor> void iterate(const Functor& functor)
-    {
-        for (VM* vm = m_vmList.head(); vm; vm = vm->next()) {
-            FunctorStatus status = functor(*vm);
-            if (status == FunctorStatus::Done)
-                return;
-        }
-    }
-
-    UncheckedLock m_lock;
-    DoublyLinkedList<VM> m_vmList;
+    Lock m_lock;
+    DoublyLinkedList<VM> m_vmList WTF_GUARDED_BY_LOCK(m_lock);
 };
 
 } // namespace JSC

Modified: trunk/Source/WTF/ChangeLog (278250 => 278251)


--- trunk/Source/WTF/ChangeLog	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/WTF/ChangeLog	2021-05-30 06:51:57 UTC (rev 278251)
@@ -1,5 +1,20 @@
 2021-05-29  Chris Dumez  <[email protected]>
 
+        Stop using UncheckedLock in JSC::VMInspector
+        https://bugs.webkit.org/show_bug.cgi?id=226427
+
+        Reviewed by Mark Lam.
+
+        Add Lock::tryLockWithTimeout(), similar to tryLock() but gives up after a
+        specified timeout. This used to be implemented in VMInspector but I think
+        Lock is a better place for it.
+
+        * wtf/Lock.cpp:
+        (WTF::Lock::tryLockWithTimeout):
+        * wtf/Lock.h:
+
+2021-05-29  Chris Dumez  <[email protected]>
+
         Adopt clang thread safety annotations in WTF::DataMutex
         https://bugs.webkit.org/show_bug.cgi?id=226431
 

Modified: trunk/Source/WTF/wtf/Lock.cpp (278250 => 278251)


--- trunk/Source/WTF/wtf/Lock.cpp	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/WTF/wtf/Lock.cpp	2021-05-30 06:51:57 UTC (rev 278251)
@@ -29,6 +29,12 @@
 #include <wtf/LockAlgorithmInlines.h>
 #include <wtf/StackShotProfiler.h>
 
+#if OS(WINDOWS)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
 namespace WTF {
 
 static constexpr bool profileLockContention = false;
@@ -63,5 +69,24 @@
     DefaultLockAlgorithm::safepointSlow(m_byte);
 }
 
+bool Lock::tryLockWithTimeout(Seconds timeout)
+{
+    // This function may be called from a signal handler (e.g. via visit()). Hence,
+    // it should only use APIs that are safe to call from signal handlers. This is
+    // why we use unistd.h's sleep() instead of its alternatives.
+
+    // We'll be doing sleep(1) between tries below. Hence, sleepPerRetry is 1.
+    unsigned maxRetries = (timeout < Seconds::infinity()) ? timeout.value() : std::numeric_limits<unsigned>::max();
+    unsigned tryCount = 0;
+    while (!tryLock() && tryCount++ <= maxRetries) {
+#if OS(WINDOWS)
+        Sleep(1000);
+#else
+        ::sleep(1);
+#endif
+    }
+    return isHeld();
+}
+
 } // namespace WTF
 

Modified: trunk/Source/WTF/wtf/Lock.h (278250 => 278251)


--- trunk/Source/WTF/wtf/Lock.h	2021-05-30 06:13:30 UTC (rev 278250)
+++ trunk/Source/WTF/wtf/Lock.h	2021-05-30 06:51:57 UTC (rev 278251)
@@ -29,6 +29,7 @@
 #include <wtf/LockAlgorithm.h>
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/Seconds.h>
 #include <wtf/ThreadSafetyAnalysis.h>
 
 namespace TestWebKitAPI {
@@ -162,6 +163,7 @@
     void lock() WTF_ACQUIRES_LOCK() { UncheckedLock::lock(); }
     bool tryLock() WTF_ACQUIRES_LOCK_IF(true) { return UncheckedLock::tryLock(); }
     bool try_lock() WTF_ACQUIRES_LOCK_IF(true) { return UncheckedLock::try_lock(); } // NOLINT: Intentional deviation to support std::scoped_lock.
+    WTF_EXPORT_PRIVATE bool tryLockWithTimeout(Seconds timeout) WTF_ACQUIRES_LOCK_IF(true);
     void unlock() WTF_RELEASES_LOCK() { UncheckedLock::unlock(); }
     void unlockFairly() WTF_RELEASES_LOCK() { UncheckedLock::unlockFairly(); }
     void safepoint() { UncheckedLock::safepoint(); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to