Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) | 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) |
| 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All r ights reserved. | 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All r ights reserved. |
| 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> | 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) |
| 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
| 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 } | 193 } |
| 194 } else if (!foundSiblingSelector && selector->isSiblingSelector()) | 194 } else if (!foundSiblingSelector && selector->isSiblingSelector()) |
| 195 foundSiblingSelector = true; | 195 foundSiblingSelector = true; |
| 196 } | 196 } |
| 197 if (foundSiblingSelector) | 197 if (foundSiblingSelector) |
| 198 features.siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selec torIndex(), ruleData.hasDocumentSecurityOrigin())); | 198 features.siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selec torIndex(), ruleData.hasDocumentSecurityOrigin())); |
| 199 if (ruleData.containsUncommonAttributeSelector()) | 199 if (ruleData.containsUncommonAttributeSelector()) |
| 200 features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), rule Data.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); | 200 features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), rule Data.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleDa ta& ruleData) | 203 void RuleSet::addToRuleSet(AtomicStringImpl* key, PendingRuleMap& map, const Rul eData& ruleData) |
| 204 { | 204 { |
| 205 if (!key) | 205 if (!key) |
| 206 return; | 206 return; |
| 207 OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).iterator->value; | 207 OwnPtr<LinkedStack<RuleData> >& rules = map.add(key, nullptr).iterator->valu e; |
| 208 if (!rules) | 208 if (!rules) |
| 209 rules = adoptPtr(new Vector<RuleData>); | 209 rules = adoptPtr(new LinkedStack<RuleData>); |
| 210 rules->append(ruleData); | 210 rules->push(ruleData); |
| 211 } | 211 } |
| 212 | 212 |
| 213 bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& rule Data) | 213 bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& rule Data) |
|
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
| |
| 214 { | 214 { |
| 215 if (component->m_match == CSSSelector::Id) { | 215 if (component->m_match == CSSSelector::Id) { |
| 216 addToRuleSet(component->value().impl(), m_idRules, ruleData); | 216 addToRuleSet(component->value().impl(), m_pendingRules->idRules, ruleDat a); |
| 217 return true; | 217 return true; |
| 218 } | 218 } |
| 219 if (component->m_match == CSSSelector::Class) { | 219 if (component->m_match == CSSSelector::Class) { |
| 220 addToRuleSet(component->value().impl(), m_classRules, ruleData); | 220 addToRuleSet(component->value().impl(), m_pendingRules->classRules, rule Data); |
| 221 return true; | 221 return true; |
| 222 } | 222 } |
| 223 if (component->isCustomPseudoElement()) { | 223 if (component->isCustomPseudoElement()) { |
| 224 addToRuleSet(component->value().impl(), m_shadowPseudoElementRules, rule Data); | 224 addToRuleSet(component->value().impl(), m_pendingRules->shadowPseudoElem entRules, ruleData); |
| 225 return true; | 225 return true; |
| 226 } | 226 } |
| 227 if (component->pseudoType() == CSSSelector::PseudoCue) { | 227 if (component->pseudoType() == CSSSelector::PseudoCue) { |
| 228 m_cuePseudoRules.append(ruleData); | 228 m_cuePseudoRules.append(ruleData); |
| 229 return true; | 229 return true; |
| 230 } | 230 } |
| 231 if (SelectorChecker::isCommonPseudoClassSelector(component)) { | 231 if (SelectorChecker::isCommonPseudoClassSelector(component)) { |
| 232 switch (component->pseudoType()) { | 232 switch (component->pseudoType()) { |
| 233 case CSSSelector::PseudoLink: | 233 case CSSSelector::PseudoLink: |
| 234 case CSSSelector::PseudoVisited: | 234 case CSSSelector::PseudoVisited: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 245 } | 245 } |
| 246 | 246 |
| 247 if (component->m_match == CSSSelector::Tag) { | 247 if (component->m_match == CSSSelector::Tag) { |
| 248 if (component->tagQName().localName() != starAtom) { | 248 if (component->tagQName().localName() != starAtom) { |
| 249 // If this is part of a subselector chain, recurse ahead to find a n arrower set (ID/class.) | 249 // If this is part of a subselector chain, recurse ahead to find a n arrower set (ID/class.) |
| 250 if (component->relation() == CSSSelector::SubSelector | 250 if (component->relation() == CSSSelector::SubSelector |
| 251 && (component->tagHistory()->m_match == CSSSelector::Class || co mponent->tagHistory()->m_match == CSSSelector::Id || SelectorChecker::isCommonPs eudoClassSelector(component->tagHistory())) | 251 && (component->tagHistory()->m_match == CSSSelector::Class || co mponent->tagHistory()->m_match == CSSSelector::Id || SelectorChecker::isCommonPs eudoClassSelector(component->tagHistory())) |
| 252 && findBestRuleSetAndAdd(component->tagHistory(), ruleData)) | 252 && findBestRuleSetAndAdd(component->tagHistory(), ruleData)) |
| 253 return true; | 253 return true; |
| 254 | 254 |
| 255 addToRuleSet(component->tagQName().localName().impl(), m_tagRules, r uleData); | 255 addToRuleSet(component->tagQName().localName().impl(), m_pendingRule s->tagRules, ruleData); |
| 256 return true; | 256 return true; |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 return false; | 259 return false; |
| 260 } | 260 } |
| 261 | 261 |
| 262 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addR uleFlags) | 262 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addR uleFlags) |
| 263 { | 263 { |
| 264 m_hasDirtyRules = true; | 264 ensurePendingRules(); |
| 265 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); | 265 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); |
| 266 collectFeaturesFromRuleData(m_features, ruleData); | 266 collectFeaturesFromRuleData(m_features, ruleData); |
| 267 | 267 |
| 268 if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { | 268 if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { |
| 269 // If we didn't find a specialized map to stick it in, file under univer sal rules. | 269 // If we didn't find a specialized map to stick it in, file under univer sal rules. |
| 270 m_universalRules.append(ruleData); | 270 m_universalRules.append(ruleData); |
| 271 } | 271 } |
| 272 } | 272 } |
| 273 | 273 |
| 274 void RuleSet::addPageRule(StyleRulePage* rule) | 274 void RuleSet::addPageRule(StyleRulePage* rule) |
| 275 { | 275 { |
| 276 m_hasDirtyRules = true; | 276 ensurePendingRules(); |
| 277 m_pageRules.append(rule); | 277 m_pageRules.append(rule); |
| 278 } | 278 } |
| 279 | 279 |
| 280 void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit yOrigin) | 280 void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit yOrigin) |
| 281 { | 281 { |
| 282 m_hasDirtyRules = true; | 282 ensurePendingRules(); |
| 283 OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); | 283 OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); |
| 284 // The region rule set should take into account the position inside the pare nt rule set. | 284 // The region rule set should take into account the position inside the pare nt rule set. |
| 285 // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from | 285 // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from |
| 286 // the stylesheet that contains the region block. | 286 // the stylesheet that contains the region block. |
| 287 regionRuleSet->m_ruleCount = m_ruleCount; | 287 regionRuleSet->m_ruleCount = m_ruleCount; |
| 288 | 288 |
| 289 // Collect the region rules into a rule set | 289 // Collect the region rules into a rule set |
| 290 // FIXME: Should this add other types of rules? (i.e. use addChildRules() di rectly?) | 290 // FIXME: Should this add other types of rules? (i.e. use addChildRules() di rectly?) |
| 291 const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); | 291 const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); |
| 292 AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecur ityOrigin : RuleHasNoSpecialState; | 292 AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecur ityOrigin : RuleHasNoSpecialState; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 372 | 372 |
| 373 addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecur ityOrigin, addRuleFlags); | 373 addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecur ityOrigin, addRuleFlags); |
| 374 } | 374 } |
| 375 | 375 |
| 376 void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) | 376 void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) |
| 377 { | 377 { |
| 378 for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = ru le->selectorList().indexOfNextSelectorAfter(selectorIndex)) | 378 for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = ru le->selectorList().indexOfNextSelectorAfter(selectorIndex)) |
| 379 addRule(rule, selectorIndex, addRuleFlags); | 379 addRule(rule, selectorIndex, addRuleFlags); |
| 380 } | 380 } |
| 381 | 381 |
| 382 void RuleSet::shrinkMapVectorsToFit(AtomRuleMap& map) | 382 void RuleSet::ensurePendingRules() |
| 383 { | 383 { |
| 384 RuleSet::AtomRuleMap::iterator end = map.end(); | 384 if (m_pendingRules) |
| 385 for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it) | 385 return; |
| 386 it->value->shrinkToFit(); | 386 m_pendingRules = adoptPtr(new PendingRuleMaps); |
| 387 } | 387 } |
| 388 | 388 |
| 389 void RuleSet::shrinkToFit() | 389 void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& co mpactMap) |
|
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
| |
| 390 { | 390 { |
| 391 m_hasDirtyRules = false; | 391 PendingRuleMap::iterator end = pendingMap.end(); |
| 392 shrinkMapVectorsToFit(m_idRules); | 392 for (PendingRuleMap::iterator it = pendingMap.begin(); it != end; ++it) { |
| 393 shrinkMapVectorsToFit(m_classRules); | 393 OwnPtr<LinkedStack<RuleData> > pendingRules = it->value.release(); |
| 394 shrinkMapVectorsToFit(m_tagRules); | 394 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
| |
| 395 shrinkMapVectorsToFit(m_shadowPseudoElementRules); | 395 ASSERT(pendingSize); |
| 396 | |
| 397 OwnPtr<Vector<RuleData> >& compactRules = compactMap.add(it->key, nullpt r).iterator->value; | |
| 398 if (!compactRules) { | |
| 399 compactRules = adoptPtr(new Vector<RuleData>); | |
| 400 compactRules->reserveInitialCapacity(pendingSize); | |
| 401 } else { | |
| 402 compactRules->reserveCapacity(pendingRules->size() + pendingSize); | |
| 403 } | |
| 404 | |
| 405 do { | |
| 406 compactRules->append(pendingRules->peek()); | |
| 407 pendingRules->pop(); | |
| 408 } 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...
| |
| 409 | |
| 410 ASSERT(compactRules->size() == compactRules->capacity()); | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 void RuleSet::compactRules() | |
| 415 { | |
| 416 OwnPtr<PendingRuleMaps> pendingRules = m_pendingRules.release(); | |
| 417 compactPendingRules(pendingRules->idRules, m_idRules); | |
| 418 compactPendingRules(pendingRules->classRules, m_classRules); | |
| 419 compactPendingRules(pendingRules->tagRules, m_tagRules); | |
| 420 compactPendingRules(pendingRules->shadowPseudoElementRules, m_shadowPseudoEl ementRules); | |
| 396 m_linkPseudoClassRules.shrinkToFit(); | 421 m_linkPseudoClassRules.shrinkToFit(); |
| 397 m_cuePseudoRules.shrinkToFit(); | 422 m_cuePseudoRules.shrinkToFit(); |
| 398 m_focusPseudoClassRules.shrinkToFit(); | 423 m_focusPseudoClassRules.shrinkToFit(); |
| 399 m_universalRules.shrinkToFit(); | 424 m_universalRules.shrinkToFit(); |
| 400 m_pageRules.shrinkToFit(); | 425 m_pageRules.shrinkToFit(); |
| 401 } | 426 } |
| 402 | 427 |
| 403 } // namespace WebCore | 428 } // namespace WebCore |
| OLD | NEW |