Title: [102721] trunk/Source/WebCore
Revision
102721
Author
[email protected]
Date
2011-12-13 17:03:01 -0800 (Tue, 13 Dec 2011)

Log Message

[MutationObservers] Avoid allocations if no observers are present
https://bugs.webkit.org/show_bug.cgi?id=74423

Patch by Rafael Weinstein <[email protected]> on 2011-12-13
Reviewed by Ojan Vafai.

This patch adds Node::mayHaveMutationObserversOfType which can be used to check
if there are any observers at all which could receive a give type of mutation.
MutationObserverInterestGroup uses this to possibly exit early (returning
null) if no observers are present.

No tests needed. This patch is just a refactor.

* css/CSSMutableStyleDeclaration.cpp:
* dom/CharacterData.cpp:
(WebCore::CharacterData::dispatchModifiedEvent):
* dom/ChildListMutationScope.cpp:
(WebCore::ChildListMutationAccumulator::MutationAccumulationRouter::incrementScopingLevel):
* dom/Element.cpp:
(WebCore::enqueueAttributesMutationRecord):
* dom/Node.cpp:
(WebCore::Node::mayHaveMutationObserversOfType):
* dom/Node.h:
* dom/WebKitMutationObserver.cpp:
(WebCore::MutationObserverInterestGroup::createIfNeeded):
(WebCore::MutationObserverInterestGroup::createForChildListMutation):
(WebCore::MutationObserverInterestGroup::createForCharacterDataMutation):
(WebCore::MutationObserverInterestGroup::createForAttributesMutation):
(WebCore::MutationObserverInterestGroup::MutationObserverInterestGroup):
(WebCore::MutationObserverInterestGroup::enqueueMutationRecord):
* dom/WebKitMutationObserver.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (102720 => 102721)


--- trunk/Source/WebCore/ChangeLog	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/ChangeLog	2011-12-14 01:03:01 UTC (rev 102721)
@@ -1,3 +1,36 @@
+2011-12-13  Rafael Weinstein  <[email protected]>
+
+        [MutationObservers] Avoid allocations if no observers are present
+        https://bugs.webkit.org/show_bug.cgi?id=74423
+
+        Reviewed by Ojan Vafai.
+
+        This patch adds Node::mayHaveMutationObserversOfType which can be used to check
+        if there are any observers at all which could receive a give type of mutation.
+        MutationObserverInterestGroup uses this to possibly exit early (returning
+        null) if no observers are present.
+
+        No tests needed. This patch is just a refactor.
+
+        * css/CSSMutableStyleDeclaration.cpp:
+        * dom/CharacterData.cpp:
+        (WebCore::CharacterData::dispatchModifiedEvent):
+        * dom/ChildListMutationScope.cpp:
+        (WebCore::ChildListMutationAccumulator::MutationAccumulationRouter::incrementScopingLevel):
+        * dom/Element.cpp:
+        (WebCore::enqueueAttributesMutationRecord):
+        * dom/Node.cpp:
+        (WebCore::Node::mayHaveMutationObserversOfType):
+        * dom/Node.h:
+        * dom/WebKitMutationObserver.cpp:
+        (WebCore::MutationObserverInterestGroup::createIfNeeded):
+        (WebCore::MutationObserverInterestGroup::createForChildListMutation):
+        (WebCore::MutationObserverInterestGroup::createForCharacterDataMutation):
+        (WebCore::MutationObserverInterestGroup::createForAttributesMutation):
+        (WebCore::MutationObserverInterestGroup::MutationObserverInterestGroup):
+        (WebCore::MutationObserverInterestGroup::enqueueMutationRecord):
+        * dom/WebKitMutationObserver.h:
+
 2011-12-13  Robin Dunn  <[email protected]>
 
         Don't make the bitmap transparent when using theme drawing

Modified: trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp (102720 => 102721)


--- trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -71,10 +71,8 @@
             return;
 
         m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(inlineDecl->element(), HTMLNames::styleAttr);
-        if (m_mutationRecipients->isEmpty()) {
-            m_mutationRecipients.clear();
+        if (!m_mutationRecipients)
             return;
-        }
 
         AtomicString oldValue = m_mutationRecipients->isOldValueRequested() ? inlineDecl->element()->getAttribute(HTMLNames::styleAttr) : nullAtom;
         m_mutation = MutationRecord::createAttributes(inlineDecl->element(), HTMLNames::styleAttr, oldValue);

Modified: trunk/Source/WebCore/dom/CharacterData.cpp (102720 => 102721)


--- trunk/Source/WebCore/dom/CharacterData.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/CharacterData.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -191,8 +191,8 @@
 void CharacterData::dispatchModifiedEvent(const String& oldData)
 {
 #if ENABLE(MUTATION_OBSERVERS)
-    OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(this);
-    mutationRecipients->enqueueMutationRecord(MutationRecord::createCharacterData(this, oldData));
+    if (OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(this))
+        mutationRecipients->enqueueMutationRecord(MutationRecord::createCharacterData(this, oldData));
 #endif
     if (parentNode())
         parentNode()->childrenChanged();

Modified: trunk/Source/WebCore/dom/ChildListMutationScope.cpp (102720 => 102721)


--- trunk/Source/WebCore/dom/ChildListMutationScope.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/ChildListMutationScope.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -218,18 +218,20 @@
 {
     HashMap<Node*, OwnPtr<ChildListMutationAccumulator> >::iterator iter = m_accumulations.find(target);
     ASSERT(iter != m_accumulations.end());
+    if (iter == m_accumulations.end() || !iter->second)
+        return;
 
-    if (iter->second)
-        iter->second->childAdded(child);
+    iter->second->childAdded(child);
 }
 
 void MutationAccumulationRouter::willRemoveChild(Node* target, Node* child)
 {
     HashMap<Node*, OwnPtr<ChildListMutationAccumulator> >::iterator iter = m_accumulations.find(target);
     ASSERT(iter != m_accumulations.end());
+    if (iter == m_accumulations.end() || !iter->second)
+        return;
 
-    if (iter->second)
-        iter->second->willRemoveChild(child);
+    iter->second->willRemoveChild(child);
 }
 
 void MutationAccumulationRouter::incrementScopingLevel(Node* target)
@@ -240,11 +242,12 @@
         return;
     }
 
-    OwnPtr<MutationObserverInterestGroup> observers = MutationObserverInterestGroup::createForChildListMutation(target);
-    if (observers->isEmpty())
+    if (OwnPtr<MutationObserverInterestGroup> observers = MutationObserverInterestGroup::createForChildListMutation(target))
+        m_accumulations.set(target, adoptPtr(new ChildListMutationAccumulator(target, observers.release())));
+#ifndef NDEBUG
+    else
         m_accumulations.set(target, nullptr);
-    else
-        m_accumulations.set(target, adoptPtr(new ChildListMutationAccumulator(target, observers.release())));
+#endif
 }
 
 void MutationAccumulationRouter::decrementScopingLevel(Node* target)

Modified: trunk/Source/WebCore/dom/Element.cpp (102720 => 102721)


--- trunk/Source/WebCore/dom/Element.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/Element.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -183,8 +183,8 @@
 #if ENABLE(MUTATION_OBSERVERS)
 static void enqueueAttributesMutationRecord(Element* target, const QualifiedName& attributeName, const AtomicString& oldValue)
 {
-    OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName);
-    mutationRecipients->enqueueMutationRecord(MutationRecord::createAttributes(target, attributeName, oldValue));
+    if (OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName))
+        mutationRecipients->enqueueMutationRecord(MutationRecord::createAttributes(target, attributeName, oldValue));
 }
 #endif
 

Modified: trunk/Source/WebCore/dom/Node.cpp (102720 => 102721)


--- trunk/Source/WebCore/dom/Node.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/Node.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -2714,6 +2714,11 @@
     }
 }
 
+bool Node::mayHaveMutationObserversOfType(WebKitMutationObserver::MutationType type)
+{
+    return document()->hasSubtreeMutationObserverOfType(type) || (hasRareData() && (rareData()->mutationObserverRegistry() || rareData()->transientMutationObserverRegistry()));
+}
+
 void Node::getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions>& observers, WebKitMutationObserver::MutationType type, const AtomicString& attributeName)
 {
     collectMatchingObserversForMutation(observers, this, type, attributeName);

Modified: trunk/Source/WebCore/dom/Node.h (102720 => 102721)


--- trunk/Source/WebCore/dom/Node.h	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/Node.h	2011-12-14 01:03:01 UTC (rev 102721)
@@ -599,6 +599,7 @@
 
 #if ENABLE(MUTATION_OBSERVERS)
     void getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions>&, WebKitMutationObserver::MutationType, const AtomicString& attributeName = nullAtom);
+    bool mayHaveMutationObserversOfType(WebKitMutationObserver::MutationType);
     MutationObserverRegistration* registerMutationObserver(PassRefPtr<WebKitMutationObserver>);
     void unregisterMutationObserver(MutationObserverRegistration*);
     void registerTransientMutationObserver(MutationObserverRegistration*);

Modified: trunk/Source/WebCore/dom/WebKitMutationObserver.cpp (102720 => 102721)


--- trunk/Source/WebCore/dom/WebKitMutationObserver.cpp	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/WebKitMutationObserver.cpp	2011-12-14 01:03:01 UTC (rev 102721)
@@ -149,28 +149,40 @@
     deliveryInProgress = false;
 }
 
+PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createIfNeeded(Node* target, WebKitMutationObserver::MutationType type, const AtomicString& attributeName, MutationRecordDeliveryOptions oldValueFlag)
+{
+    if (!target->mayHaveMutationObserversOfType(type))
+        return nullptr;
+
+    HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions> observers;
+    target->getRegisteredMutationObserversOfType(observers, type, attributeName);
+    if (observers.isEmpty())
+        return nullptr;
+
+    return adoptPtr(new MutationObserverInterestGroup(observers, oldValueFlag));
+}
+
 PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForChildListMutation(Node* target)
 {
-    return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::ChildList));
+    MutationRecordDeliveryOptions oldValueFlag = 0;
+    return createIfNeeded(target, WebKitMutationObserver::ChildList, nullAtom, oldValueFlag);
 }
 
 PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForCharacterDataMutation(Node* target)
 {
-    return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::CharacterData));
+    return createIfNeeded(target, WebKitMutationObserver::CharacterData, nullAtom, WebKitMutationObserver::CharacterDataOldValue);
 }
 
 PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForAttributesMutation(Node* target, const QualifiedName& attributeName)
 {
-    return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::Attributes, attributeName.localName()));
+    return createIfNeeded(target, WebKitMutationObserver::Attributes, attributeName.localName(), WebKitMutationObserver::AttributeOldValue);
 }
 
-MutationObserverInterestGroup::MutationObserverInterestGroup(Node* target, WebKitMutationObserver::MutationType type, const AtomicString& attributeName)
+MutationObserverInterestGroup::MutationObserverInterestGroup(HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions> observers, MutationRecordDeliveryOptions oldValueFlag)
+    : m_oldValueFlag(oldValueFlag)
 {
-    target->getRegisteredMutationObserversOfType(m_observers, type, attributeName);
-    if (type & WebKitMutationObserver::Attributes)
-        m_oldValueFlag = WebKitMutationObserver::AttributeOldValue;
-    else if (type & WebKitMutationObserver::CharacterData)
-        m_oldValueFlag = WebKitMutationObserver::CharacterDataOldValue;
+    ASSERT(!observers.isEmpty());
+    m_observers.swap(observers);
 }
 
 bool MutationObserverInterestGroup::isOldValueRequested()
@@ -184,9 +196,6 @@
 
 void MutationObserverInterestGroup::enqueueMutationRecord(PassRefPtr<MutationRecord> prpMutation)
 {
-    if (m_observers.isEmpty())
-        return;
-
     RefPtr<MutationRecord> mutation = prpMutation;
     RefPtr<MutationRecord> mutationWithNullOldValue;
     for (HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions>::iterator iter = m_observers.begin(); iter != m_observers.end(); ++iter) {

Modified: trunk/Source/WebCore/dom/WebKitMutationObserver.h (102720 => 102721)


--- trunk/Source/WebCore/dom/WebKitMutationObserver.h	2011-12-14 00:20:11 UTC (rev 102720)
+++ trunk/Source/WebCore/dom/WebKitMutationObserver.h	2011-12-14 01:03:01 UTC (rev 102721)
@@ -103,15 +103,15 @@
     static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const QualifiedName& attributeName);
 
     bool isOldValueRequested();
-    bool isEmpty() { return m_observers.isEmpty(); }
     void enqueueMutationRecord(PassRefPtr<MutationRecord>);
 private:
-    MutationObserverInterestGroup(Node* target, WebKitMutationObserver::MutationType, const AtomicString& attributeName = nullAtom);
+    static PassOwnPtr<MutationObserverInterestGroup> createIfNeeded(Node* target, WebKitMutationObserver::MutationType, const AtomicString& attributeName, MutationRecordDeliveryOptions oldValueFlag);
+    MutationObserverInterestGroup(HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions> observers, MutationRecordDeliveryOptions oldValueFlag);
 
     inline bool hasOldValue(MutationRecordDeliveryOptions options) { return options & m_oldValueFlag; }
 
     HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions> m_observers;
-    WebKitMutationObserver::DeliveryFlags m_oldValueFlag;
+    MutationRecordDeliveryOptions m_oldValueFlag;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to