Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: Source/core/css/RuleSet.cpp

Issue 17314010: RuleSet causes 600 kB of memory fragmentation (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address reviewer feedback Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/css/RuleSet.h ('k') | Source/wtf/LinkedStack.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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)
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(), ensurePendingRules()->idRules, r uleData);
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(), ensurePendingRules()->classRules , ruleData);
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(), ensurePendingRules()->shadowPseu doElementRules, 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
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(), ensurePending Rules()->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;
265 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); 264 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags);
266 collectFeaturesFromRuleData(m_features, ruleData); 265 collectFeaturesFromRuleData(m_features, ruleData);
267 266
268 if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { 267 if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) {
269 // If we didn't find a specialized map to stick it in, file under univer sal rules. 268 // If we didn't find a specialized map to stick it in, file under univer sal rules.
270 m_universalRules.append(ruleData); 269 m_universalRules.append(ruleData);
271 } 270 }
272 } 271 }
273 272
274 void RuleSet::addPageRule(StyleRulePage* rule) 273 void RuleSet::addPageRule(StyleRulePage* rule)
275 { 274 {
276 m_hasDirtyRules = true; 275 ensurePendingRules(); // So that m_pageRules.shrinkToFit() gets called.
277 m_pageRules.append(rule); 276 m_pageRules.append(rule);
278 } 277 }
279 278
280 void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit yOrigin) 279 void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit yOrigin)
281 { 280 {
282 m_hasDirtyRules = true; 281 ensurePendingRules(); // So that m_regionSelectorsAndRuleSets.shrinkToFit() gets called.
283 OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); 282 OwnPtr<RuleSet> regionRuleSet = RuleSet::create();
284 // The region rule set should take into account the position inside the pare nt rule set. 283 // 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 284 // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from
286 // the stylesheet that contains the region block. 285 // the stylesheet that contains the region block.
287 regionRuleSet->m_ruleCount = m_ruleCount; 286 regionRuleSet->m_ruleCount = m_ruleCount;
288 287
289 // Collect the region rules into a rule set 288 // Collect the region rules into a rule set
290 // FIXME: Should this add other types of rules? (i.e. use addChildRules() di rectly?) 289 // FIXME: Should this add other types of rules? (i.e. use addChildRules() di rectly?)
291 const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); 290 const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules();
292 AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecur ityOrigin : RuleHasNoSpecialState; 291 AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecur ityOrigin : RuleHasNoSpecialState;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 371
373 addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecur ityOrigin, addRuleFlags); 372 addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecur ityOrigin, addRuleFlags);
374 } 373 }
375 374
376 void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) 375 void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags)
377 { 376 {
378 for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = ru le->selectorList().indexOfNextSelectorAfter(selectorIndex)) 377 for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = ru le->selectorList().indexOfNextSelectorAfter(selectorIndex))
379 addRule(rule, selectorIndex, addRuleFlags); 378 addRule(rule, selectorIndex, addRuleFlags);
380 } 379 }
381 380
382 void RuleSet::shrinkMapVectorsToFit(AtomRuleMap& map) 381 void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& co mpactMap)
383 { 382 {
384 RuleSet::AtomRuleMap::iterator end = map.end(); 383 PendingRuleMap::iterator end = pendingMap.end();
385 for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it) 384 for (PendingRuleMap::iterator it = pendingMap.begin(); it != end; ++it) {
386 it->value->shrinkToFit(); 385 OwnPtr<LinkedStack<RuleData> > pendingRules = it->value.release();
386 size_t pendingSize = pendingRules->size();
387 ASSERT(pendingSize);
388
389 OwnPtr<Vector<RuleData> >& compactRules = compactMap.add(it->key, nullpt r).iterator->value;
390 if (!compactRules) {
391 compactRules = adoptPtr(new Vector<RuleData>);
392 compactRules->reserveInitialCapacity(pendingSize);
393 } else {
394 compactRules->reserveCapacity(compactRules->size() + pendingSize);
395 }
396
397 while (!pendingRules->isEmpty()) {
398 compactRules->append(pendingRules->peek());
399 pendingRules->pop();
400 }
401
402 ASSERT(compactRules->size() == compactRules->capacity());
403 }
387 } 404 }
388 405
389 void RuleSet::shrinkToFit() 406 void RuleSet::compactRules()
390 { 407 {
391 m_hasDirtyRules = false; 408 ASSERT(m_pendingRules);
392 shrinkMapVectorsToFit(m_idRules); 409 OwnPtr<PendingRuleMaps> pendingRules = m_pendingRules.release();
393 shrinkMapVectorsToFit(m_classRules); 410 compactPendingRules(pendingRules->idRules, m_idRules);
394 shrinkMapVectorsToFit(m_tagRules); 411 compactPendingRules(pendingRules->classRules, m_classRules);
395 shrinkMapVectorsToFit(m_shadowPseudoElementRules); 412 compactPendingRules(pendingRules->tagRules, m_tagRules);
413 compactPendingRules(pendingRules->shadowPseudoElementRules, m_shadowPseudoEl ementRules);
396 m_linkPseudoClassRules.shrinkToFit(); 414 m_linkPseudoClassRules.shrinkToFit();
397 m_cuePseudoRules.shrinkToFit(); 415 m_cuePseudoRules.shrinkToFit();
398 m_focusPseudoClassRules.shrinkToFit(); 416 m_focusPseudoClassRules.shrinkToFit();
399 m_universalRules.shrinkToFit(); 417 m_universalRules.shrinkToFit();
400 m_pageRules.shrinkToFit(); 418 m_pageRules.shrinkToFit();
401 } 419 }
402 420
403 } // namespace WebCore 421 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/css/RuleSet.h ('k') | Source/wtf/LinkedStack.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698