Diff
Modified: trunk/Source/WebCore/ChangeLog (121125 => 121126)
--- trunk/Source/WebCore/ChangeLog 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/ChangeLog 2012-06-25 00:41:05 UTC (rev 121126)
@@ -1,3 +1,55 @@
+2012-06-24 Sheriff Bot <[email protected]>
+
+ Unreviewed, rolling out r121106.
+ http://trac.webkit.org/changeset/121106
+ https://bugs.webkit.org/show_bug.cgi?id=89841
+
+ Caused 85% performance regressions on Dromaeo/jslib-modify-
+ jquery.html (Requested by rniwa on #webkit).
+
+ * dom/Document.cpp:
+ (WebCore::Document::clearNodeListCaches):
+ * dom/Document.h:
+ (Document):
+ * dom/DynamicNodeList.cpp:
+ (WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList):
+ * dom/DynamicNodeList.h:
+ (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
+ * dom/Node.cpp:
+ (WebCore::Node::clearRareData):
+ (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
+ (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
+ (WebCore::Node::getElementsByTagName):
+ (WebCore::Node::getElementsByTagNameNS):
+ (WebCore::Node::getElementsByName):
+ (WebCore::Node::getElementsByClassName):
+ (WebCore::Node::radioNodeList):
+ (WebCore::NodeListsNodeData::invalidateCaches):
+ (WebCore):
+ (WebCore::NodeRareData::createNodeLists):
+ * dom/NodeRareData.h:
+ (NodeListsNodeData):
+ (WebCore::NodeListsNodeData::adoptTreeScope):
+ (WebCore::NodeRareData::ensureNodeLists):
+ (NodeRareData):
+ * dom/TreeScope.cpp:
+ (WebCore::TreeScope::TreeScope):
+ * dom/TreeScope.h:
+ (WebCore::TreeScope::addNodeListCache):
+ (WebCore::TreeScope::removeNodeListCache):
+ (WebCore::TreeScope::hasNodeListCaches):
+ (TreeScope):
+ * dom/TreeScopeAdopter.cpp:
+ (WebCore::TreeScopeAdopter::moveTreeToNewScope):
+ * html/LabelableElement.cpp:
+ (WebCore::LabelableElement::labels):
+ * html/LabelsNodeList.cpp:
+ (WebCore::LabelsNodeList::LabelsNodeList):
+ (WebCore::LabelsNodeList::~LabelsNodeList):
+ * html/RadioNodeList.cpp:
+ (WebCore::RadioNodeList::RadioNodeList):
+ (WebCore::RadioNodeList::~RadioNodeList):
+
2012-06-24 Adam Barth <[email protected]>
Change the type of the second argument of FrameSelection::revealSelection to use RevealExtentOption
Modified: trunk/Source/WebCore/dom/Document.cpp (121125 => 121126)
--- trunk/Source/WebCore/dom/Document.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -3872,14 +3872,11 @@
m_listsInvalidatedAtDocument.remove(list);
}
-void Document::clearNodeListCaches(const QualifiedName* attrName)
+void Document::clearNodeListCaches()
{
- // FIXME: Only invalidate caches of node lists that match attrName.
HashSet<DynamicSubtreeNodeList*>::iterator end = m_listsInvalidatedAtDocument.end();
- for (HashSet<DynamicSubtreeNodeList*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it) {
- if (!attrName || (*it)->shouldInvalidateOnAttributeChange())
- (*it)->invalidateCache();
- }
+ for (HashSet<DynamicSubtreeNodeList*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
+ (*it)->invalidateCache();
}
void Document::attachNodeIterator(NodeIterator* ni)
Modified: trunk/Source/WebCore/dom/Document.h (121125 => 121126)
--- trunk/Source/WebCore/dom/Document.h 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/Document.h 2012-06-25 00:41:05 UTC (rev 121126)
@@ -714,7 +714,7 @@
void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
- void clearNodeListCaches(const QualifiedName* attrName);
+ void clearNodeListCaches();
void attachNodeIterator(NodeIterator*);
void detachNodeIterator(NodeIterator*);
Modified: trunk/Source/WebCore/dom/DynamicNodeList.cpp (121125 => 121126)
--- trunk/Source/WebCore/dom/DynamicNodeList.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/DynamicNodeList.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -30,7 +30,6 @@
DynamicSubtreeNodeList::~DynamicSubtreeNodeList()
{
- document()->unregisterDynamicSubtreeNodeList(this);
}
unsigned DynamicSubtreeNodeList::length() const
Modified: trunk/Source/WebCore/dom/DynamicNodeList.h (121125 => 121126)
--- trunk/Source/WebCore/dom/DynamicNodeList.h 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/DynamicNodeList.h 2012-06-25 00:41:05 UTC (rev 121126)
@@ -123,9 +123,7 @@
protected:
DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode, InvalidationType invalidationType = AlwaysInvalidate)
: DynamicNodeList(node, rootType, invalidationType)
- {
- document()->registerDynamicSubtreeNodeList(this);
- }
+ { }
private:
Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
Modified: trunk/Source/WebCore/dom/Node.cpp (121125 => 121126)
--- trunk/Source/WebCore/dom/Node.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/Node.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -482,6 +482,9 @@
void Node::clearRareData()
{
ASSERT(hasRareData());
+ if (treeScope() && rareData()->nodeLists())
+ treeScope()->removeNodeListCache();
+
#if ENABLE(MUTATION_OBSERVERS)
ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
#endif
@@ -948,10 +951,10 @@
return;
// FIXME: Move the list of attributes each NodeList type cares about to be a static on the
- // appropriate NodeList class. Then use those lists here and in clearNodeListCaches
+ // appropriate NodeList class. Then use those lists here and in invalidateCachesThatDependOnAttributes
// to only invalidate the cache types that depend on the attribute that changed.
// FIXME: Keep track of when we have no caches of a given type so that we can avoid the for-loop
- // in clearNodeListCaches even if a related attribute changed (e.g. if we have no RadioNodeLists, we don't need
+ // below even if a related attribute changed (e.g. if we have no RadioNodeLists, we don't need
// to invalidate any caches when id attributes change.)
if (attrName != classAttr
#if ENABLE(MICRODATA)
@@ -964,7 +967,21 @@
&& (attrName != idAttr || !attributeOwnerElement->isFormControlElement()))
return;
- document()->clearNodeListCaches(&attrName);
+ document()->clearNodeListCaches();
+
+ if (!treeScope()->hasNodeListCaches())
+ return;
+
+ for (Node* node = this; node; node = node->parentNode()) {
+ ASSERT(this == node || !node->isAttributeNode());
+ if (!node->hasRareData())
+ continue;
+ NodeRareData* data = ""
+ if (!data->nodeLists())
+ continue;
+
+ data->nodeLists()->invalidateCaches(&attrName);
+ }
}
void Node::invalidateNodeListsCacheAfterChildrenChanged()
@@ -972,7 +989,20 @@
if (hasRareData())
rareData()->clearChildNodeListCache();
- document()->clearNodeListCaches(0);
+ document()->clearNodeListCaches();
+
+ if (!treeScope()->hasNodeListCaches())
+ return;
+
+ for (Node* node = this; node; node = node->parentNode()) {
+ if (!node->hasRareData())
+ continue;
+ NodeRareData* data = ""
+ if (!data->nodeLists())
+ continue;
+
+ data->nodeLists()->invalidateCaches();
+ }
}
NodeListsNodeData* Node::nodeLists()
@@ -1518,8 +1548,8 @@
return 0;
if (document()->isHTMLDocument())
- return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
- return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
}
PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
@@ -1530,23 +1560,23 @@
if (namespaceURI == starAtom)
return getElementsByTagName(localName);
- return ensureRareData()->ensureNodeLists()->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
}
PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
{
- return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName);
}
PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
{
- return ensureRareData()->ensureNodeLists()->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames);
}
PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)
{
ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
- return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name);
+ return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name);
}
PassRefPtr<Element> Node::querySelector(const AtomicString& selectors, ExceptionCode& ec)
@@ -2208,6 +2238,28 @@
// --------
+void NodeListsNodeData::invalidateCaches(const QualifiedName* attrName)
+{
+ NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+ for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
+ if (!attrName || it->second->shouldInvalidateOnAttributeChange())
+ it->second->invalidateCache();
+ }
+
+ NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+ for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
+ if (!attrName || it->second->shouldInvalidateOnAttributeChange())
+ it->second->invalidateCache();
+ }
+
+ if (!attrName)
+ return;
+
+ TagNodeListCacheNS::iterator tagCacheEnd = m_tagNodeListCacheNS.end();
+ for (TagNodeListCacheNS::iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEnd; ++it)
+ it->second->invalidateCache();
+}
+
void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
{
addSubresourceAttributeURLs(urls);
@@ -2702,9 +2754,12 @@
}
#endif
-void NodeRareData::createNodeLists()
+void NodeRareData::createNodeLists(Node* node)
{
+ ASSERT(node);
setNodeLists(NodeListsNodeData::create());
+ if (TreeScope* treeScope = node->treeScope())
+ treeScope->addNodeListCache();
}
void NodeRareData::clearChildNodeListCache()
Modified: trunk/Source/WebCore/dom/NodeRareData.h (121125 => 121126)
--- trunk/Source/WebCore/dom/NodeRareData.h 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/NodeRareData.h 2012-06-25 00:41:05 UTC (rev 121126)
@@ -123,36 +123,39 @@
return adoptPtr(new NodeListsNodeData);
}
+ void invalidateCaches(const QualifiedName* attrName = 0);
bool isEmpty() const
{
return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagNodeListCacheNS.isEmpty();
}
- void adoptTreeScope(Document* oldDocument, Document* newDocument)
+ void adoptTreeScope(TreeScope* oldTreeScope, TreeScope* newTreeScope, Document* oldDocument, Document* newDocument)
{
- NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
- for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
- DynamicSubtreeNodeList* list = it->second;
- list->invalidateCache();
- if (oldDocument != newDocument && list->isRootedAtDocument()) {
- oldDocument->unregisterDynamicSubtreeNodeList(list);
- newDocument->registerDynamicSubtreeNodeList(list);
+ invalidateCaches();
+
+ if (oldDocument != newDocument) {
+ NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+ for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
+ DynamicSubtreeNodeList* list = it->second;
+ if (list->isRootedAtDocument()) {
+ oldDocument->unregisterDynamicSubtreeNodeList(list);
+ newDocument->registerDynamicSubtreeNodeList(list);
+ }
}
- }
- NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
- for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
- DynamicSubtreeNodeList* list = it->second;
- list->invalidateCache();
- if (oldDocument != newDocument && list->isRootedAtDocument()) {
- oldDocument->unregisterDynamicSubtreeNodeList(list);
- newDocument->registerDynamicSubtreeNodeList(list);
+ NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+ for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
+ DynamicSubtreeNodeList* list = it->second;
+ if (list->isRootedAtDocument()) {
+ oldDocument->unregisterDynamicSubtreeNodeList(list);
+ newDocument->registerDynamicSubtreeNodeList(list);
+ }
}
}
- TagNodeListCacheNS::iterator tagCacheEnd = m_tagNodeListCacheNS.end();
- for (TagNodeListCacheNS::iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEnd; ++it)
- it->second->invalidateCache();
+ if (oldTreeScope)
+ oldTreeScope->removeNodeListCache();
+ newTreeScope->addNodeListCache();
}
private:
@@ -212,10 +215,10 @@
void clearNodeLists() { m_nodeLists.clear(); }
void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
- NodeListsNodeData* ensureNodeLists()
+ NodeListsNodeData* ensureNodeLists(Node* node)
{
if (!m_nodeLists)
- createNodeLists();
+ createNodeLists(node);
return m_nodeLists.get();
}
void clearChildNodeListCache();
@@ -345,7 +348,7 @@
void setNeedsFocusAppearanceUpdateSoonAfterAttach(bool needs) { m_needsFocusAppearanceUpdateSoonAfterAttach = needs; }
private:
- void createNodeLists();
+ void createNodeLists(Node*);
TreeScope* m_treeScope;
OwnPtr<NodeListsNodeData> m_nodeLists;
Modified: trunk/Source/WebCore/dom/TreeScope.cpp (121125 => 121126)
--- trunk/Source/WebCore/dom/TreeScope.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/TreeScope.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -54,6 +54,7 @@
TreeScope::TreeScope(ContainerNode* rootNode)
: m_rootNode(rootNode)
, m_parentTreeScope(0)
+ , m_numNodeListCaches(0)
{
ASSERT(rootNode);
}
Modified: trunk/Source/WebCore/dom/TreeScope.h (121125 => 121126)
--- trunk/Source/WebCore/dom/TreeScope.h 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/TreeScope.h 2012-06-25 00:41:05 UTC (rev 121126)
@@ -61,6 +61,10 @@
void removeImageMap(HTMLMapElement*);
HTMLMapElement* getImageMap(const String& url) const;
+ void addNodeListCache() { ++m_numNodeListCaches; }
+ void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; }
+ bool hasNodeListCaches() const { return m_numNodeListCaches; }
+
DOMSelection* getSelection() const;
// Find first anchor with the given name.
@@ -91,6 +95,8 @@
DocumentOrderedMap m_elementsById;
DocumentOrderedMap m_imageMapsByName;
+ unsigned m_numNodeListCaches;
+
mutable RefPtr<DOMSelection> m_selection;
};
Modified: trunk/Source/WebCore/dom/TreeScopeAdopter.cpp (121125 => 121126)
--- trunk/Source/WebCore/dom/TreeScopeAdopter.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/dom/TreeScopeAdopter.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -54,7 +54,7 @@
for (Node* node = root; node; node = node->traverseNextNode(root)) {
NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
if (rareData && rareData->nodeLists())
- rareData->nodeLists()->adoptTreeScope(oldDocument, newDocument);
+ rareData->nodeLists()->adoptTreeScope(m_oldScope, m_newScope, oldDocument, newDocument);
if (willMoveToNewDocument)
moveNodeToNewDocument(node, oldDocument, newDocument);
Modified: trunk/Source/WebCore/html/LabelableElement.cpp (121125 => 121126)
--- trunk/Source/WebCore/html/LabelableElement.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/html/LabelableElement.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -47,7 +47,7 @@
if (!document())
return 0;
- return Node::ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom);
+ return Node::ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom);
}
} // namespace Webcore
Modified: trunk/Source/WebCore/html/LabelsNodeList.cpp (121125 => 121126)
--- trunk/Source/WebCore/html/LabelsNodeList.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/html/LabelsNodeList.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -36,11 +36,13 @@
LabelsNodeList::LabelsNodeList(Node* forNode)
: DynamicSubtreeNodeList(forNode, RootedAtDocument)
{
+ document()->registerDynamicSubtreeNodeList(this);
}
LabelsNodeList::~LabelsNodeList()
{
ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
+ document()->unregisterDynamicSubtreeNodeList(this);
}
bool LabelsNodeList::nodeMatches(Element* testNode) const
Modified: trunk/Source/WebCore/html/RadioNodeList.cpp (121125 => 121126)
--- trunk/Source/WebCore/html/RadioNodeList.cpp 2012-06-25 00:29:03 UTC (rev 121125)
+++ trunk/Source/WebCore/html/RadioNodeList.cpp 2012-06-25 00:41:05 UTC (rev 121126)
@@ -41,11 +41,13 @@
: DynamicSubtreeNodeList(rootNode, rootNode->hasTagName(formTag) ? RootedAtDocument : RootedAtNode)
, m_name(name)
{
+ document()->registerDynamicSubtreeNodeList(this);
}
RadioNodeList::~RadioNodeList()
{
ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
+ document()->unregisterDynamicSubtreeNodeList(this);
}
static inline HTMLInputElement* toRadioButtonInputElement(Node* node)