Chromium Code Reviews| 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(); |