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 |