| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2010 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 David Smith <catfish.man@gmail.com> | 3 * Copyright (C) 2008 David Smith <catfish.man@gmail.com> |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 } | 77 } |
| 78 | 78 |
| 79 void removeEmptyChildNodeList(EmptyNodeList* list) | 79 void removeEmptyChildNodeList(EmptyNodeList* list) |
| 80 { | 80 { |
| 81 ASSERT(m_childNodeList == list); | 81 ASSERT(m_childNodeList == list); |
| 82 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) | 82 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) |
| 83 return; | 83 return; |
| 84 m_childNodeList = 0; | 84 m_childNodeList = 0; |
| 85 } | 85 } |
| 86 | 86 |
| 87 template <typename StringType> | |
| 88 struct NodeListCacheMapEntryHash { | |
| 89 static unsigned hash(const std::pair<unsigned char, StringType>& entry) | |
| 90 { | |
| 91 return DefaultHash<StringType>::Hash::hash(entry.second) + entry.fir
st; | |
| 92 } | |
| 93 static bool equal(const std::pair<unsigned char, StringType>& a, const s
td::pair<unsigned char, StringType>& b) { return a == b; } | |
| 94 static const bool safeToCompareToEmptyOrDeleted = DefaultHash<StringType
>::Hash::safeToCompareToEmptyOrDeleted; | |
| 95 }; | |
| 96 | |
| 97 struct NodeListAtomicCacheMapEntryHash { | 87 struct NodeListAtomicCacheMapEntryHash { |
| 98 static unsigned hash(const std::pair<unsigned char, StringImpl*>& entry) | 88 static unsigned hash(const std::pair<unsigned char, StringImpl*>& entry) |
| 99 { | 89 { |
| 100 return DefaultHash<StringImpl*>::Hash::hash(entry.second) + entry.fi
rst; | 90 return DefaultHash<StringImpl*>::Hash::hash(entry.second) + entry.fi
rst; |
| 101 } | 91 } |
| 102 static bool equal(const std::pair<unsigned char, StringImpl*>& a, const
std::pair<unsigned char, StringImpl*>& b) { return a == b; } | 92 static bool equal(const std::pair<unsigned char, StringImpl*>& a, const
std::pair<unsigned char, StringImpl*>& b) { return a == b; } |
| 103 static const bool safeToCompareToEmptyOrDeleted = DefaultHash<StringImpl
*>::Hash::safeToCompareToEmptyOrDeleted; | 93 static const bool safeToCompareToEmptyOrDeleted = DefaultHash<StringImpl
*>::Hash::safeToCompareToEmptyOrDeleted; |
| 104 }; | 94 }; |
| 105 | 95 |
| 106 typedef HashMap<std::pair<unsigned char, StringImpl*>, LiveNodeListBase*, No
deListAtomicCacheMapEntryHash> NodeListAtomicNameCacheMap; | 96 typedef HashMap<std::pair<unsigned char, StringImpl*>, LiveNodeListBase*, No
deListAtomicCacheMapEntryHash> NodeListAtomicNameCacheMap; |
| 107 typedef HashMap<std::pair<unsigned char, String>, LiveNodeListBase*, NodeLis
tCacheMapEntryHash<String> > NodeListNameCacheMap; | |
| 108 typedef HashMap<QualifiedName, TagCollection*> TagCollectionCacheNS; | 97 typedef HashMap<QualifiedName, TagCollection*> TagCollectionCacheNS; |
| 109 | 98 |
| 110 template<typename T> | 99 template<typename T> |
| 111 PassRefPtr<T> addCacheWithAtomicName(ContainerNode* node, CollectionType col
lectionType, const AtomicString& name) | 100 PassRefPtr<T> addCacheWithAtomicName(ContainerNode* node, CollectionType col
lectionType, const AtomicString& name) |
| 112 { | 101 { |
| 113 NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(na
medNodeListKey(collectionType, name), 0); | 102 NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(na
medNodeListKey(collectionType, name), 0); |
| 114 if (!result.isNewEntry) | 103 if (!result.isNewEntry) |
| 115 return static_cast<T*>(result.iterator->value); | 104 return static_cast<T*>(result.iterator->value); |
| 116 | 105 |
| 117 RefPtr<T> list = T::create(node, collectionType, name); | 106 RefPtr<T> list = T::create(node, collectionType, name); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 131 result.iterator->value = list.get(); | 120 result.iterator->value = list.get(); |
| 132 return list.release(); | 121 return list.release(); |
| 133 } | 122 } |
| 134 | 123 |
| 135 template<typename T> | 124 template<typename T> |
| 136 T* cacheWithAtomicName(CollectionType collectionType) | 125 T* cacheWithAtomicName(CollectionType collectionType) |
| 137 { | 126 { |
| 138 return static_cast<T*>(m_atomicNameCaches.get(namedNodeListKey(collectio
nType, starAtom))); | 127 return static_cast<T*>(m_atomicNameCaches.get(namedNodeListKey(collectio
nType, starAtom))); |
| 139 } | 128 } |
| 140 | 129 |
| 141 template<typename T> | |
| 142 PassRefPtr<T> addCacheWithName(Node* node, CollectionType collectionType, co
nst String& name) | |
| 143 { | |
| 144 NodeListNameCacheMap::AddResult result = m_nameCaches.add(namedNodeListK
ey(collectionType, name), 0); | |
| 145 if (!result.isNewEntry) | |
| 146 return static_cast<T*>(result.iterator->value); | |
| 147 | |
| 148 RefPtr<T> list = T::create(node, name); | |
| 149 result.iterator->value = list.get(); | |
| 150 return list.release(); | |
| 151 } | |
| 152 | |
| 153 PassRefPtr<TagCollection> addCacheWithQualifiedName(ContainerNode* node, con
st AtomicString& namespaceURI, const AtomicString& localName) | 130 PassRefPtr<TagCollection> addCacheWithQualifiedName(ContainerNode* node, con
st AtomicString& namespaceURI, const AtomicString& localName) |
| 154 { | 131 { |
| 155 QualifiedName name(nullAtom, localName, namespaceURI); | 132 QualifiedName name(nullAtom, localName, namespaceURI); |
| 156 TagCollectionCacheNS::AddResult result = m_tagCollectionCacheNS.add(name
, 0); | 133 TagCollectionCacheNS::AddResult result = m_tagCollectionCacheNS.add(name
, 0); |
| 157 if (!result.isNewEntry) | 134 if (!result.isNewEntry) |
| 158 return result.iterator->value; | 135 return result.iterator->value; |
| 159 | 136 |
| 160 RefPtr<TagCollection> list = TagCollection::create(node, namespaceURI, l
ocalName); | 137 RefPtr<TagCollection> list = TagCollection::create(node, namespaceURI, l
ocalName); |
| 161 result.iterator->value = list.get(); | 138 result.iterator->value = list.get(); |
| 162 return list.release(); | 139 return list.release(); |
| 163 } | 140 } |
| 164 | 141 |
| 165 void removeCacheWithAtomicName(LiveNodeListBase* list, CollectionType collec
tionType, const AtomicString& name = starAtom) | 142 void removeCacheWithAtomicName(LiveNodeListBase* list, CollectionType collec
tionType, const AtomicString& name = starAtom) |
| 166 { | 143 { |
| 167 ASSERT(list == m_atomicNameCaches.get(namedNodeListKey(collectionType, n
ame))); | 144 ASSERT(list == m_atomicNameCaches.get(namedNodeListKey(collectionType, n
ame))); |
| 168 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) | 145 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) |
| 169 return; | 146 return; |
| 170 m_atomicNameCaches.remove(namedNodeListKey(collectionType, name)); | 147 m_atomicNameCaches.remove(namedNodeListKey(collectionType, name)); |
| 171 } | 148 } |
| 172 | 149 |
| 173 void removeCacheWithName(LiveNodeListBase* list, CollectionType collectionTy
pe, const String& name) | |
| 174 { | |
| 175 ASSERT(list == m_nameCaches.get(namedNodeListKey(collectionType, name)))
; | |
| 176 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) | |
| 177 return; | |
| 178 m_nameCaches.remove(namedNodeListKey(collectionType, name)); | |
| 179 } | |
| 180 | |
| 181 void removeCacheWithQualifiedName(LiveNodeListBase* list, const AtomicString
& namespaceURI, const AtomicString& localName) | 150 void removeCacheWithQualifiedName(LiveNodeListBase* list, const AtomicString
& namespaceURI, const AtomicString& localName) |
| 182 { | 151 { |
| 183 QualifiedName name(nullAtom, localName, namespaceURI); | 152 QualifiedName name(nullAtom, localName, namespaceURI); |
| 184 ASSERT(list == m_tagCollectionCacheNS.get(name)); | 153 ASSERT(list == m_tagCollectionCacheNS.get(name)); |
| 185 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) | 154 if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNo
de())) |
| 186 return; | 155 return; |
| 187 m_tagCollectionCacheNS.remove(name); | 156 m_tagCollectionCacheNS.remove(name); |
| 188 } | 157 } |
| 189 | 158 |
| 190 static PassOwnPtr<NodeListsNodeData> create() | 159 static PassOwnPtr<NodeListsNodeData> create() |
| 191 { | 160 { |
| 192 return adoptPtr(new NodeListsNodeData); | 161 return adoptPtr(new NodeListsNodeData); |
| 193 } | 162 } |
| 194 | 163 |
| 195 void invalidateCaches(const QualifiedName* attrName = 0); | 164 void invalidateCaches(const QualifiedName* attrName = 0); |
| 196 bool isEmpty() const | 165 bool isEmpty() const |
| 197 { | 166 { |
| 198 return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagCo
llectionCacheNS.isEmpty(); | 167 return m_atomicNameCaches.isEmpty() && m_tagCollectionCacheNS.isEmpty(); |
| 199 } | 168 } |
| 200 | 169 |
| 201 void adoptTreeScope() | 170 void adoptTreeScope() |
| 202 { | 171 { |
| 203 invalidateCaches(); | 172 invalidateCaches(); |
| 204 } | 173 } |
| 205 | 174 |
| 206 void adoptDocument(Document& oldDocument, Document& newDocument) | 175 void adoptDocument(Document& oldDocument, Document& newDocument) |
| 207 { | 176 { |
| 208 invalidateCaches(); | 177 invalidateCaches(); |
| 209 | 178 |
| 210 if (oldDocument != newDocument) { | 179 if (oldDocument != newDocument) { |
| 211 NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_at
omicNameCaches.end(); | 180 NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_at
omicNameCaches.end(); |
| 212 for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCac
hes.begin(); it != atomicNameCacheEnd; ++it) { | 181 for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCac
hes.begin(); it != atomicNameCacheEnd; ++it) { |
| 213 LiveNodeListBase* list = it->value; | 182 LiveNodeListBase* list = it->value; |
| 214 oldDocument.unregisterNodeList(list); | 183 oldDocument.unregisterNodeList(list); |
| 215 newDocument.registerNodeList(list); | 184 newDocument.registerNodeList(list); |
| 216 } | 185 } |
| 217 | 186 |
| 218 NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end
(); | |
| 219 for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin();
it != nameCacheEnd; ++it) { | |
| 220 LiveNodeListBase* list = it->value; | |
| 221 oldDocument.unregisterNodeList(list); | |
| 222 newDocument.registerNodeList(list); | |
| 223 } | |
| 224 | |
| 225 TagCollectionCacheNS::const_iterator tagEnd = m_tagCollectionCacheNS
.end(); | 187 TagCollectionCacheNS::const_iterator tagEnd = m_tagCollectionCacheNS
.end(); |
| 226 for (TagCollectionCacheNS::const_iterator it = m_tagCollectionCacheN
S.begin(); it != tagEnd; ++it) { | 188 for (TagCollectionCacheNS::const_iterator it = m_tagCollectionCacheN
S.begin(); it != tagEnd; ++it) { |
| 227 LiveNodeListBase* list = it->value; | 189 LiveNodeListBase* list = it->value; |
| 228 ASSERT(!list->isRootedAtDocument()); | 190 ASSERT(!list->isRootedAtDocument()); |
| 229 oldDocument.unregisterNodeList(list); | 191 oldDocument.unregisterNodeList(list); |
| 230 newDocument.registerNodeList(list); | 192 newDocument.registerNodeList(list); |
| 231 } | 193 } |
| 232 } | 194 } |
| 233 } | 195 } |
| 234 | 196 |
| 235 private: | 197 private: |
| 236 NodeListsNodeData() | 198 NodeListsNodeData() |
| 237 : m_childNodeList(0) | 199 : m_childNodeList(0) |
| 238 { } | 200 { } |
| 239 | 201 |
| 240 std::pair<unsigned char, StringImpl*> namedNodeListKey(CollectionType type,
const AtomicString& name) | 202 std::pair<unsigned char, StringImpl*> namedNodeListKey(CollectionType type,
const AtomicString& name) |
| 241 { | 203 { |
| 242 // Holding the raw StringImpl is safe because |name| is retained by the
NodeList and the NodeList | 204 // Holding the raw StringImpl is safe because |name| is retained by the
NodeList and the NodeList |
| 243 // is reponsible for removing itself from the cache on deletion. | 205 // is reponsible for removing itself from the cache on deletion. |
| 244 return std::pair<unsigned char, StringImpl*>(type, name.impl()); | 206 return std::pair<unsigned char, StringImpl*>(type, name.impl()); |
| 245 } | 207 } |
| 246 | 208 |
| 247 std::pair<unsigned char, String> namedNodeListKey(CollectionType type, const
String& name) | |
| 248 { | |
| 249 return std::pair<unsigned char, String>(type, name); | |
| 250 } | |
| 251 | |
| 252 bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node*); | 209 bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node*); |
| 253 | 210 |
| 254 // Can be a ChildNodeList or an EmptyNodeList. | 211 // Can be a ChildNodeList or an EmptyNodeList. |
| 255 NodeList* m_childNodeList; | 212 NodeList* m_childNodeList; |
| 256 NodeListAtomicNameCacheMap m_atomicNameCaches; | 213 NodeListAtomicNameCacheMap m_atomicNameCaches; |
| 257 NodeListNameCacheMap m_nameCaches; | |
| 258 TagCollectionCacheNS m_tagCollectionCacheNS; | 214 TagCollectionCacheNS m_tagCollectionCacheNS; |
| 259 }; | 215 }; |
| 260 | 216 |
| 261 class NodeMutationObserverData { | 217 class NodeMutationObserverData { |
| 262 WTF_MAKE_NONCOPYABLE(NodeMutationObserverData); WTF_MAKE_FAST_ALLOCATED; | 218 WTF_MAKE_NONCOPYABLE(NodeMutationObserverData); WTF_MAKE_FAST_ALLOCATED; |
| 263 public: | 219 public: |
| 264 Vector<OwnPtr<MutationObserverRegistration> > registry; | 220 Vector<OwnPtr<MutationObserverRegistration> > registry; |
| 265 HashSet<MutationObserverRegistration*> transientRegistry; | 221 HashSet<MutationObserverRegistration*> transientRegistry; |
| 266 | 222 |
| 267 static PassOwnPtr<NodeMutationObserverData> create() { return adoptPtr(new N
odeMutationObserverData); } | 223 static PassOwnPtr<NodeMutationObserverData> create() { return adoptPtr(new N
odeMutationObserverData); } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 unsigned m_connectedFrameCount : 10; // Must fit Page::maxNumberOfFrames. | 270 unsigned m_connectedFrameCount : 10; // Must fit Page::maxNumberOfFrames. |
| 315 | 271 |
| 316 OwnPtr<NodeListsNodeData> m_nodeLists; | 272 OwnPtr<NodeListsNodeData> m_nodeLists; |
| 317 OwnPtr<NodeMutationObserverData> m_mutationObserverData; | 273 OwnPtr<NodeMutationObserverData> m_mutationObserverData; |
| 318 }; | 274 }; |
| 319 | 275 |
| 320 inline bool NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLas
tList(Node* ownerNode) | 276 inline bool NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLas
tList(Node* ownerNode) |
| 321 { | 277 { |
| 322 ASSERT(ownerNode); | 278 ASSERT(ownerNode); |
| 323 ASSERT(ownerNode->nodeLists() == this); | 279 ASSERT(ownerNode->nodeLists() == this); |
| 324 if ((m_childNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_nameCaches.siz
e() + m_tagCollectionCacheNS.size() != 1) | 280 if ((m_childNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_tagCollectionC
acheNS.size() != 1) |
| 325 return false; | 281 return false; |
| 326 ownerNode->clearNodeLists(); | 282 ownerNode->clearNodeLists(); |
| 327 return true; | 283 return true; |
| 328 } | 284 } |
| 329 | 285 |
| 330 // Ensure the 10 bits reserved for the m_connectedFrameCount cannot overflow | 286 // Ensure the 10 bits reserved for the m_connectedFrameCount cannot overflow |
| 331 COMPILE_ASSERT(Page::maxNumberOfFrames < 1024, Frame_limit_should_fit_in_rare_da
ta_count); | 287 COMPILE_ASSERT(Page::maxNumberOfFrames < 1024, Frame_limit_should_fit_in_rare_da
ta_count); |
| 332 | 288 |
| 333 } // namespace WebCore | 289 } // namespace WebCore |
| 334 | 290 |
| 335 #endif // NodeRareData_h | 291 #endif // NodeRareData_h |
| OLD | NEW |