Title: [267591] trunk/Source
Revision
267591
Author
[email protected]
Date
2020-09-25 13:36:50 -0700 (Fri, 25 Sep 2020)

Log Message

Get rid of AudioNode::RefType
https://bugs.webkit.org/show_bug.cgi?id=216945

Reviewed by Darin Adler.

Source/_javascript_Core:

* runtime/CachedTypes.cpp:
(JSC::CachedRefPtr::decode const):

Source/WebCore:

Previously, the node had ref()/deref() function taking a RefType parameter.
The RefType would be used to determine which counter should be incremented
or decremented: either m_normalRefCount or m_connectionRefCount.

In a previous patch, I have already ported code that was calling ref() / deref()
explicitly with RefTypeNormal to use RefPtr<> instead. This patch goes further by:
1. Dropping the RefType parameter to ref() / deref(). ref() / deref() now increment
   or decrement m_normalRefCount only. Clients are expected to use RefPtr to handle
   ref counting.
2. Introduce new incrementConnectionCount() / decrementConnectionCount() to increment
   or decrement m_connectionRefCount. To reduce the chance of leakage, clients should
   not call these functions directly anymore. Instead, they use use the new
   AudioConnectionRefPtr<> pointer type to handle the connection ref counting for them.
   AudioConnectionRefPtr<> is a RefPtr<> which special traits causing incrementConnectionCount()
   and decrementConnectionCount() to get called on the AudioNode instead of ref() and
   deref().

I believe this new design is a bit simpler to reason about and less prone to leaks.
There is no longer any code explicitly ref'ing or deref'ing the AudioNodes. Instead,
RefPtr<> or AudioConnectionRefPtr<> is used to increment/decrement the right internal
count.

No new tests, no Web-facing behavior change.

* Modules/webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::setPannerNode):
(WebCore::AudioBufferSourceNode::clearPannerNode):
* Modules/webaudio/AudioBufferSourceNode.h:
* Modules/webaudio/AudioNode.cpp:
(WebCore::AudioNode::disableOutputsIfNecessary):
(WebCore::AudioNode::incrementConnectionCount):
(WebCore::AudioNode::decrementConnectionCount):
(WebCore::AudioNode::decrementConnectionCountWithLock):
(WebCore::AudioNode::markNodeForDeletionIfNecessary):
(WebCore::AudioNode::ref):
(WebCore::AudioNode::deref):
(WebCore::AudioNode::derefWithLock):
* Modules/webaudio/AudioNode.h:
(WebCore::AudioNodeConnectionRefDerefTraits::refIfNotNull):
(WebCore::AudioNodeConnectionRefDerefTraits::derefIfNotNull):
* Modules/webaudio/AudioNodeInput.cpp:
(WebCore::AudioNodeInput::connect):
(WebCore::AudioNodeInput::disconnect):
* Modules/webaudio/AudioNodeOutput.cpp:
(WebCore::AudioNodeOutput::propagateChannelCount):
(WebCore::AudioNodeOutput::addInput):
(WebCore::AudioNodeOutput::disconnectAllInputs):
(WebCore::AudioNodeOutput::disable):
(WebCore::AudioNodeOutput::enable):
* Modules/webaudio/AudioNodeOutput.h:
* Modules/webaudio/BaseAudioContext.cpp:
(WebCore::BaseAudioContext::~BaseAudioContext):
(WebCore::BaseAudioContext::refNode):
(WebCore::BaseAudioContext::derefNode):
(WebCore::BaseAudioContext::derefUnfinishedSourceNodes):
(WebCore::BaseAudioContext::addDeferredDecrementConnectionCount):
(WebCore::BaseAudioContext::handlePostRenderTasks):
(WebCore::BaseAudioContext::handleDeferredDecrementConnectionCounts):
* Modules/webaudio/BaseAudioContext.h:
* Modules/webaudio/ScriptProcessorNode.cpp:
(WebCore::ScriptProcessorNode::process):

Source/WTF:

Add third template parameter to RefPtr allowing to define the traits
from incrementing / decrementing the refcount. The default traits
call ref() / deref() but this can now be customized to call other
functions.

* wtf/CompactRefPtrTuple.h:
* wtf/Forward.h:
* wtf/RefPtr.h:
(WTF::DefaultRefDerefTraits::refIfNotNull):
(WTF::DefaultRefDerefTraits::derefIfNotNull):
(WTF::RefPtr::RefPtr):
(WTF::RefPtr::~RefPtr):
(WTF::V>::RefPtr):
(WTF::V>::leakRef):
(WTF::=):
(WTF::V>::swap):
(WTF::swap):
(WTF::operator==):
(WTF::operator!=):
(WTF::static_pointer_cast):
(WTF::adoptRef):
(WTF::is):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (267590 => 267591)


--- trunk/Source/_javascript_Core/ChangeLog	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-09-25 20:36:50 UTC (rev 267591)
@@ -1,3 +1,13 @@
+2020-09-25  Chris Dumez  <[email protected]>
+
+        Get rid of AudioNode::RefType
+        https://bugs.webkit.org/show_bug.cgi?id=216945
+
+        Reviewed by Darin Adler.
+
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedRefPtr::decode const):
+
 2020-09-25  Alexey Shvayka  <[email protected]>
 
         DataView instances should not have own "byteLength" and "byteOffset" properties

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (267590 => 267591)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -554,10 +554,10 @@
             return nullptr;
         if (isNewAllocation) {
             decoder.addFinalizer([=] {
-                derefIfNotNull(decodedPtr);
+                WTF::DefaultRefDerefTraits<Source>::derefIfNotNull(decodedPtr);
             });
         }
-        refIfNotNull(decodedPtr);
+        WTF::DefaultRefDerefTraits<Source>::refIfNotNull(decodedPtr);
         return adoptRef(decodedPtr);
     }
 

Modified: trunk/Source/WTF/ChangeLog (267590 => 267591)


--- trunk/Source/WTF/ChangeLog	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WTF/ChangeLog	2020-09-25 20:36:50 UTC (rev 267591)
@@ -1,3 +1,33 @@
+2020-09-25  Chris Dumez  <[email protected]>
+
+        Get rid of AudioNode::RefType
+        https://bugs.webkit.org/show_bug.cgi?id=216945
+
+        Reviewed by Darin Adler.
+
+        Add third template parameter to RefPtr allowing to define the traits
+        from incrementing / decrementing the refcount. The default traits
+        call ref() / deref() but this can now be customized to call other
+        functions.
+
+        * wtf/CompactRefPtrTuple.h:
+        * wtf/Forward.h:
+        * wtf/RefPtr.h:
+        (WTF::DefaultRefDerefTraits::refIfNotNull):
+        (WTF::DefaultRefDerefTraits::derefIfNotNull):
+        (WTF::RefPtr::RefPtr):
+        (WTF::RefPtr::~RefPtr):
+        (WTF::V>::RefPtr):
+        (WTF::V>::leakRef):
+        (WTF::=):
+        (WTF::V>::swap):
+        (WTF::swap):
+        (WTF::operator==):
+        (WTF::operator!=):
+        (WTF::static_pointer_cast):
+        (WTF::adoptRef):
+        (WTF::is):
+
 2020-09-25  Antti Koivisto  <[email protected]>
 
         [LFC][Integration] Enable on Apple Windows port

Modified: trunk/Source/WTF/wtf/CompactRefPtrTuple.h (267590 => 267591)


--- trunk/Source/WTF/wtf/CompactRefPtrTuple.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WTF/wtf/CompactRefPtrTuple.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -39,7 +39,7 @@
     CompactRefPtrTuple() = default;
     ~CompactRefPtrTuple()
     {
-        derefIfNotNull(m_data.pointer());
+        WTF::DefaultRefDerefTraits<T>::derefIfNotNull(m_data.pointer());
     }
 
     T* pointer() const
@@ -49,10 +49,10 @@
 
     void setPointer(T* pointer)
     {
-        refIfNotNull(pointer);
+        WTF::DefaultRefDerefTraits<T>::refIfNotNull(pointer);
         auto* old = m_data.pointer();
         m_data.setPointer(pointer);
-        derefIfNotNull(old);
+        WTF::DefaultRefDerefTraits<T>::derefIfNotNull(old);
     }
 
     Type type() const { return m_data.type(); }

Modified: trunk/Source/WTF/wtf/Forward.h (267590 => 267591)


--- trunk/Source/WTF/wtf/Forward.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WTF/wtf/Forward.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -59,6 +59,7 @@
 #endif
 
 template<typename> struct DumbPtrTraits;
+template<typename> struct DefaultRefDerefTraits;
 
 template<typename> class CompletionHandler;
 template<typename> class Function;
@@ -69,7 +70,7 @@
 template<typename> class Packed;
 template<typename T, size_t = alignof(T)> class PackedAlignedPtr;
 template<typename T, typename = DumbPtrTraits<T>> class Ref;
-template<typename T, typename = DumbPtrTraits<T>> class RefPtr;
+template<typename T, typename = DumbPtrTraits<T>, typename = DefaultRefDerefTraits<T>> class RefPtr;
 template<typename> class StringBuffer;
 template<typename> class StringParsingBuffer;
 template<typename, typename = void> class StringTypeAdapter;

Modified: trunk/Source/WTF/wtf/RefPtr.h (267590 => 267591)


--- trunk/Source/WTF/wtf/RefPtr.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WTF/wtf/RefPtr.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -29,26 +29,29 @@
 
 namespace WTF {
 
-template<typename T, typename PtrTraits> class RefPtr;
-template<typename T, typename PtrTraits = DumbPtrTraits<T>> RefPtr<T, PtrTraits> adoptRef(T*);
+template<typename T> struct DefaultRefDerefTraits {
+    static ALWAYS_INLINE void refIfNotNull(T* ptr)
+    {
+        if (LIKELY(ptr != nullptr))
+            ptr->ref();
+    }
 
-template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
-{
-    if (LIKELY(ptr != nullptr))
-        ptr->ref();
-}
+    static ALWAYS_INLINE void derefIfNotNull(T* ptr)
+    {
+        if (LIKELY(ptr != nullptr))
+            ptr->deref();
+    }
+};
 
-template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
-{
-    if (LIKELY(ptr != nullptr))
-        ptr->deref();
-}
+template<typename T, typename PtrTraits, typename RefDerefTraits> class RefPtr;
+template<typename T, typename PtrTraits = DumbPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> RefPtr<T, PtrTraits, RefDerefTraits> adoptRef(T*);
 
-template<typename T, typename Traits>
+template<typename T, typename _PtrTraits, typename _RefDerefTraits>
 class RefPtr {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    using PtrTraits = Traits;
+    using PtrTraits = _PtrTraits;
+    using RefDerefTraits = _RefDerefTraits;
     typedef T ValueType;
     typedef ValueType* PtrType;
 
@@ -55,12 +58,12 @@
     static constexpr bool isRefPtr = true;
 
     ALWAYS_INLINE constexpr RefPtr() : m_ptr(nullptr) { }
-    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
-    ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(PtrTraits::unwrap(m_ptr)); }
-    template<typename X, typename Y> RefPtr(const RefPtr<X, Y>& o) : m_ptr(o.get()) { refIfNotNull(PtrTraits::unwrap(m_ptr)); }
+    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { RefDerefTraits::refIfNotNull(ptr); }
+    ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { RefDerefTraits::refIfNotNull(PtrTraits::unwrap(m_ptr)); }
+    template<typename X, typename Y, typename Z> RefPtr(const RefPtr<X, Y, Z>& o) : m_ptr(o.get()) { RefDerefTraits::refIfNotNull(PtrTraits::unwrap(m_ptr)); }
 
     ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.leakRef()) { }
-    template<typename X, typename Y> RefPtr(RefPtr<X, Y>&& o) : m_ptr(o.leakRef()) { }
+    template<typename X, typename Y, typename Z> RefPtr(RefPtr<X, Y, Z>&& o) : m_ptr(o.leakRef()) { }
     template<typename X, typename Y> RefPtr(Ref<X, Y>&&);
 
     // Hash table deleted values, which are only constructed and never copied or destroyed.
@@ -67,7 +70,7 @@
     RefPtr(HashTableDeletedValueType) : m_ptr(PtrTraits::hashTableDeletedValue()) { }
     bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
 
-    ALWAYS_INLINE ~RefPtr() { derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
+    ALWAYS_INLINE ~RefPtr() { RefDerefTraits::derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
 
     T* get() const { return PtrTraits::unwrap(m_ptr); }
 
@@ -90,12 +93,12 @@
     RefPtr& operator=(const RefPtr&);
     RefPtr& operator=(T*);
     RefPtr& operator=(std::nullptr_t);
-    template<typename X, typename Y> RefPtr& operator=(const RefPtr<X, Y>&);
+    template<typename X, typename Y, typename Z> RefPtr& operator=(const RefPtr<X, Y, Z>&);
     RefPtr& operator=(RefPtr&&);
-    template<typename X, typename Y> RefPtr& operator=(RefPtr<X, Y>&&);
+    template<typename X, typename Y, typename Z> RefPtr& operator=(RefPtr<X, Y, Z>&&);
     template<typename X> RefPtr& operator=(Ref<X>&&);
 
-    template<typename X, typename Y> void swap(RefPtr<X, Y>&);
+    template<typename X, typename Y, typename Z> void swap(RefPtr<X, Y, Z>&);
 
     RefPtr copyRef() && = delete;
     RefPtr copyRef() const & WARN_UNUSED_RETURN { return RefPtr(m_ptr); }
@@ -103,8 +106,8 @@
 private:
     void unspecifiedBoolTypeInstance() const { }
 
-    friend RefPtr adoptRef<T, PtrTraits>(T*);
-    template<typename X, typename Y> friend class RefPtr;
+    friend RefPtr adoptRef<T, PtrTraits, RefDerefTraits>(T*);
+    template<typename X, typename Y, typename Z> friend class RefPtr;
 
     enum AdoptTag { Adopt };
     RefPtr(T* ptr, AdoptTag) : m_ptr(ptr) { }
@@ -112,21 +115,21 @@
     typename PtrTraits::StorageType m_ptr;
 };
 
-template<typename T, typename U>
+template<typename T, typename U, typename V>
 template<typename X, typename Y>
-inline RefPtr<T, U>::RefPtr(Ref<X, Y>&& reference)
+inline RefPtr<T, U, V>::RefPtr(Ref<X, Y>&& reference)
     : m_ptr(&reference.leakRef())
 {
 }
 
-template<typename T, typename U>
-inline T* RefPtr<T, U>::leakRef()
+template<typename T, typename U, typename V>
+inline T* RefPtr<T, U, V>::leakRef()
 {
     return U::exchange(m_ptr, nullptr);
 }
 
-template<typename T, typename U>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(const RefPtr& o)
+template<typename T, typename U, typename V>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr& o)
 {
     RefPtr ptr = o;
     swap(ptr);
@@ -133,9 +136,9 @@
     return *this;
 }
 
-template<typename T, typename U>
-template<typename X, typename Y>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(const RefPtr<X, Y>& o)
+template<typename T, typename U, typename V>
+template<typename X, typename Y, typename Z>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr<X, Y, Z>& o)
 {
     RefPtr ptr = o;
     swap(ptr);
@@ -142,8 +145,8 @@
     return *this;
 }
 
-template<typename T, typename U>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(T* optr)
+template<typename T, typename U, typename V>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(T* optr)
 {
     RefPtr ptr = optr;
     swap(ptr);
@@ -150,15 +153,15 @@
     return *this;
 }
 
-template<typename T, typename U>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(std::nullptr_t)
+template<typename T, typename U, typename V>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(std::nullptr_t)
 {
-    derefIfNotNull(U::exchange(m_ptr, nullptr));
+    V::derefIfNotNull(U::exchange(m_ptr, nullptr));
     return *this;
 }
 
-template<typename T, typename U>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(RefPtr&& o)
+template<typename T, typename U, typename V>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr&& o)
 {
     RefPtr ptr = WTFMove(o);
     swap(ptr);
@@ -165,9 +168,9 @@
     return *this;
 }
 
-template<typename T, typename U>
-template<typename X, typename Y>
-inline RefPtr<T, U>& RefPtr<T, U>::operator=(RefPtr<X, Y>&& o)
+template<typename T, typename U, typename V>
+template<typename X, typename Y, typename Z>
+inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr<X, Y, Z>&& o)
 {
     RefPtr ptr = WTFMove(o);
     swap(ptr);
@@ -174,9 +177,9 @@
     return *this;
 }
 
-template<typename T, typename V>
+template<typename T, typename V, typename W>
 template<typename U>
-inline RefPtr<T, V>& RefPtr<T, V>::operator=(Ref<U>&& reference)
+inline RefPtr<T, V, W>& RefPtr<T, V, W>::operator=(Ref<U>&& reference)
 {
     RefPtr ptr = WTFMove(reference);
     swap(ptr);
@@ -183,71 +186,71 @@
     return *this;
 }
 
-template<class T, typename U>
-template<typename X, typename Y>
-inline void RefPtr<T, U>::swap(RefPtr<X, Y>& o)
+template<class T, typename U, typename V>
+template<typename X, typename Y, typename Z>
+inline void RefPtr<T, U, V>::swap(RefPtr<X, Y, Z>& o)
 {
     U::swap(m_ptr, o.m_ptr);
 }
 
-template<typename T, typename U, typename X, typename Y, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>>
-inline void swap(RefPtr<T, U>& a, RefPtr<X, Y>& b)
+template<typename T, typename U, typename V, typename X, typename Y, typename Z, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>>
+inline void swap(RefPtr<T, U, V>& a, RefPtr<X, Y, Z>& b)
 {
     a.swap(b);
 }
 
-template<typename T, typename U, typename X, typename Y>
-inline bool operator==(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
+template<typename T, typename U, typename V, typename X, typename Y, typename Z>
+inline bool operator==(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b)
 { 
     return a.get() == b.get();
 }
 
-template<typename T, typename U, typename X>
-inline bool operator==(const RefPtr<T, U>& a, X* b)
+template<typename T, typename U, typename V, typename X>
+inline bool operator==(const RefPtr<T, U, V>& a, X* b)
 { 
     return a.get() == b; 
 }
 
-template<typename T, typename X, typename Y>
-inline bool operator==(T* a, const RefPtr<X, Y>& b)
+template<typename T, typename X, typename Y, typename Z>
+inline bool operator==(T* a, const RefPtr<X, Y, Z>& b)
 {
     return a == b.get(); 
 }
 
-template<typename T, typename U, typename X, typename Y>
-inline bool operator!=(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
+template<typename T, typename U, typename V, typename X, typename Y, typename Z>
+inline bool operator!=(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b)
 { 
     return a.get() != b.get(); 
 }
 
-template<typename T, typename U, typename X>
-inline bool operator!=(const RefPtr<T, U>& a, X* b)
+template<typename T, typename U, typename V, typename X>
+inline bool operator!=(const RefPtr<T, U, V>& a, X* b)
 {
     return a.get() != b; 
 }
 
-template<typename T, typename X, typename Y>
-inline bool operator!=(T* a, const RefPtr<X, Y>& b)
+template<typename T, typename X, typename Y, typename Z>
+inline bool operator!=(T* a, const RefPtr<X, Y, Z>& b)
 { 
     return a != b.get(); 
 }
 
-template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>
-inline RefPtr<T, U> static_pointer_cast(const RefPtr<X, Y>& p)
+template<typename T, typename U = DumbPtrTraits<T>, typename V = DefaultRefDerefTraits<T>, typename X, typename Y, typename Z>
+inline RefPtr<T, U, V> static_pointer_cast(const RefPtr<X, Y, Z>& p)
 { 
-    return RefPtr<T, U>(static_cast<T*>(p.get()));
+    return RefPtr<T, U, V>(static_cast<T*>(p.get()));
 }
 
-template <typename T, typename U>
-struct IsSmartPtr<RefPtr<T, U>> {
+template <typename T, typename U, typename V>
+struct IsSmartPtr<RefPtr<T, U, V>> {
     static constexpr bool value = true;
 };
 
-template<typename T, typename U>
-inline RefPtr<T, U> adoptRef(T* p)
+template<typename T, typename U, typename V>
+inline RefPtr<T, U, V> adoptRef(T* p)
 {
     adopted(p);
-    return RefPtr<T, U>(p, RefPtr<T, U>::Adopt);
+    return RefPtr<T, U, V>(p, RefPtr<T, U, V>::Adopt);
 }
 
 template<typename T> inline RefPtr<T> makeRefPtr(T* pointer)
@@ -260,14 +263,14 @@
     return &reference;
 }
 
-template<typename ExpectedType, typename ArgType, typename PtrTraits>
-inline bool is(RefPtr<ArgType, PtrTraits>& source)
+template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits>
+inline bool is(RefPtr<ArgType, PtrTraits, RefDerefTraits>& source)
 {
     return is<ExpectedType>(source.get());
 }
 
-template<typename ExpectedType, typename ArgType, typename PtrTraits>
-inline bool is(const RefPtr<ArgType, PtrTraits>& source)
+template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits>
+inline bool is(const RefPtr<ArgType, PtrTraits, RefDerefTraits>& source)
 {
     return is<ExpectedType>(source.get());
 }

Modified: trunk/Source/WebCore/ChangeLog (267590 => 267591)


--- trunk/Source/WebCore/ChangeLog	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/ChangeLog	2020-09-25 20:36:50 UTC (rev 267591)
@@ -1,3 +1,72 @@
+2020-09-25  Chris Dumez  <[email protected]>
+
+        Get rid of AudioNode::RefType
+        https://bugs.webkit.org/show_bug.cgi?id=216945
+
+        Reviewed by Darin Adler.
+
+        Previously, the node had ref()/deref() function taking a RefType parameter.
+        The RefType would be used to determine which counter should be incremented
+        or decremented: either m_normalRefCount or m_connectionRefCount.
+
+        In a previous patch, I have already ported code that was calling ref() / deref()
+        explicitly with RefTypeNormal to use RefPtr<> instead. This patch goes further by:
+        1. Dropping the RefType parameter to ref() / deref(). ref() / deref() now increment
+           or decrement m_normalRefCount only. Clients are expected to use RefPtr to handle
+           ref counting.
+        2. Introduce new incrementConnectionCount() / decrementConnectionCount() to increment
+           or decrement m_connectionRefCount. To reduce the chance of leakage, clients should
+           not call these functions directly anymore. Instead, they use use the new
+           AudioConnectionRefPtr<> pointer type to handle the connection ref counting for them.
+           AudioConnectionRefPtr<> is a RefPtr<> which special traits causing incrementConnectionCount()
+           and decrementConnectionCount() to get called on the AudioNode instead of ref() and
+           deref().
+
+        I believe this new design is a bit simpler to reason about and less prone to leaks.
+        There is no longer any code explicitly ref'ing or deref'ing the AudioNodes. Instead,
+        RefPtr<> or AudioConnectionRefPtr<> is used to increment/decrement the right internal
+        count.
+
+        No new tests, no Web-facing behavior change.
+
+        * Modules/webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::setPannerNode):
+        (WebCore::AudioBufferSourceNode::clearPannerNode):
+        * Modules/webaudio/AudioBufferSourceNode.h:
+        * Modules/webaudio/AudioNode.cpp:
+        (WebCore::AudioNode::disableOutputsIfNecessary):
+        (WebCore::AudioNode::incrementConnectionCount):
+        (WebCore::AudioNode::decrementConnectionCount):
+        (WebCore::AudioNode::decrementConnectionCountWithLock):
+        (WebCore::AudioNode::markNodeForDeletionIfNecessary):
+        (WebCore::AudioNode::ref):
+        (WebCore::AudioNode::deref):
+        (WebCore::AudioNode::derefWithLock):
+        * Modules/webaudio/AudioNode.h:
+        (WebCore::AudioNodeConnectionRefDerefTraits::refIfNotNull):
+        (WebCore::AudioNodeConnectionRefDerefTraits::derefIfNotNull):
+        * Modules/webaudio/AudioNodeInput.cpp:
+        (WebCore::AudioNodeInput::connect):
+        (WebCore::AudioNodeInput::disconnect):
+        * Modules/webaudio/AudioNodeOutput.cpp:
+        (WebCore::AudioNodeOutput::propagateChannelCount):
+        (WebCore::AudioNodeOutput::addInput):
+        (WebCore::AudioNodeOutput::disconnectAllInputs):
+        (WebCore::AudioNodeOutput::disable):
+        (WebCore::AudioNodeOutput::enable):
+        * Modules/webaudio/AudioNodeOutput.h:
+        * Modules/webaudio/BaseAudioContext.cpp:
+        (WebCore::BaseAudioContext::~BaseAudioContext):
+        (WebCore::BaseAudioContext::refNode):
+        (WebCore::BaseAudioContext::derefNode):
+        (WebCore::BaseAudioContext::derefUnfinishedSourceNodes):
+        (WebCore::BaseAudioContext::addDeferredDecrementConnectionCount):
+        (WebCore::BaseAudioContext::handlePostRenderTasks):
+        (WebCore::BaseAudioContext::handleDeferredDecrementConnectionCounts):
+        * Modules/webaudio/BaseAudioContext.h:
+        * Modules/webaudio/ScriptProcessorNode.cpp:
+        (WebCore::ScriptProcessorNode::process):
+
 2020-09-25  Rob Buis  <[email protected]>
 
         Simplify SVGTests.hasExtension idl

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -580,22 +580,13 @@
 
 void AudioBufferSourceNode::setPannerNode(PannerNodeBase* pannerNode)
 {
-    if (m_pannerNode != pannerNode && !hasFinished()) {
-        if (pannerNode)
-            pannerNode->ref(AudioNode::RefTypeConnection);
-        if (m_pannerNode)
-            m_pannerNode->deref(AudioNode::RefTypeConnection);
-
+    if (m_pannerNode != pannerNode && !hasFinished())
         m_pannerNode = pannerNode;
-    }
 }
 
 void AudioBufferSourceNode::clearPannerNode()
 {
-    if (m_pannerNode) {
-        m_pannerNode->deref(AudioNode::RefTypeConnection);
-        m_pannerNode = nullptr;
-    }
+    m_pannerNode = nullptr;
 }
 
 void AudioBufferSourceNode::finish()

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -141,8 +141,8 @@
     double totalPitchRate();
 
     // We optionally keep track of a panner node which has a doppler shift that is incorporated into
-    // the pitch rate. We manually manage ref-counting because we want to use RefTypeConnection.
-    PannerNodeBase* m_pannerNode { nullptr };
+    // the pitch rate.
+    AudioConnectionRefPtr<PannerNodeBase> m_pannerNode;
 
     // This synchronizes process() with setBuffer() which can cause dynamic channel count changes.
     mutable Lock m_processMutex;

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -548,7 +548,7 @@
 void AudioNode::disableOutputsIfNecessary()
 {
     // Disable outputs if appropriate. We do this if the number of connections is 0 or 1. The case
-    // of 0 is from finishDeref() where there are no connections left. The case of 1 is from
+    // of 0 is from decrementConnectionCountWithLock() where there are no connections left. The case of 1 is from
     // AudioNodeInput::disable() where we want to disable outputs when there's only one connection
     // left because we're ready to go away, but can't quite yet.
     if (m_connectionRefCount <= 1 && !m_isDisabled) {
@@ -574,31 +574,21 @@
         output->disable();
 }
 
-void AudioNode::ref(RefType refType)
+void AudioNode::incrementConnectionCount()
 {
-    switch (refType) {
-    case RefTypeNormal:
-        ++m_normalRefCount;
-        break;
-    case RefTypeConnection:
-        ++m_connectionRefCount;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
+    ++m_connectionRefCount;
 
+    // See the disabling code in decrementConnectionCountWithLock() below. This handles the case where a node
+    // is being re-connected after being used at least once and disconnected.
+    // In this case, we need to re-enable.
+    enableOutputsIfNecessary();
+
 #if DEBUG_AUDIONODE_REFERENCES
-    fprintf(stderr, "%p: %d: AudioNode::ref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount);
+    fprintf(stderr, "%p: %d: AudioNode::incrementConnectionCount() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount);
 #endif
-
-    // See the disabling code in finishDeref() below. This handles the case where a node
-    // is being re-connected after being used at least once and disconnected.
-    // In this case, we need to re-enable.
-    if (refType == RefTypeConnection)
-        enableOutputsIfNecessary();
 }
 
-void AudioNode::deref(RefType refType)
+void AudioNode::decrementConnectionCount()
 {
     // The actually work for deref happens completely within the audio context's graph lock.
     // In the case of the audio thread, we must use a tryLock to avoid glitches.
@@ -615,7 +605,7 @@
 
     if (hasLock) {
         // This is where the real deref work happens.
-        finishDeref(refType);
+        decrementConnectionCountWithLock();
 
         if (mustReleaseLock)
             context().unlock();
@@ -622,8 +612,7 @@
     } else {
         // We were unable to get the lock, so put this in a list to finish up later.
         ASSERT(context().isAudioThread());
-        ASSERT(refType == RefTypeConnection);
-        context().addDeferredFinishDeref(this);
+        context().addDeferredDecrementConnectionCount(this);
     }
 
     // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here.
@@ -633,6 +622,66 @@
         context().deleteMarkedNodes();
 }
 
+void AudioNode::decrementConnectionCountWithLock()
+{
+    ASSERT(context().isGraphOwner());
+
+    ASSERT(m_connectionRefCount > 0);
+    --m_connectionRefCount;
+
+#if DEBUG_AUDIONODE_REFERENCES
+    fprintf(stderr, "%p: %d: AudioNode::decrementConnectionCountWithLock() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount);
+#endif
+
+    if (!m_connectionRefCount && m_normalRefCount)
+        disableOutputsIfNecessary();
+
+    markNodeForDeletionIfNecessary();
+}
+
+void AudioNode::markNodeForDeletionIfNecessary()
+{
+    ASSERT(context().isGraphOwner());
+
+    if (m_connectionRefCount || m_normalRefCount || m_isMarkedForDeletion)
+        return;
+
+    // All references are gone - we need to go away.
+    for (auto& output : m_outputs)
+        output->disconnectAll(); // This will deref() nodes we're connected to.
+
+    // Mark for deletion at end of each render quantum or when context shuts down.
+    context().markForDeletion(*this);
+    m_isMarkedForDeletion = true;
+    didBecomeMarkedForDeletion();
+}
+
+void AudioNode::ref()
+{
+    ++m_normalRefCount;
+
+#if DEBUG_AUDIONODE_REFERENCES
+    fprintf(stderr, "%p: %d: AudioNode::ref() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount);
+#endif
+}
+
+void AudioNode::deref()
+{
+    ASSERT(!context().isAudioThread());
+
+    {
+        BaseAudioContext::AutoLocker locker(context());
+        // This is where the real deref work happens.
+        derefWithLock();
+    }
+
+    // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here.
+    // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive
+    // because AudioNodes keep a reference to the context.
+    if (context().isAudioThreadFinished())
+        context().deleteMarkedNodes();
+}
+
 Variant<RefPtr<BaseAudioContext>, RefPtr<WebKitAudioContext>> AudioNode::contextForBindings() const
 {
     if (m_context->isWebKitAudioContext())
@@ -640,42 +689,18 @@
     return makeRefPtr(m_context.get());
 }
 
-void AudioNode::finishDeref(RefType refType)
+void AudioNode::derefWithLock()
 {
     ASSERT(context().isGraphOwner());
     
-    switch (refType) {
-    case RefTypeNormal:
-        ASSERT(m_normalRefCount > 0);
-        --m_normalRefCount;
-        break;
-    case RefTypeConnection:
-        ASSERT(m_connectionRefCount > 0);
-        --m_connectionRefCount;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
+    ASSERT(m_normalRefCount > 0);
+    --m_normalRefCount;
     
 #if DEBUG_AUDIONODE_REFERENCES
-    fprintf(stderr, "%p: %d: AudioNode::deref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount);
+    fprintf(stderr, "%p: %d: AudioNode::deref() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount);
 #endif
 
-    if (!m_connectionRefCount) {
-        if (!m_normalRefCount) {
-            if (!m_isMarkedForDeletion) {
-                // All references are gone - we need to go away.
-                for (auto& output : m_outputs)
-                    output->disconnectAll(); // This will deref() nodes we're connected to.
-
-                // Mark for deletion at end of each render quantum or when context shuts down.
-                context().markForDeletion(*this);
-                m_isMarkedForDeletion = true;
-                didBecomeMarkedForDeletion();
-            }
-        } else if (refType == RefTypeConnection)
-            disableOutputsIfNecessary();
-    }
+    markNodeForDeletionIfNecessary();
 }
 
 ExceptionOr<void> AudioNode::handleAudioNodeOptions(const AudioNodeOptions& options, const DefaultAudioNodeOptions& defaults)

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.h (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioNode.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -96,17 +96,14 @@
     NodeType nodeType() const { return m_nodeType; }
     void setNodeType(NodeType);
 
-    // We handle our own ref-counting because of the threading issues and subtle nature of
-    // how AudioNodes can continue processing (playing one-shot sound) after there are no more
-    // _javascript_ references to the object.
-    enum RefType { RefTypeNormal, RefTypeConnection };
-
     // Can be called from main thread or context's audio thread.
-    void ref(RefType refType = RefTypeNormal);
-    void deref(RefType refType = RefTypeNormal);
+    void ref();
+    void deref();
+    void incrementConnectionCount();
+    void decrementConnectionCount();
 
     // Can be called from main thread or context's audio thread.  It must be called while the context's graph lock is held.
-    void finishDeref(RefType refType);
+    void decrementConnectionCountWithLock();
     virtual void didBecomeMarkedForDeletion() { }
 
     // The AudioNodeInput(s) (if any) will already have their input data available when process() is called.
@@ -202,6 +199,9 @@
     void addInput();
     void addOutput(unsigned numberOfChannels);
 
+    void markNodeForDeletionIfNecessary();
+    void derefWithLock();
+
     struct DefaultAudioNodeOptions {
         unsigned channelCount;
         ChannelCountMode channelCountMode;
@@ -270,6 +270,23 @@
     ChannelInterpretation m_channelInterpretation { ChannelInterpretation::Speakers };
 };
 
+template<typename T> struct AudioNodeConnectionRefDerefTraits {
+    static ALWAYS_INLINE void refIfNotNull(T* ptr)
+    {
+        if (LIKELY(ptr != nullptr))
+            ptr->incrementConnectionCount();
+    }
+
+    static ALWAYS_INLINE void derefIfNotNull(T* ptr)
+    {
+        if (LIKELY(ptr != nullptr))
+            ptr->decrementConnectionCount();
+    }
+};
+
+template<typename T>
+using AudioConnectionRefPtr = RefPtr<T, DumbPtrTraits<T>, AudioNodeConnectionRefDerefTraits<T>>;
+
 String convertEnumerationToString(AudioNode::NodeType);
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -60,9 +60,6 @@
 
     output->addInput(this);
     changedOutputs();
-
-    // Sombody has just connected to us, so count it as a reference.
-    node()->ref(AudioNode::RefTypeConnection);
 }
 
 void AudioNodeInput::disconnect(AudioNodeOutput* output)
@@ -76,15 +73,13 @@
     // First try to disconnect from "active" connections.
     if (m_outputs.remove(output)) {
         changedOutputs();
-        output->removeInput(this);
-        node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+        output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted.
         return;
     }
     
     // Otherwise, try to disconnect from disabled connections.
     if (m_disabledOutputs.remove(output)) {
-        output->removeInput(this);
-        node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+        output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted.
         return;
     }
 

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -95,7 +95,7 @@
     
     if (isChannelCountKnown()) {
         // Announce to any nodes we're connected to that we changed our channel count for its input.
-        for (auto& input : m_inputs) {
+        for (auto& input : m_inputs.keys()) {
             AudioNode* connectionNode = input->node();
             connectionNode->checkNumberOfChannelsForInput(input);
         }
@@ -157,7 +157,7 @@
     if (!input)
         return;
 
-    m_inputs.add(input);
+    m_inputs.add(input, input->node());
 }
 
 void AudioNodeOutput::removeInput(AudioNodeInput* input)
@@ -177,7 +177,7 @@
     
     // AudioNodeInput::disconnect() changes m_inputs by calling removeInput().
     while (!m_inputs.isEmpty()) {
-        AudioNodeInput* input = *m_inputs.begin();
+        AudioNodeInput* input = m_inputs.begin()->key;
         input->disconnect(this);
     }
 }
@@ -226,7 +226,7 @@
     ASSERT(context().isGraphOwner());
 
     if (m_isEnabled) {
-        for (auto& input : m_inputs)
+        for (auto& input : m_inputs.keys())
             input->disable(this);
         m_isEnabled = false;
     }
@@ -237,7 +237,7 @@
     ASSERT(context().isGraphOwner());
 
     if (!m_isEnabled) {
-        for (auto& input : m_inputs)
+        for (auto& input : m_inputs.keys())
             input->enable(this);
         m_isEnabled = true;
     }

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -140,8 +140,9 @@
     // If m_isInPlace is true, use m_inPlaceBus as the valid AudioBus; If false, use the default m_internalBus.
     bool m_isInPlace { false };
 
-    HashSet<AudioNodeInput*> m_inputs;
-    typedef HashSet<AudioNodeInput*>::iterator InputsIterator;
+    using InputsMap = HashMap<AudioNodeInput*, AudioConnectionRefPtr<AudioNode>>;
+    InputsMap m_inputs;
+    typedef InputsMap::iterator InputsIterator;
     bool m_isEnabled { true };
 
     // For the purposes of rendering, keeps track of the number of inputs and AudioParams we're connected to.

Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -197,7 +197,7 @@
     if (m_automaticPullNodesNeedUpdating)
         m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
     ASSERT(m_renderingAutomaticPullNodes.isEmpty());
-    // FIXME: Can we assert that m_deferredFinishDerefList is empty?
+    // FIXME: Can we assert that m_deferredBreakConnectionList is empty?
 
     if (!isOfflineContext() && scriptExecutionContext()) {
         document()->removeAudioProducer(*this);
@@ -681,7 +681,6 @@
     ASSERT(isMainThread());
     AutoLocker locker(*this);
     
-    node.ref(AudioNode::RefTypeConnection);
     m_referencedNodes.append(&node);
 }
 
@@ -689,8 +688,6 @@
 {
     ASSERT(isGraphOwner());
     
-    node.deref(AudioNode::RefTypeConnection);
-
     ASSERT(m_referencedNodes.contains(&node));
     m_referencedNodes.removeFirst(&node);
 }
@@ -698,9 +695,6 @@
 void BaseAudioContext::derefUnfinishedSourceNodes()
 {
     ASSERT(isMainThread() && isAudioThreadFinished());
-    for (auto& node : m_referencedNodes)
-        node->deref(AudioNode::RefTypeConnection);
-
     m_referencedNodes.clear();
 }
 
@@ -778,10 +772,10 @@
     return m_graphOwnerThread == &Thread::current();
 }
 
-void BaseAudioContext::addDeferredFinishDeref(AudioNode* node)
+void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node)
 {
     ASSERT(isAudioThread());
-    m_deferredFinishDerefList.append(node);
+    m_deferredBreakConnectionList.append(node);
 }
 
 void BaseAudioContext::handlePreRenderTasks(const AudioIOPosition& outputPosition)
@@ -821,7 +815,7 @@
     bool mustReleaseLock;
     if (tryLock(mustReleaseLock)) {
         // Take care of finishing any derefs where the tryLock() failed previously.
-        handleDeferredFinishDerefs();
+        handleDeferredDecrementConnectionCounts();
 
         // Dynamically clean up nodes which are no longer needed.
         derefFinishedSourceNodes();
@@ -841,13 +835,13 @@
     }
 }
 
-void BaseAudioContext::handleDeferredFinishDerefs()
+void BaseAudioContext::handleDeferredDecrementConnectionCounts()
 {
     ASSERT(isAudioThread() && isGraphOwner());
-    for (auto& node : m_deferredFinishDerefList)
-        node->finishDeref(AudioNode::RefTypeConnection);
+    for (auto& node : m_deferredBreakConnectionList)
+        node->decrementConnectionCountWithLock();
     
-    m_deferredFinishDerefList.clear();
+    m_deferredBreakConnectionList.clear();
 }
 
 void BaseAudioContext::markForDeletion(AudioNode& node)

Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -229,11 +229,11 @@
     // Returns the maximum number of channels we can support.
     static unsigned maxNumberOfChannels() { return MaxNumberOfChannels; }
     
-    // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
-    void addDeferredFinishDeref(AudioNode*);
+    // In AudioNode::decrementConnectionCount() a tryLock() is used for calling decrementConnectionCountWithLock(), but if it fails keep track here.
+    void addDeferredDecrementConnectionCount(AudioNode*);
 
-    // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
-    void handleDeferredFinishDerefs();
+    // In the audio thread at the start of each render cycle, we'll call handleDeferredDecrementConnectionCounts().
+    void handleDeferredDecrementConnectionCounts();
 
     // Only accessed when the graph lock is held.
     void markSummingJunctionDirty(AudioSummingJunction*);
@@ -397,10 +397,8 @@
     // Only accessed in the audio thread.
     Vector<AudioNode*> m_finishedNodes;
 
-    // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
-    // with an optional argument for refType.  We need to use the special refType: RefTypeConnection
     // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
-    Vector<AudioNode*> m_referencedNodes;
+    Vector<AudioConnectionRefPtr<AudioNode>> m_referencedNodes;
 
     // Accumulate nodes which need to be deleted here.
     // This is copied to m_nodesToDelete at the end of a render cycle in handlePostRenderTasks(), where we're assured of a stable graph
@@ -427,7 +425,7 @@
     HashSet<AudioNode*> m_automaticPullNodes;
     Vector<AudioNode*> m_renderingAutomaticPullNodes;
     // Only accessed in the audio thread.
-    Vector<AudioNode*> m_deferredFinishDerefList;
+    Vector<AudioNode*> m_deferredBreakConnectionList;
     Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions;
 
     std::unique_ptr<PlatformMediaSession> m_mediaSession;

Modified: trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp (267590 => 267591)


--- trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -183,12 +183,10 @@
     // When this happens, fire an event and swap buffers.
     if (!m_bufferReadWriteIndex) {
         // Reference ourself so we don't accidentally get deleted before fireProcessEvent() gets called.
-        auto protector = makeRef(*this);
-
         // We only wait for script code execution when the context is an offline one for performance reasons.
         if (context().isOfflineContext()) {
             BinarySemaphore semaphore;
-            callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex] {
+            callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] {
                 fireProcessEvent(doubleBufferIndex);
                 semaphore.signal();
             });
@@ -202,7 +200,7 @@
                 return;
             }
 
-            callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = WTFMove(protector)] {
+            callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] {
                 auto locker = holdLock(m_processLock);
                 fireProcessEvent(doubleBufferIndex);
             });

Modified: trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp (267590 => 267591)


--- trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -25,73 +25,73 @@
 
 namespace WTF {
 
-template<> void refIfNotNull(cairo_t* ptr)
+void DefaultRefDerefTraits<cairo_t>::refIfNotNull(cairo_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_t* ptr)
+void DefaultRefDerefTraits<cairo_t>::derefIfNotNull(cairo_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_destroy(ptr);
 }
 
-template<> void refIfNotNull(cairo_surface_t* ptr)
+void DefaultRefDerefTraits<cairo_surface_t>::refIfNotNull(cairo_surface_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_surface_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_surface_t* ptr)
+void DefaultRefDerefTraits<cairo_surface_t>::derefIfNotNull(cairo_surface_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_surface_destroy(ptr);
 }
 
-template<> void refIfNotNull(cairo_font_face_t* ptr)
+void DefaultRefDerefTraits<cairo_font_face_t>::refIfNotNull(cairo_font_face_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_font_face_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_font_face_t* ptr)
+void DefaultRefDerefTraits<cairo_font_face_t>::derefIfNotNull(cairo_font_face_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_font_face_destroy(ptr);
 }
 
-template<> void refIfNotNull(cairo_scaled_font_t* ptr)
+void DefaultRefDerefTraits<cairo_scaled_font_t>::refIfNotNull(cairo_scaled_font_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_scaled_font_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_scaled_font_t* ptr)
+void DefaultRefDerefTraits<cairo_scaled_font_t>::derefIfNotNull(cairo_scaled_font_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_scaled_font_destroy(ptr);
 }
 
-template<> void refIfNotNull(cairo_pattern_t* ptr)
+void DefaultRefDerefTraits<cairo_pattern_t>::refIfNotNull(cairo_pattern_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_pattern_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_pattern_t* ptr)
+void DefaultRefDerefTraits<cairo_pattern_t>::derefIfNotNull(cairo_pattern_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_pattern_destroy(ptr);
 }
 
-template<> void refIfNotNull(cairo_region_t* ptr)
+void DefaultRefDerefTraits<cairo_region_t>::refIfNotNull(cairo_region_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_region_reference(ptr);
 }
 
-template<> void derefIfNotNull(cairo_region_t* ptr)
+void DefaultRefDerefTraits<cairo_region_t>::derefIfNotNull(cairo_region_t* ptr)
 {
     if (LIKELY(ptr))
         cairo_region_destroy(ptr);

Modified: trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h (267590 => 267591)


--- trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -33,23 +33,41 @@
 
 namespace WTF {
 
-template<> void refIfNotNull(cairo_t* ptr);
-template<> WEBCORE_EXPORT void derefIfNotNull(cairo_t* ptr);
+template<>
+struct DefaultRefDerefTraits<cairo_t> {
+    static void refIfNotNull(cairo_t* ptr);
+    WEBCORE_EXPORT static void derefIfNotNull(cairo_t* ptr);
+};
 
-template<> WEBCORE_EXPORT void refIfNotNull(cairo_surface_t* ptr);
-template<> WEBCORE_EXPORT void derefIfNotNull(cairo_surface_t* ptr);
+template<>
+struct DefaultRefDerefTraits<cairo_surface_t> {
+    WEBCORE_EXPORT static void refIfNotNull(cairo_surface_t* ptr);
+    WEBCORE_EXPORT static void derefIfNotNull(cairo_surface_t* ptr);
+};
 
-template<> void refIfNotNull(cairo_font_face_t* ptr);
-template<> void derefIfNotNull(cairo_font_face_t* ptr);
+template<>
+struct DefaultRefDerefTraits<cairo_font_face_t> {
+    static void refIfNotNull(cairo_font_face_t* ptr);
+    static void derefIfNotNull(cairo_font_face_t* ptr);
+};
 
-template<> void refIfNotNull(cairo_scaled_font_t* ptr);
-template<> void derefIfNotNull(cairo_scaled_font_t* ptr);
+template<>
+struct DefaultRefDerefTraits<cairo_scaled_font_t> {
+    static void refIfNotNull(cairo_scaled_font_t* ptr);
+    static void derefIfNotNull(cairo_scaled_font_t* ptr);
+};
 
-template<> void refIfNotNull(cairo_pattern_t*);
-template<> void derefIfNotNull(cairo_pattern_t*);
+template<>
+struct DefaultRefDerefTraits<cairo_pattern_t> {
+    static void refIfNotNull(cairo_pattern_t*);
+    static void derefIfNotNull(cairo_pattern_t*);
+};
 
-template<> void refIfNotNull(cairo_region_t*);
-template<> void derefIfNotNull(cairo_region_t*);
+template<>
+struct DefaultRefDerefTraits<cairo_region_t> {
+    static void refIfNotNull(cairo_region_t*);
+    static void derefIfNotNull(cairo_region_t*);
+};
 
 } // namespace WTF
 

Modified: trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp (267590 => 267591)


--- trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp	2020-09-25 20:36:50 UTC (rev 267591)
@@ -25,25 +25,25 @@
 
 namespace WTF {
 
-template<> void refIfNotNull(FcPattern* ptr)
+void DefaultRefDerefTraits<FcPattern>::refIfNotNull(FcPattern* ptr)
 {
     if (LIKELY(ptr))
         FcPatternReference(ptr);
 }
 
-template<> void derefIfNotNull(FcPattern* ptr)
+void DefaultRefDerefTraits<FcPattern>::derefIfNotNull(FcPattern* ptr)
 {
     if (LIKELY(ptr))
         FcPatternDestroy(ptr);
 }
 
-template<> void refIfNotNull(FcConfig* ptr)
+void DefaultRefDerefTraits<FcConfig>::refIfNotNull(FcConfig* ptr)
 {
     if (LIKELY(ptr))
         FcConfigReference(ptr);
 }
 
-template<> void derefIfNotNull(FcConfig* ptr)
+void DefaultRefDerefTraits<FcConfig>::derefIfNotNull(FcConfig* ptr)
 {
     if (LIKELY(ptr))
         FcConfigDestroy(ptr);

Modified: trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.h (267590 => 267591)


--- trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.h	2020-09-25 20:19:39 UTC (rev 267590)
+++ trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.h	2020-09-25 20:36:50 UTC (rev 267591)
@@ -28,11 +28,17 @@
 
 namespace WTF {
 
-template<> void refIfNotNull(FcPattern* ptr);
-template<> void derefIfNotNull(FcPattern* ptr);
+template<>
+struct DefaultRefDerefTraits<FcPattern> {
+    static void refIfNotNull(FcPattern* ptr);
+    static void derefIfNotNull(FcPattern* ptr);
+};
 
-template<> void refIfNotNull(FcConfig* ptr);
-template<> void derefIfNotNull(FcConfig* ptr);
+template<>
+struct DefaultRefDerefTraits<FcConfig> {
+    static void refIfNotNull(FcConfig* ptr);
+    static void derefIfNotNull(FcConfig* ptr);
+};
 
 } // namespace WTF
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to