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;
};