Index: Source/core/css/RuleSet.cpp |
diff --git a/Source/core/css/RuleSet.cpp b/Source/core/css/RuleSet.cpp |
index 51f43585a4fad5c2fc32dd7638611769569fa068..1d65069deb97a46d731988ce5e7f858528e73cb8 100644 |
--- a/Source/core/css/RuleSet.cpp |
+++ b/Source/core/css/RuleSet.cpp |
@@ -130,9 +130,80 @@ static inline PropertyWhitelistType determinePropertyWhitelistType(const AddRule |
return PropertyWhitelistNone; |
} |
+namespace { |
+ |
+// FIXME: Should we move this class to WTF? |
+template<typename T> |
+class TerminatedArrayBuilder { |
+public: |
+ explicit TerminatedArrayBuilder(PassOwnPtr<T> array) |
+ : m_array(array) |
+ , m_count(0) |
+ , m_capacity(0) |
+ { |
+ if (!m_array) |
+ return; |
+ for (T* item = m_array.get(); !item->isLastInArray(); ++item) |
+ ++m_count; |
+ ++m_count; // To count the last item itself. |
+ m_capacity = m_count; |
+ } |
+ |
+ void grow(size_t count) |
+ { |
+ ASSERT(count); |
+ if (!m_array) { |
+ ASSERT(!m_count); |
+ ASSERT(!m_capacity); |
+ m_capacity = count; |
+ m_array = adoptPtr(static_cast<T*>(fastMalloc(m_capacity * sizeof(T)))); |
+ return; |
+ } |
+ m_capacity += count; |
+ m_array = adoptPtr(static_cast<T*>(fastRealloc(m_array.leakPtr(), m_capacity * sizeof(T)))); |
+ m_array.get()[m_count - 1].setLastInArray(false); |
+ } |
+ |
+ void append(const T& item) |
+ { |
+ RELEASE_ASSERT(m_count < m_capacity); |
+ ASSERT(!item.isLastInArray()); |
+ m_array.get()[m_count++] = item; |
+ } |
+ |
+ PassOwnPtr<T> release() |
+ { |
+ RELEASE_ASSERT(m_count == m_capacity); |
+ if (m_array) |
+ m_array.get()[m_count - 1].setLastInArray(true); |
+ assertValid(); |
+ return m_array.release(); |
+ } |
+ |
+private: |
+#ifndef NDEBUG |
+ void assertValid() |
+ { |
+ for (size_t i = 0; i < m_count; ++i) { |
+ bool isLastInArray = (i + 1 == m_count); |
+ ASSERT(m_array.get()[i].isLastInArray() == isLastInArray); |
+ } |
+ } |
+#else |
+ void assertValid() { } |
+#endif |
+ |
+ OwnPtr<T> m_array; |
+ size_t m_count; |
+ size_t m_capacity; |
+}; |
+ |
+} |
+ |
RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags) |
: m_rule(rule) |
, m_selectorIndex(selectorIndex) |
+ , m_isLastInArray(false) |
, m_position(position) |
, m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorCheckerFastPath::canUse(selector())) |
, m_specificity(selector()->specificity()) |
@@ -381,21 +452,16 @@ void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& co |
PendingRuleMap::iterator end = pendingMap.end(); |
for (PendingRuleMap::iterator it = pendingMap.begin(); it != end; ++it) { |
OwnPtr<LinkedStack<RuleData> > pendingRules = it->value.release(); |
- size_t pendingSize = pendingRules->size(); |
- ASSERT(pendingSize); |
- |
- OwnPtr<Vector<RuleData> >& compactRules = compactMap.add(it->key, nullptr).iterator->value; |
- if (!compactRules) { |
- compactRules = adoptPtr(new Vector<RuleData>); |
- compactRules->reserveInitialCapacity(pendingSize); |
- } else { |
- compactRules->reserveCapacity(compactRules->size() + pendingSize); |
- } |
+ CompactRuleMap::iterator compactRules = compactMap.add(it->key, nullptr).iterator; |
+ TerminatedArrayBuilder<RuleData> builder(compactRules->value.release()); |
+ builder.grow(pendingRules->size()); |
while (!pendingRules->isEmpty()) { |
- compactRules->append(pendingRules->peek()); |
+ builder.append(pendingRules->peek()); |
pendingRules->pop(); |
} |
+ |
+ compactRules->value = builder.release(); |
} |
} |