Title: [103079] trunk/Source/WebCore
Revision
103079
Author
ad...@chromium.org
Date
2011-12-16 10:27:13 -0800 (Fri, 16 Dec 2011)

Log Message

Improve performance of ChildListMutationScope when no MutationObservers are present
https://bugs.webkit.org/show_bug.cgi?id=74671

Reviewed by Ojan Vafai.

Inline ChildListMutationScope's methods (including constructor and
destructor), and provide a fast-fail case when no mutation observers
are present.

The code reorganization necessary for the above also removed the
anonymous namespace in ChildListMutationScope.cpp, making both helper
classes private inner classes of ChildListMutationScope.

No new tests, refactoring only.

* dom/ChildListMutationScope.cpp:
(WebCore::ChildListMutationScope::MutationAccumulator::MutationAccumulator):
(WebCore::ChildListMutationScope::MutationAccumulator::~MutationAccumulator):
(WebCore::ChildListMutationScope::MutationAccumulator::isAddedNodeInOrder):
(WebCore::ChildListMutationScope::MutationAccumulator::childAdded):
(WebCore::ChildListMutationScope::MutationAccumulator::isRemovedNodeInOrder):
(WebCore::ChildListMutationScope::MutationAccumulator::willRemoveChild):
(WebCore::ChildListMutationScope::MutationAccumulator::enqueueMutationRecord):
(WebCore::ChildListMutationScope::MutationAccumulator::clear):
(WebCore::ChildListMutationScope::MutationAccumulator::isEmpty):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::MutationAccumulationRouter):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::~MutationAccumulationRouter):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::initialize):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::instance):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::childAdded):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::willRemoveChild):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::incrementScopingLevel):
(WebCore::ChildListMutationScope::MutationAccumulationRouter::decrementScopingLevel):
* dom/ChildListMutationScope.h:
(WebCore::ChildListMutationScope::ChildListMutationScope):
(WebCore::ChildListMutationScope::~ChildListMutationScope):
(WebCore::ChildListMutationScope::childAdded):
(WebCore::ChildListMutationScope::willRemoveChild):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (103078 => 103079)


--- trunk/Source/WebCore/ChangeLog	2011-12-16 18:07:29 UTC (rev 103078)
+++ trunk/Source/WebCore/ChangeLog	2011-12-16 18:27:13 UTC (rev 103079)
@@ -1,3 +1,44 @@
+2011-12-16  Adam Klein  <ad...@chromium.org>
+
+        Improve performance of ChildListMutationScope when no MutationObservers are present
+        https://bugs.webkit.org/show_bug.cgi?id=74671
+
+        Reviewed by Ojan Vafai.
+
+        Inline ChildListMutationScope's methods (including constructor and
+        destructor), and provide a fast-fail case when no mutation observers
+        are present.
+
+        The code reorganization necessary for the above also removed the
+        anonymous namespace in ChildListMutationScope.cpp, making both helper
+        classes private inner classes of ChildListMutationScope.
+
+        No new tests, refactoring only.
+
+        * dom/ChildListMutationScope.cpp:
+        (WebCore::ChildListMutationScope::MutationAccumulator::MutationAccumulator):
+        (WebCore::ChildListMutationScope::MutationAccumulator::~MutationAccumulator):
+        (WebCore::ChildListMutationScope::MutationAccumulator::isAddedNodeInOrder):
+        (WebCore::ChildListMutationScope::MutationAccumulator::childAdded):
+        (WebCore::ChildListMutationScope::MutationAccumulator::isRemovedNodeInOrder):
+        (WebCore::ChildListMutationScope::MutationAccumulator::willRemoveChild):
+        (WebCore::ChildListMutationScope::MutationAccumulator::enqueueMutationRecord):
+        (WebCore::ChildListMutationScope::MutationAccumulator::clear):
+        (WebCore::ChildListMutationScope::MutationAccumulator::isEmpty):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::MutationAccumulationRouter):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::~MutationAccumulationRouter):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::initialize):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::instance):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::childAdded):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::willRemoveChild):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::incrementScopingLevel):
+        (WebCore::ChildListMutationScope::MutationAccumulationRouter::decrementScopingLevel):
+        * dom/ChildListMutationScope.h:
+        (WebCore::ChildListMutationScope::ChildListMutationScope):
+        (WebCore::ChildListMutationScope::~ChildListMutationScope):
+        (WebCore::ChildListMutationScope::childAdded):
+        (WebCore::ChildListMutationScope::willRemoveChild):
+
 2011-12-16  Dean Jackson  <d...@apple.com>
 
         Filters need to affect visual overflow

Modified: trunk/Source/WebCore/dom/ChildListMutationScope.cpp (103078 => 103079)


--- trunk/Source/WebCore/dom/ChildListMutationScope.cpp	2011-12-16 18:07:29 UTC (rev 103078)
+++ trunk/Source/WebCore/dom/ChildListMutationScope.cpp	2011-12-16 18:27:13 UTC (rev 103079)
@@ -45,17 +45,15 @@
 
 namespace WebCore {
 
-namespace {
-
-// ChildListMutationAccumulator expects that all removals from a parent take place in order
+// MutationAccumulator expects that all removals from a parent take place in order
 // and precede any additions. If this is violated (i.e. because of code changes elsewhere
 // in WebCore) it will likely result in both (a) ASSERTions failing, and (b) mutation records
 // being enqueued for delivery before the outer-most scope closes.
-class ChildListMutationAccumulator {
-    WTF_MAKE_NONCOPYABLE(ChildListMutationAccumulator);
+class ChildListMutationScope::MutationAccumulator {
+    WTF_MAKE_NONCOPYABLE(MutationAccumulator);
 public:
-    ChildListMutationAccumulator(PassRefPtr<Node>, PassOwnPtr<MutationObserverInterestGroup> observers);
-    ~ChildListMutationAccumulator();
+    MutationAccumulator(PassRefPtr<Node>, PassOwnPtr<MutationObserverInterestGroup> observers);
+    ~MutationAccumulator();
 
     void childAdded(PassRefPtr<Node>);
     void willRemoveChild(PassRefPtr<Node>);
@@ -77,48 +75,24 @@
     OwnPtr<MutationObserverInterestGroup> m_observers;
 };
 
-class MutationAccumulationRouter {
-    WTF_MAKE_NONCOPYABLE(MutationAccumulationRouter);
-public:
-    ~MutationAccumulationRouter();
-
-    static MutationAccumulationRouter* instance();
-
-    void incrementScopingLevel(Node*);
-    void decrementScopingLevel(Node*);
-
-    void childAdded(Node* target, Node* child);
-    void willRemoveChild(Node* target, Node* child);
-
-private:
-    MutationAccumulationRouter();
-    static void initialize();
-
-    typedef HashMap<Node*, unsigned> ScopingLevelMap;
-    ScopingLevelMap m_scopingLevels;
-    HashMap<Node*, OwnPtr<ChildListMutationAccumulator> > m_accumulations;
-
-    static MutationAccumulationRouter* s_instance;
-};
-
-ChildListMutationAccumulator::ChildListMutationAccumulator(PassRefPtr<Node> target, PassOwnPtr<MutationObserverInterestGroup> observers)
+ChildListMutationScope::MutationAccumulator::MutationAccumulator(PassRefPtr<Node> target, PassOwnPtr<MutationObserverInterestGroup> observers)
     : m_target(target)
     , m_observers(observers)
 {
     clear();
 }
 
-ChildListMutationAccumulator::~ChildListMutationAccumulator()
+ChildListMutationScope::MutationAccumulator::~MutationAccumulator()
 {
     ASSERT(isEmpty());
 }
 
-inline bool ChildListMutationAccumulator::isAddedNodeInOrder(Node* child)
+inline bool ChildListMutationScope::MutationAccumulator::isAddedNodeInOrder(Node* child)
 {
     return isEmpty() || (m_lastAdded == child->previousSibling() && m_nextSibling == child->nextSibling());
 }
 
-void ChildListMutationAccumulator::childAdded(PassRefPtr<Node> prpChild)
+void ChildListMutationScope::MutationAccumulator::childAdded(PassRefPtr<Node> prpChild)
 {
     RefPtr<Node> child = prpChild;
 
@@ -135,12 +109,12 @@
     m_lastAdded = child;
 }
 
-inline bool ChildListMutationAccumulator::isRemovedNodeInOrder(Node* child)
+inline bool ChildListMutationScope::MutationAccumulator::isRemovedNodeInOrder(Node* child)
 {
     return isEmpty() || m_nextSibling.get() == child;
 }
 
-void ChildListMutationAccumulator::willRemoveChild(PassRefPtr<Node> prpChild)
+void ChildListMutationScope::MutationAccumulator::willRemoveChild(PassRefPtr<Node> prpChild)
 {
     RefPtr<Node> child = prpChild;
 
@@ -159,7 +133,7 @@
     m_removedNodes.append(child);
 }
 
-void ChildListMutationAccumulator::enqueueMutationRecord()
+void ChildListMutationScope::MutationAccumulator::enqueueMutationRecord()
 {
     ASSERT(!isEmpty());
     if (isEmpty()) {
@@ -172,7 +146,7 @@
     clear();
 }
 
-void ChildListMutationAccumulator::clear()
+void ChildListMutationScope::MutationAccumulator::clear()
 {
     if (!m_removedNodes.isEmpty())
         m_removedNodes.clear();
@@ -183,31 +157,31 @@
     m_lastAdded = 0;
 }
 
-bool ChildListMutationAccumulator::isEmpty()
+bool ChildListMutationScope::MutationAccumulator::isEmpty()
 {
     return m_removedNodes.isEmpty() && m_addedNodes.isEmpty();
 }
 
-MutationAccumulationRouter* MutationAccumulationRouter::s_instance = 0;
+ChildListMutationScope::MutationAccumulationRouter* ChildListMutationScope::MutationAccumulationRouter::s_instance = 0;
 
-MutationAccumulationRouter::MutationAccumulationRouter()
+ChildListMutationScope::MutationAccumulationRouter::MutationAccumulationRouter()
 {
 }
 
-MutationAccumulationRouter::~MutationAccumulationRouter()
+ChildListMutationScope::MutationAccumulationRouter::~MutationAccumulationRouter()
 {
     ASSERT(m_scopingLevels.isEmpty());
     ASSERT(m_accumulations.isEmpty());
 }
 
-void MutationAccumulationRouter::initialize()
+void ChildListMutationScope::MutationAccumulationRouter::initialize()
 {
     ASSERT(!s_instance);
-    s_instance = adoptPtr(new MutationAccumulationRouter).leakPtr();
+    s_instance = adoptPtr(new ChildListMutationScope::MutationAccumulationRouter).leakPtr();
 }
 
 
-MutationAccumulationRouter* MutationAccumulationRouter::instance()
+ChildListMutationScope::MutationAccumulationRouter* ChildListMutationScope::MutationAccumulationRouter::instance()
 {
     if (!s_instance)
         initialize();
@@ -215,9 +189,9 @@
     return s_instance;
 }
 
-void MutationAccumulationRouter::childAdded(Node* target, Node* child)
+void ChildListMutationScope::MutationAccumulationRouter::childAdded(Node* target, Node* child)
 {
-    HashMap<Node*, OwnPtr<ChildListMutationAccumulator> >::iterator iter = m_accumulations.find(target);
+    HashMap<Node*, OwnPtr<ChildListMutationScope::MutationAccumulator> >::iterator iter = m_accumulations.find(target);
     ASSERT(iter != m_accumulations.end());
     if (iter == m_accumulations.end() || !iter->second)
         return;
@@ -225,9 +199,9 @@
     iter->second->childAdded(child);
 }
 
-void MutationAccumulationRouter::willRemoveChild(Node* target, Node* child)
+void ChildListMutationScope::MutationAccumulationRouter::willRemoveChild(Node* target, Node* child)
 {
-    HashMap<Node*, OwnPtr<ChildListMutationAccumulator> >::iterator iter = m_accumulations.find(target);
+    HashMap<Node*, OwnPtr<ChildListMutationScope::MutationAccumulator> >::iterator iter = m_accumulations.find(target);
     ASSERT(iter != m_accumulations.end());
     if (iter == m_accumulations.end() || !iter->second)
         return;
@@ -235,7 +209,7 @@
     iter->second->willRemoveChild(child);
 }
 
-void MutationAccumulationRouter::incrementScopingLevel(Node* target)
+void ChildListMutationScope::MutationAccumulationRouter::incrementScopingLevel(Node* target)
 {
     pair<ScopingLevelMap::iterator, bool> result = m_scopingLevels.add(target, 1);
     if (!result.second) {
@@ -244,14 +218,14 @@
     }
 
     if (OwnPtr<MutationObserverInterestGroup> observers = MutationObserverInterestGroup::createForChildListMutation(target))
-        m_accumulations.set(target, adoptPtr(new ChildListMutationAccumulator(target, observers.release())));
+        m_accumulations.set(target, adoptPtr(new ChildListMutationScope::MutationAccumulator(target, observers.release())));
 #ifndef NDEBUG
     else
         m_accumulations.set(target, nullptr);
 #endif
 }
 
-void MutationAccumulationRouter::decrementScopingLevel(Node* target)
+void ChildListMutationScope::MutationAccumulationRouter::decrementScopingLevel(Node* target)
 {
     ScopingLevelMap::iterator iter = m_scopingLevels.find(target);
     ASSERT(iter != m_scopingLevels.end());
@@ -262,34 +236,11 @@
 
     m_scopingLevels.remove(iter);
 
-    OwnPtr<ChildListMutationAccumulator> record(m_accumulations.take(target));
+    OwnPtr<MutationAccumulator> record(m_accumulations.take(target));
     if (record)
         record->enqueueMutationRecord();
 }
 
-} // namespace
-
-ChildListMutationScope::ChildListMutationScope(Node* target)
-    : m_target(target)
-{
-    MutationAccumulationRouter::instance()->incrementScopingLevel(m_target);
-}
-
-ChildListMutationScope::~ChildListMutationScope()
-{
-    MutationAccumulationRouter::instance()->decrementScopingLevel(m_target);
-}
-
-void ChildListMutationScope::childAdded(Node* child)
-{
-    MutationAccumulationRouter::instance()->childAdded(m_target, child);
-}
-
-void ChildListMutationScope::willRemoveChild(Node* child)
-{
-    MutationAccumulationRouter::instance()->willRemoveChild(m_target, child);
-}
-
 } // namespace WebCore
 
 #endif // ENABLE(MUTATION_OBSERVERS)

Modified: trunk/Source/WebCore/dom/ChildListMutationScope.h (103078 => 103079)


--- trunk/Source/WebCore/dom/ChildListMutationScope.h	2011-12-16 18:07:29 UTC (rev 103078)
+++ trunk/Source/WebCore/dom/ChildListMutationScope.h	2011-12-16 18:27:13 UTC (rev 103079)
@@ -33,22 +33,70 @@
 
 #if ENABLE(MUTATION_OBSERVERS)
 
+#include "Document.h"
+#include "Node.h"
+#include "WebKitMutationObserver.h"
+#include <wtf/HashMap.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
 
 namespace WebCore {
 
-class Node;
-
 class ChildListMutationScope {
     WTF_MAKE_NONCOPYABLE(ChildListMutationScope);
 public:
-    ChildListMutationScope(Node* target);
-    ~ChildListMutationScope();
+    ChildListMutationScope(Node* target)
+        : m_target(target->document()->hasMutationObserversOfType(WebKitMutationObserver::ChildList) ? target : 0)
+    {
+        if (m_target)
+            MutationAccumulationRouter::instance()->incrementScopingLevel(m_target);
+    }
 
-    void childAdded(Node*);
-    void willRemoveChild(Node*);
+    ~ChildListMutationScope()
+    {
+        if (m_target)
+            MutationAccumulationRouter::instance()->decrementScopingLevel(m_target);
+    }
 
+    void childAdded(Node* child)
+    {
+        if (m_target)
+            MutationAccumulationRouter::instance()->childAdded(m_target, child);
+    }
+
+    void willRemoveChild(Node* child)
+    {
+        if (m_target)
+            MutationAccumulationRouter::instance()->willRemoveChild(m_target, child);
+    }
+
 private:
+    class MutationAccumulator;
+
+    class MutationAccumulationRouter {
+        WTF_MAKE_NONCOPYABLE(MutationAccumulationRouter);
+    public:
+        ~MutationAccumulationRouter();
+
+        static MutationAccumulationRouter* instance();
+
+        void incrementScopingLevel(Node*);
+        void decrementScopingLevel(Node*);
+
+        void childAdded(Node* target, Node* child);
+        void willRemoveChild(Node* target, Node* child);
+
+    private:
+        MutationAccumulationRouter();
+        static void initialize();
+
+        typedef HashMap<Node*, unsigned> ScopingLevelMap;
+        ScopingLevelMap m_scopingLevels;
+        HashMap<Node*, OwnPtr<MutationAccumulator> > m_accumulations;
+
+        static MutationAccumulationRouter* s_instance;
+    };
+
     Node* m_target;
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to