Index: Source/core/dom/DocumentOrderedMap.cpp |
diff --git a/Source/core/dom/DocumentOrderedMap.cpp b/Source/core/dom/DocumentOrderedMap.cpp |
index 494d266768f241b113a78fb0a0392cc89a72707b..7c7edc66a87bf198ca086b71f28a5e082d672c1c 100644 |
--- a/Source/core/dom/DocumentOrderedMap.cpp |
+++ b/Source/core/dom/DocumentOrderedMap.cpp |
@@ -65,7 +65,6 @@ inline bool keyMatchesLabelForAttribute(StringImpl* key, Element* element) |
void DocumentOrderedMap::clear() |
{ |
m_map.clear(); |
- m_duplicateCounts.clear(); |
} |
void DocumentOrderedMap::add(StringImpl* key, Element* element) |
@@ -73,29 +72,14 @@ void DocumentOrderedMap::add(StringImpl* key, Element* element) |
ASSERT(key); |
ASSERT(element); |
- if (!m_duplicateCounts.contains(key)) { |
- // Fast path. The key is not already in m_duplicateCounts, so we assume that it's |
- // also not already in m_map and try to add it. If that add succeeds, we're done. |
- Map::AddResult addResult = m_map.add(key, element); |
- if (addResult.isNewEntry) |
- return; |
- |
- // The add failed, so this key was already cached in m_map. |
- // There are multiple elements with this key. Remove the m_map |
- // cache for this key so get searches for it next time it is called. |
- m_map.remove(addResult.iterator); |
- m_duplicateCounts.add(key); |
- } else { |
- // There are multiple elements with this key. Remove the m_map |
- // cache for this key so get will search for it next time it is called. |
- Map::iterator cachedItem = m_map.find(key); |
- if (cachedItem != m_map.end()) { |
- m_map.remove(cachedItem); |
- m_duplicateCounts.add(key); |
- } |
- } |
+ Map::AddResult addResult = m_map.add(key, MapEntry(element)); |
+ if (addResult.isNewEntry) |
+ return; |
- m_duplicateCounts.add(key); |
+ MapEntry& entry = addResult.iterator->value; |
+ ASSERT(entry.count); |
+ entry.element = 0; |
+ entry.count++; |
} |
void DocumentOrderedMap::remove(StringImpl* key, Element* element) |
@@ -103,11 +87,20 @@ void DocumentOrderedMap::remove(StringImpl* key, Element* element) |
ASSERT(key); |
ASSERT(element); |
- Map::iterator cachedItem = m_map.find(key); |
- if (cachedItem != m_map.end() && cachedItem->value == element) |
- m_map.remove(cachedItem); |
- else |
- m_duplicateCounts.remove(key); |
+ Map::iterator it = m_map.find(key); |
+ if (it == m_map.end()) |
Inactive
2013/12/17 15:34:50
This is the fix for the clusterfuzz crash. We need
|
+ return; |
+ |
+ MapEntry& entry = it->value; |
+ ASSERT(entry.count); |
+ if (entry.count == 1) { |
+ ASSERT(!entry.element || entry.element == element); |
+ m_map.remove(it); |
+ } else { |
+ if (entry.element == element) |
+ entry.element = 0; |
+ entry.count--; |
+ } |
} |
template<bool keyMatches(StringImpl*, Element*)> |
@@ -116,23 +109,23 @@ inline Element* DocumentOrderedMap::get(StringImpl* key, const TreeScope* scope) |
ASSERT(key); |
ASSERT(scope); |
- Element* element = m_map.get(key); |
- if (element) |
- return element; |
+ Map::iterator it = m_map.find(key); |
+ if (it == m_map.end()) |
+ return 0; |
- if (m_duplicateCounts.contains(key)) { |
- // We know there's at least one node that matches; iterate to find the first one. |
- ASSERT(scope->rootNode()); |
- for (element = ElementTraversal::firstWithin(*scope->rootNode()); element; element = ElementTraversal::next(*element)) { |
- if (!keyMatches(key, element)) |
- continue; |
- m_duplicateCounts.remove(key); |
- m_map.set(key, element); |
- return element; |
- } |
- ASSERT_NOT_REACHED(); |
- } |
+ MapEntry& entry = it->value; |
+ ASSERT(entry.count); |
+ if (entry.element) |
+ return entry.element; |
+ // We know there's at least one node that matches; iterate to find the first one. |
+ for (Element* element = ElementTraversal::firstWithin(*scope->rootNode()); element; element = ElementTraversal::next(*element)) { |
+ if (!keyMatches(key, element)) |
+ continue; |
+ entry.element = element; |
+ return element; |
+ } |
+ ASSERT_NOT_REACHED(); |
return 0; |
} |