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

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

Issue 220943002: Use invalidation sets for :hover, :active, and :focus. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added layout tests Created 6 years, 8 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
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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 features.attributes.append(selector.attribute().localName()); 159 features.attributes.append(selector.attribute().localName());
160 else if (selector.isCustomPseudoElement()) 160 else if (selector.isCustomPseudoElement())
161 features.customPseudoElement = true; 161 features.customPseudoElement = true;
162 } 162 }
163 163
164 RuleFeatureSet::RuleFeatureSet() 164 RuleFeatureSet::RuleFeatureSet()
165 : m_targetedStyleRecalcEnabled(RuntimeEnabledFeatures::targetedStyleRecalcEn abled()) 165 : m_targetedStyleRecalcEnabled(RuntimeEnabledFeatures::targetedStyleRecalcEn abled())
166 { 166 {
167 } 167 }
168 168
169 DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSS elector& selector) 169 DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSS elector& selector, bool seenCombinator)
170 { 170 {
171 if (selector.m_match == CSSSelector::Class) 171 if (selector.m_match == CSSSelector::Class)
172 return &ensureClassInvalidationSet(selector.value()); 172 return &ensureClassInvalidationSet(selector.value());
173 if (selector.isAttributeSelector()) 173 if (selector.isAttributeSelector())
174 return &ensureAttributeInvalidationSet(selector.attribute().localName()) ; 174 return &ensureAttributeInvalidationSet(selector.attribute().localName()) ;
175 if (selector.m_match == CSSSelector::Id) 175 if (selector.m_match == CSSSelector::Id)
176 return &ensureIdInvalidationSet(selector.value()); 176 return &ensureIdInvalidationSet(selector.value());
177 if (seenCombinator && selector.m_match == CSSSelector::PseudoClass) {
178 CSSSelector::PseudoType pseudo = selector.pseudoType();
179 if (pseudo == CSSSelector::PseudoHover || pseudo == CSSSelector::PseudoA ctive || pseudo == CSSSelector::PseudoFocus)
180 return &ensurePseudoInvalidationSet(pseudo);
181 }
177 return 0; 182 return 0;
178 } 183 }
179 184
180 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) 185 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector)
181 { 186 {
182 InvalidationSetMode mode = invalidationSetModeForSelector(selector); 187 InvalidationSetMode mode = invalidationSetModeForSelector(selector);
183 if (mode != AddFeatures) 188 if (mode != AddFeatures)
184 return mode; 189 return mode;
185 190
186 InvalidationSetFeatures features; 191 InvalidationSetFeatures features;
187 const CSSSelector* current = extractInvalidationSetFeatures(selector, featur es); 192 const CSSSelector* current = extractInvalidationSetFeatures(selector, featur es);
188 if (current) { 193 if (current) {
189 bool wholeSubtree = current->relation() == CSSSelector::DirectAdjacent | | current->relation() == CSSSelector::IndirectAdjacent; 194 bool wholeSubtree = current->relation() == CSSSelector::DirectAdjacent | | current->relation() == CSSSelector::IndirectAdjacent;
190 current = current->tagHistory(); 195 current = current->tagHistory();
191 if (current) 196 if (current)
192 addFeaturesToInvalidationSets(*current, features, wholeSubtree); 197 addFeaturesToInvalidationSets(*current, features, wholeSubtree);
193 } 198 }
194 return AddFeatures; 199 return AddFeatures;
195 } 200 }
196 201
197 const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec tor& selector, InvalidationSetFeatures& features) 202 const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec tor& selector, InvalidationSetFeatures& features)
198 { 203 {
199 const CSSSelector* lastSelector = &selector; 204 const CSSSelector* lastSelector = &selector;
200 for (; lastSelector; lastSelector = lastSelector->tagHistory()) { 205 for (; lastSelector; lastSelector = lastSelector->tagHistory()) {
201 extractInvalidationSetFeature(*lastSelector, features); 206 extractInvalidationSetFeature(*lastSelector, features);
202 // Initialize the entry in the invalidation set map, if supported. 207 // Initialize the entry in the invalidation set map, if supported.
203 invalidationSetForSelector(*lastSelector); 208 invalidationSetForSelector(*lastSelector, false);
204 if (lastSelector->pseudoType() == CSSSelector::PseudoHost || lastSelecto r->pseudoType() == CSSSelector::PseudoAny) { 209 if (lastSelector->pseudoType() == CSSSelector::PseudoHost || lastSelecto r->pseudoType() == CSSSelector::PseudoAny) {
205 if (const CSSSelectorList* selectorList = lastSelector->selectorList ()) { 210 if (const CSSSelectorList* selectorList = lastSelector->selectorList ()) {
206 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) 211 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector))
207 extractInvalidationSetFeatures(*selector, features); 212 extractInvalidationSetFeatures(*selector, features);
208 } 213 }
209 } 214 }
210 215
211 if (lastSelector->relation() != CSSSelector::SubSelector) 216 if (lastSelector->relation() != CSSSelector::SubSelector)
212 break; 217 break;
213 } 218 }
214 return lastSelector; 219 return lastSelector;
215 } 220 }
216 221
217 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, const InvalidationSetFeatures& features, bool wholeSubtree) 222 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, const InvalidationSetFeatures& features, bool wholeSubtree)
218 { 223 {
219 for (const CSSSelector* current = &selector; current; current = current->tag History()) { 224 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
220 if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelec tor(*current)) { 225 if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelec tor(*current, true)) {
221 if (wholeSubtree) { 226 if (wholeSubtree) {
222 invalidationSet->setWholeSubtreeInvalid(); 227 invalidationSet->setWholeSubtreeInvalid();
223 } else { 228 } else {
224 if (!features.id.isEmpty()) 229 if (!features.id.isEmpty())
225 invalidationSet->addId(features.id); 230 invalidationSet->addId(features.id);
226 if (!features.tagName.isEmpty()) 231 if (!features.tagName.isEmpty())
227 invalidationSet->addTagName(features.tagName); 232 invalidationSet->addTagName(features.tagName);
228 for (Vector<AtomicString>::const_iterator it = features.classes. begin(); it != features.classes.end(); ++it) 233 for (Vector<AtomicString>::const_iterator it = features.classes. begin(); it != features.classes.end(); ++it)
229 invalidationSet->addClass(*it); 234 invalidationSet->addClass(*it);
230 for (Vector<AtomicString>::const_iterator it = features.attribut es.begin(); it != features.attributes.end(); ++it) 235 for (Vector<AtomicString>::const_iterator it = features.attribut es.begin(); it != features.attributes.end(); ++it)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 invalidationSet.setWholeSubtreeInvalid(); 270 invalidationSet.setWholeSubtreeInvalid();
266 } 271 }
267 272
268 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) 273 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData)
269 { 274 {
270 FeatureMetadata metadata; 275 FeatureMetadata metadata;
271 InvalidationSetMode mode = UseSubtreeStyleChange; 276 InvalidationSetMode mode = UseSubtreeStyleChange;
272 if (m_targetedStyleRecalcEnabled) 277 if (m_targetedStyleRecalcEnabled)
273 mode = updateInvalidationSets(ruleData.selector()); 278 mode = updateInvalidationSets(ruleData.selector());
274 279
275 collectFeaturesFromSelector(ruleData.selector(), metadata, mode); 280 collectFeaturesFromSelector(ruleData.selector(), metadata, mode, false);
276 m_metadata.add(metadata); 281 m_metadata.add(metadata);
277 282
278 if (metadata.foundSiblingSelector) 283 if (metadata.foundSiblingSelector)
279 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin())); 284 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin()));
280 if (ruleData.containsUncommonAttributeSelector()) 285 if (ruleData.containsUncommonAttributeSelector())
281 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin())); 286 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin()));
282 } 287 }
283 288
284 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className) 289 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className)
285 { 290 {
(...skipping 12 matching lines...) Expand all
298 } 303 }
299 304
300 DescendantInvalidationSet& RuleFeatureSet::ensureIdInvalidationSet(const AtomicS tring& id) 305 DescendantInvalidationSet& RuleFeatureSet::ensureIdInvalidationSet(const AtomicS tring& id)
301 { 306 {
302 InvalidationSetMap::AddResult addResult = m_idInvalidationSets.add(id, nullp tr); 307 InvalidationSetMap::AddResult addResult = m_idInvalidationSets.add(id, nullp tr);
303 if (addResult.isNewEntry) 308 if (addResult.isNewEntry)
304 addResult.storedValue->value = DescendantInvalidationSet::create(); 309 addResult.storedValue->value = DescendantInvalidationSet::create();
305 return *addResult.storedValue->value; 310 return *addResult.storedValue->value;
306 } 311 }
307 312
313 DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelect or::PseudoType pseudoType)
314 {
315 PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets .add(pseudoType, nullptr);
316 if (addResult.isNewEntry)
317 addResult.storedValue->value = DescendantInvalidationSet::create();
318 return *addResult.storedValue->value;
319 }
320
308 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) 321 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector)
309 { 322 {
310 collectFeaturesFromSelector(selector, m_metadata, UseSubtreeStyleChange); 323 collectFeaturesFromSelector(selector, m_metadata, UseSubtreeStyleChange, fal se);
311 } 324 }
312 325
313 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) 326 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode, bool seenComb inator)
314 { 327 {
315 unsigned maxDirectAdjacentSelectors = 0; 328 unsigned maxDirectAdjacentSelectors = 0;
316 329
317 for (const CSSSelector* current = &selector; current; current = current->tag History()) { 330 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
318 if (mode != AddFeatures && (current->m_match == CSSSelector::Class || cu rrent->m_match == CSSSelector::Id || current->isAttributeSelector())) { 331 if (mode != AddFeatures) {
319 DescendantInvalidationSet* invalidationSet = invalidationSetForSelec tor(*current); 332 if (DescendantInvalidationSet* invalidationSet = invalidationSetForS elector(*current, seenCombinator)) {
320 ASSERT(invalidationSet); 333 if (mode == UseSubtreeStyleChange)
321 if (mode == UseSubtreeStyleChange) 334 invalidationSet->setWholeSubtreeInvalid();
322 invalidationSet->setWholeSubtreeInvalid(); 335 }
323 } 336 }
324 if (current->pseudoType() == CSSSelector::PseudoFirstLine) 337 if (current->pseudoType() == CSSSelector::PseudoFirstLine)
325 metadata.usesFirstLineRules = true; 338 metadata.usesFirstLineRules = true;
326 if (current->isDirectAdjacentSelector()) { 339 if (current->isDirectAdjacentSelector()) {
327 maxDirectAdjacentSelectors++; 340 maxDirectAdjacentSelectors++;
328 } else if (maxDirectAdjacentSelectors) { 341 } else if (maxDirectAdjacentSelectors) {
329 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors ) 342 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors )
330 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ; 343 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ;
331 maxDirectAdjacentSelectors = 0; 344 maxDirectAdjacentSelectors = 0;
332 } 345 }
333 if (current->isSiblingSelector()) 346 if (current->isSiblingSelector())
334 metadata.foundSiblingSelector = true; 347 metadata.foundSiblingSelector = true;
335 348
336 collectFeaturesFromSelectorList(current->selectorList(), metadata, mode) ; 349 collectFeaturesFromSelectorList(current->selectorList(), metadata, mode, seenCombinator);
337 350
338 if (mode == UseLocalStyleChange && current->relation() != CSSSelector::S ubSelector) 351 if (mode == UseLocalStyleChange && current->relation() != CSSSelector::S ubSelector) {
352 seenCombinator = true;
339 mode = UseSubtreeStyleChange; 353 mode = UseSubtreeStyleChange;
354 }
340 } 355 }
341 356
342 ASSERT(!maxDirectAdjacentSelectors); 357 ASSERT(!maxDirectAdjacentSelectors);
343 } 358 }
344 359
345 void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* sele ctorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) 360 void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* sele ctorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode, b ool seenCombinator)
346 { 361 {
347 if (!selectorList) 362 if (!selectorList)
348 return; 363 return;
349 364
350 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) 365 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector))
351 collectFeaturesFromSelector(*selector, metadata, mode); 366 collectFeaturesFromSelector(*selector, metadata, mode, seenCombinator);
352 } 367 }
353 368
354 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) 369 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other)
355 { 370 {
356 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; 371 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
357 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors); 372 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors);
358 } 373 }
359 374
360 void RuleFeatureSet::FeatureMetadata::clear() 375 void RuleFeatureSet::FeatureMetadata::clear()
361 { 376 {
362 usesFirstLineRules = false; 377 usesFirstLineRules = false;
363 foundSiblingSelector = false; 378 foundSiblingSelector = false;
364 maxDirectAdjacentSelectors = 0; 379 maxDirectAdjacentSelectors = 0;
365 } 380 }
366 381
367 void RuleFeatureSet::add(const RuleFeatureSet& other) 382 void RuleFeatureSet::add(const RuleFeatureSet& other)
368 { 383 {
369 for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.b egin(); it != other.m_classInvalidationSets.end(); ++it) 384 for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.b egin(); it != other.m_classInvalidationSets.end(); ++it)
370 ensureClassInvalidationSet(it->key).combine(*it->value); 385 ensureClassInvalidationSet(it->key).combine(*it->value);
371 for (InvalidationSetMap::const_iterator it = other.m_attributeInvalidationSe ts.begin(); it != other.m_attributeInvalidationSets.end(); ++it) 386 for (InvalidationSetMap::const_iterator it = other.m_attributeInvalidationSe ts.begin(); it != other.m_attributeInvalidationSets.end(); ++it)
372 ensureAttributeInvalidationSet(it->key).combine(*it->value); 387 ensureAttributeInvalidationSet(it->key).combine(*it->value);
373 for (InvalidationSetMap::const_iterator it = other.m_idInvalidationSets.begi n(); it != other.m_idInvalidationSets.end(); ++it) 388 for (InvalidationSetMap::const_iterator it = other.m_idInvalidationSets.begi n(); it != other.m_idInvalidationSets.end(); ++it)
374 ensureIdInvalidationSet(it->key).combine(*it->value); 389 ensureIdInvalidationSet(it->key).combine(*it->value);
390 for (PseudoTypeInvalidationSetMap::const_iterator it = other.m_pseudoInvalid ationSets.begin(); it != other.m_pseudoInvalidationSets.end(); ++it)
391 ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(it->key )).combine(*it->value);
esprehn 2014/04/11 20:23:01 Why do you need the cast?
rune 2014/04/11 22:34:36 It's because of the use of IntHash: typedef Has
375 392
376 m_metadata.add(other.m_metadata); 393 m_metadata.add(other.m_metadata);
377 394
378 siblingRules.appendVector(other.siblingRules); 395 siblingRules.appendVector(other.siblingRules);
379 uncommonAttributeRules.appendVector(other.uncommonAttributeRules); 396 uncommonAttributeRules.appendVector(other.uncommonAttributeRules);
380 } 397 }
381 398
382 void RuleFeatureSet::clear() 399 void RuleFeatureSet::clear()
383 { 400 {
384 siblingRules.clear(); 401 siblingRules.clear();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 if (!oldId.isEmpty()) { 462 if (!oldId.isEmpty()) {
446 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidation Sets.get(oldId)) 463 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidation Sets.get(oldId))
447 m_styleInvalidator.scheduleInvalidation(invalidationSet, element); 464 m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
448 } 465 }
449 if (!newId.isEmpty()) { 466 if (!newId.isEmpty()) {
450 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidation Sets.get(newId)) 467 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidation Sets.get(newId))
451 m_styleInvalidator.scheduleInvalidation(invalidationSet, element); 468 m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
452 } 469 }
453 } 470 }
454 471
472 void RuleFeatureSet::scheduleStyleInvalidationForPseudoChange(CSSSelector::Pseud oType pseudo, Element& element)
473 {
474 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_pseudoInvalidation Sets.get(pseudo))
475 m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
476 }
477
455 void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, El ement& element) 478 void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, El ement& element)
456 { 479 {
457 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationS ets.get(className)) 480 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationS ets.get(className))
458 m_styleInvalidator.scheduleInvalidation(invalidationSet, element); 481 m_styleInvalidator.scheduleInvalidation(invalidationSet, element);
459 } 482 }
460 483
461 StyleInvalidator& RuleFeatureSet::styleInvalidator() 484 StyleInvalidator& RuleFeatureSet::styleInvalidator()
462 { 485 {
463 return m_styleInvalidator; 486 return m_styleInvalidator;
464 } 487 }
465 488
466 } // namespace WebCore 489 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698