Index: Source/core/css/RuleSet.cpp |
diff --git a/Source/core/css/RuleSet.cpp b/Source/core/css/RuleSet.cpp |
index a08c06c7676b3fd6617e5eb3798d7bf6fe4e6724..3ea0504d4ebd207d96cd4ed8dbc0bf21049c1331 100644 |
--- a/Source/core/css/RuleSet.cpp |
+++ b/Source/core/css/RuleSet.cpp |
@@ -200,28 +200,28 @@ static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData |
features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); |
} |
-void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleData& ruleData) |
+void RuleSet::addToRuleSet(AtomicStringImpl* key, PendingRuleMap& map, const RuleData& ruleData) |
{ |
if (!key) |
return; |
- OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).iterator->value; |
+ OwnPtr<LinkedStack<RuleData> >& rules = map.add(key, nullptr).iterator->value; |
if (!rules) |
- rules = adoptPtr(new Vector<RuleData>); |
- rules->append(ruleData); |
+ rules = adoptPtr(new LinkedStack<RuleData>); |
+ rules->push(ruleData); |
} |
bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& ruleData) |
ojan
2013/06/20 22:38:45
Should we ASSERT(m_pendingRules) here and in other
abarth-chromium
2013/06/20 22:52:32
The ASSERT isn't really needed because the code wi
|
{ |
if (component->m_match == CSSSelector::Id) { |
- addToRuleSet(component->value().impl(), m_idRules, ruleData); |
+ addToRuleSet(component->value().impl(), m_pendingRules->idRules, ruleData); |
return true; |
} |
if (component->m_match == CSSSelector::Class) { |
- addToRuleSet(component->value().impl(), m_classRules, ruleData); |
+ addToRuleSet(component->value().impl(), m_pendingRules->classRules, ruleData); |
return true; |
} |
if (component->isCustomPseudoElement()) { |
- addToRuleSet(component->value().impl(), m_shadowPseudoElementRules, ruleData); |
+ addToRuleSet(component->value().impl(), m_pendingRules->shadowPseudoElementRules, ruleData); |
return true; |
} |
if (component->pseudoType() == CSSSelector::PseudoCue) { |
@@ -252,7 +252,7 @@ bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& rule |
&& findBestRuleSetAndAdd(component->tagHistory(), ruleData)) |
return true; |
- addToRuleSet(component->tagQName().localName().impl(), m_tagRules, ruleData); |
+ addToRuleSet(component->tagQName().localName().impl(), m_pendingRules->tagRules, ruleData); |
return true; |
} |
} |
@@ -261,7 +261,7 @@ bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& rule |
void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) |
{ |
- m_hasDirtyRules = true; |
+ ensurePendingRules(); |
RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); |
collectFeaturesFromRuleData(m_features, ruleData); |
@@ -273,13 +273,13 @@ void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addR |
void RuleSet::addPageRule(StyleRulePage* rule) |
{ |
- m_hasDirtyRules = true; |
+ ensurePendingRules(); |
m_pageRules.append(rule); |
} |
void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurityOrigin) |
{ |
- m_hasDirtyRules = true; |
+ ensurePendingRules(); |
OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); |
// The region rule set should take into account the position inside the parent rule set. |
// Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from |
@@ -379,20 +379,45 @@ void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) |
addRule(rule, selectorIndex, addRuleFlags); |
} |
-void RuleSet::shrinkMapVectorsToFit(AtomRuleMap& map) |
+void RuleSet::ensurePendingRules() |
{ |
- RuleSet::AtomRuleMap::iterator end = map.end(); |
- for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it) |
- it->value->shrinkToFit(); |
+ if (m_pendingRules) |
+ return; |
+ m_pendingRules = adoptPtr(new PendingRuleMaps); |
+} |
+ |
+void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& compactMap) |
esprehn
2013/06/20 22:29:52
nit: Why isn't this just static in the file? It do
abarth-chromium
2013/06/20 22:52:32
The PendingRuleMap and CompactRuleMap types are pr
|
+{ |
+ 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(); |
esprehn
2013/06/20 22:29:52
This is O(n), why not just keep the size of the li
abarth-chromium
2013/06/20 22:52:32
Sure, I can do that. My thinking was that we're g
|
+ 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(pendingRules->size() + pendingSize); |
+ } |
+ |
+ do { |
+ compactRules->append(pendingRules->peek()); |
+ pendingRules->pop(); |
+ } while (!pendingRules->isEmpty()); |
esprehn
2013/06/20 22:29:52
I think regular while would be more clear, I don't
abarth-chromium
2013/06/20 22:52:32
Will fix. I was excited to be able to use a do...
|
+ |
+ ASSERT(compactRules->size() == compactRules->capacity()); |
+ } |
} |
-void RuleSet::shrinkToFit() |
+void RuleSet::compactRules() |
{ |
- m_hasDirtyRules = false; |
- shrinkMapVectorsToFit(m_idRules); |
- shrinkMapVectorsToFit(m_classRules); |
- shrinkMapVectorsToFit(m_tagRules); |
- shrinkMapVectorsToFit(m_shadowPseudoElementRules); |
+ OwnPtr<PendingRuleMaps> pendingRules = m_pendingRules.release(); |
+ compactPendingRules(pendingRules->idRules, m_idRules); |
+ compactPendingRules(pendingRules->classRules, m_classRules); |
+ compactPendingRules(pendingRules->tagRules, m_tagRules); |
+ compactPendingRules(pendingRules->shadowPseudoElementRules, m_shadowPseudoElementRules); |
m_linkPseudoClassRules.shrinkToFit(); |
m_cuePseudoRules.shrinkToFit(); |
m_focusPseudoClassRules.shrinkToFit(); |