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

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

Issue 2326783002: Simplified compound feature extraction. (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « third_party/WebKit/Source/core/css/RuleFeature.h ('k') | no next file » | 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 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 // Given a rule, update the descendant invalidation sets for the features 432 // Given a rule, update the descendant invalidation sets for the features
433 // found in its selector. The first step is to extract the features from the 433 // found in its selector. The first step is to extract the features from the
434 // rightmost compound selector (extractInvalidationSetFeaturesFromCompound). 434 // rightmost compound selector (extractInvalidationSetFeaturesFromCompound).
435 // Secondly, add those features to the invalidation sets for the features 435 // Secondly, add those features to the invalidation sets for the features
436 // found in the other compound selectors (addFeaturesToInvalidationSets). If 436 // found in the other compound selectors (addFeaturesToInvalidationSets). If
437 // we find a feature in the right-most compound selector that requires a 437 // we find a feature in the right-most compound selector that requires a
438 // subtree recalc, nextCompound will be the rightmost compound and we will 438 // subtree recalc, nextCompound will be the rightmost compound and we will
439 // addFeaturesToInvalidationSets for that one as well. 439 // addFeaturesToInvalidationSets for that one as well.
440 440
441 InvalidationSetFeatures features; 441 InvalidationSetFeatures features;
442 const CSSSelector* nextCompound = extractInvalidationSetFeaturesFromCompound (ruleData.selector(), features, Subject); 442 InvalidationSetFeatures* siblingFeatures = nullptr;
443
444 const CSSSelector* lastInCompound = extractInvalidationSetFeaturesFromCompou nd(ruleData.selector(), features, Subject);
443 445
444 if (!features.hasFeatures()) 446 if (!features.hasFeatures())
445 features.forceSubtree = true; 447 features.forceSubtree = true;
446 448 if (features.hasNthPseudo)
447 if (nextCompound)
448 addFeaturesToInvalidationSets(*nextCompound, features);
449 else if (features.hasNthPseudo)
450 addFeaturesToInvalidationSet(ensureNthInvalidationSet(), features); 449 addFeaturesToInvalidationSet(ensureNthInvalidationSet(), features);
451
452 if (features.hasBeforeOrAfter) 450 if (features.hasBeforeOrAfter)
453 updateInvalidationSetsForContentAttribute(ruleData); 451 updateInvalidationSetsForContentAttribute(ruleData);
452
453 const CSSSelector* nextCompound = lastInCompound ? lastInCompound->tagHistor y() : &ruleData.selector();
454 if (!nextCompound)
455 return;
456 if (lastInCompound)
457 updateFeaturesFromCombinator(*lastInCompound, nullptr, features, sibling Features, features);
458
459 addFeaturesToInvalidationSets(*nextCompound, siblingFeatures, features);
454 } 460 }
455 461
456 void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& r uleData) 462 void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& r uleData)
457 { 463 {
458 // If any ::before and ::after rules specify 'content: attr(...)', we 464 // If any ::before and ::after rules specify 'content: attr(...)', we
459 // need to create invalidation sets for those attributes to have content 465 // need to create invalidation sets for those attributes to have content
460 // changes applied through style recalc. 466 // changes applied through style recalc.
461 467
462 const StylePropertySet& propertySet = ruleData.rule()->properties(); 468 const StylePropertySet& propertySet = ruleData.rule()->properties();
463 469
(...skipping 11 matching lines...) Expand all
475 for (auto& item : toCSSValueList(contentValue)) { 481 for (auto& item : toCSSValueList(contentValue)) {
476 if (!item->isFunctionValue()) 482 if (!item->isFunctionValue())
477 continue; 483 continue;
478 const CSSFunctionValue* functionValue = toCSSFunctionValue(item.get()); 484 const CSSFunctionValue* functionValue = toCSSFunctionValue(item.get());
479 if (functionValue->functionType() != CSSValueAttr) 485 if (functionValue->functionType() != CSSValueAttr)
480 continue; 486 continue;
481 ensureAttributeInvalidationSet(AtomicString(toCSSCustomIdentValue(functi onValue->item(0)).value()), InvalidateDescendants).setInvalidatesSelf(); 487 ensureAttributeInvalidationSet(AtomicString(toCSSCustomIdentValue(functi onValue->item(0)).value()), InvalidateDescendants).setInvalidatesSelf();
482 } 488 }
483 } 489 }
484 490
485 const CSSSelector* 491 RuleFeatureSet::FeatureInvalidationType
486 RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(const CSSSelector & simpleSelector, InvalidationSetFeatures& features, PositionType position) 492 RuleFeatureSet::extractInvalidationSetFeaturesFromSelectorList(const CSSSelector & simpleSelector, InvalidationSetFeatures& features, PositionType position)
487 { 493 {
488 const CSSSelectorList* selectorList = simpleSelector.selectorList(); 494 const CSSSelectorList* selectorList = simpleSelector.selectorList();
489 if (!selectorList) 495 if (!selectorList)
490 return nullptr; 496 return NormalInvalidation;
491 497
492 DCHECK(supportsInvalidationWithSelectorList(simpleSelector.getPseudoType())) ; 498 DCHECK(supportsInvalidationWithSelectorList(simpleSelector.getPseudoType())) ;
493 499
494 const CSSSelector* subSelector = selectorList->first(); 500 const CSSSelector* subSelector = selectorList->first();
495 501
496 bool allSubSelectorsHaveFeatures = true; 502 bool allSubSelectorsHaveFeatures = true;
497 InvalidationSetFeatures anyFeatures; 503 InvalidationSetFeatures anyFeatures;
498 504
499 for (; subSelector; subSelector = CSSSelectorList::next(*subSelector)) { 505 for (; subSelector; subSelector = CSSSelectorList::next(*subSelector)) {
500 InvalidationSetFeatures compoundFeatures; 506 InvalidationSetFeatures compoundFeatures;
501 if (extractInvalidationSetFeaturesFromCompound(*subSelector, compoundFea tures, position, simpleSelector.getPseudoType())) { 507 if (!extractInvalidationSetFeaturesFromCompound(*subSelector, compoundFe atures, position, simpleSelector.getPseudoType())) {
502 // A non-null selector return means the sub-selector contained a 508 // A null selector return means the sub-selector contained a
503 // selector which requiresSubtreeInvalidation(). 509 // selector which requiresSubtreeInvalidation().
504 DCHECK(compoundFeatures.forceSubtree); 510 DCHECK(compoundFeatures.forceSubtree);
505 features.forceSubtree = true; 511 features.forceSubtree = true;
506 return &simpleSelector; 512 return RequiresSubtreeInvalidation;
507 } 513 }
508 if (allSubSelectorsHaveFeatures && !compoundFeatures.hasFeatures()) 514 if (allSubSelectorsHaveFeatures && !compoundFeatures.hasFeatures())
509 allSubSelectorsHaveFeatures = false; 515 allSubSelectorsHaveFeatures = false;
510 else 516 else
511 anyFeatures.add(compoundFeatures); 517 anyFeatures.add(compoundFeatures);
512 if (compoundFeatures.hasNthPseudo) 518 if (compoundFeatures.hasNthPseudo)
513 features.hasNthPseudo = true; 519 features.hasNthPseudo = true;
514 } 520 }
515 // Don't add any features if one of the sub-selectors of does not contain 521 // Don't add any features if one of the sub-selectors of does not contain
516 // any invalidation set features. E.g. :-webkit-any(*, span). 522 // any invalidation set features. E.g. :-webkit-any(*, span).
517 if (allSubSelectorsHaveFeatures) 523 if (allSubSelectorsHaveFeatures)
518 features.add(anyFeatures); 524 features.add(anyFeatures);
519 return nullptr; 525 return NormalInvalidation;
520 } 526 }
521 527
522 const CSSSelector* 528 const CSSSelector*
523 RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(const CSSSelector& co mpound, InvalidationSetFeatures& features, PositionType position, CSSSelector::P seudoType pseudo) 529 RuleFeatureSet::extractInvalidationSetFeaturesFromCompound(const CSSSelector& co mpound, InvalidationSetFeatures& features, PositionType position, CSSSelector::P seudoType pseudo)
524 { 530 {
531 // Extract invalidation set features and return a pointer to the the last
532 // simple selector of the compound, or nullptr if one of the selectors
533 // requiresSubtreeInvalidation().
534
525 const CSSSelector* simpleSelector = &compound; 535 const CSSSelector* simpleSelector = &compound;
526 for (; simpleSelector; simpleSelector = simpleSelector->tagHistory()) { 536 for (; simpleSelector; simpleSelector = simpleSelector->tagHistory()) {
Eric Willigers 2016/09/11 23:58:03 Another option would be for (;; simpleSelector
rune 2016/09/12 08:01:58 Done.
527 537
528 // Fall back to use subtree invalidations, even for features in the 538 // Fall back to use subtree invalidations, even for features in the
529 // rightmost compound selector. Returning the start &selector here 539 // rightmost compound selector. Returning nullptr here will make
530 // will make addFeaturesToInvalidationSets start marking invalidation 540 // addFeaturesToInvalidationSets start marking invalidation sets for
531 // sets for subtree recalc for features in the rightmost compound 541 // subtree recalc for features in the rightmost compound selector.
532 // selector.
533 if (requiresSubtreeInvalidation(*simpleSelector)) { 542 if (requiresSubtreeInvalidation(*simpleSelector)) {
534 features.forceSubtree = true; 543 features.forceSubtree = true;
535 return &compound; 544 return nullptr;
536 } 545 }
537 546
538 // When inside a :not(), we should not use the found features for 547 // When inside a :not(), we should not use the found features for
539 // invalidation because we should invalidate elements _without_ that 548 // invalidation because we should invalidate elements _without_ that
540 // feature. On the other hand, we should still have invalidation sets 549 // feature. On the other hand, we should still have invalidation sets
541 // for the features since we are able to detect when they change. 550 // for the features since we are able to detect when they change.
542 // That is, ".a" should not have ".b" in its invalidation set for 551 // That is, ".a" should not have ".b" in its invalidation set for
543 // ".a :not(.b)", but there should be an invalidation set for ".a" in 552 // ".a :not(.b)", but there should be an invalidation set for ".a" in
544 // ":not(.a) .b". 553 // ":not(.a) .b".
545 if (pseudo != CSSSelector::PseudoNot) 554 if (pseudo != CSSSelector::PseudoNot)
546 extractInvalidationSetFeaturesFromSimpleSelector(*simpleSelector, fe atures); 555 extractInvalidationSetFeaturesFromSimpleSelector(*simpleSelector, fe atures);
547 556
548 // Initialize the entry in the invalidation set map for self- 557 // Initialize the entry in the invalidation set map for self-
549 // invalidation, if supported. 558 // invalidation, if supported.
550 if (InvalidationSet* invalidationSet = invalidationSetForSimpleSelector( *simpleSelector, InvalidateDescendants)) { 559 if (InvalidationSet* invalidationSet = invalidationSetForSimpleSelector( *simpleSelector, InvalidateDescendants)) {
551 if (invalidationSet == m_nthInvalidationSet) 560 if (invalidationSet == m_nthInvalidationSet)
552 features.hasNthPseudo = true; 561 features.hasNthPseudo = true;
553 else if (position == Subject) 562 else if (position == Subject)
554 invalidationSet->setInvalidatesSelf(); 563 invalidationSet->setInvalidatesSelf();
555 } 564 }
556 565
557 if (extractInvalidationSetFeaturesFromSelectorList(*simpleSelector, feat ures, position)) { 566 if (extractInvalidationSetFeaturesFromSelectorList(*simpleSelector, feat ures, position) == RequiresSubtreeInvalidation) {
558 DCHECK(features.forceSubtree); 567 DCHECK(features.forceSubtree);
559 return &compound; 568 return nullptr;
560 } 569 }
561 570
562 if (simpleSelector->relation() == CSSSelector::SubSelector) 571 if (!simpleSelector->tagHistory())
563 continue; 572 break;
564 573 if (simpleSelector->relation() != CSSSelector::SubSelector)
565 if (position == Subject) { 574 break;
566 if (features.hasNthPseudo) {
567 DCHECK(m_nthInvalidationSet);
568 if (features.hasFeatures())
569 addFeaturesToInvalidationSet(*m_nthInvalidationSet, features );
570 else
571 m_nthInvalidationSet->setWholeSubtreeInvalid();
572 }
573 InvalidationSetFeatures* siblingFeatures = nullptr;
574 updateFeaturesFromCombinator(*simpleSelector, nullptr, features, sib lingFeatures, features);
575 }
576 return simpleSelector->tagHistory();
577 } 575 }
578 576
579 return nullptr; 577 DCHECK(simpleSelector);
578 return simpleSelector;
580 } 579 }
581 580
582 // Add features extracted from the rightmost compound selector to descendant inv alidation 581 // Add features extracted from the rightmost compound selector to descendant inv alidation
583 // sets for features found in other compound selectors. 582 // sets for features found in other compound selectors.
584 // 583 //
585 // We use descendant invalidation for descendants, sibling invalidation for sibl ings and their subtrees. 584 // We use descendant invalidation for descendants, sibling invalidation for sibl ings and their subtrees.
586 // 585 //
587 // As we encounter a descendant type of combinator, the features only need to be checked 586 // As we encounter a descendant type of combinator, the features only need to be checked
588 // against descendants in the same subtree only. features.adjacent is set to fal se, and 587 // against descendants in the same subtree only. features.adjacent is set to fal se, and
589 // we start adding features to the descendant invalidation set. 588 // we start adding features to the descendant invalidation set.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 if (!simpleSelector->tagHistory()) 663 if (!simpleSelector->tagHistory())
665 break; 664 break;
666 } 665 }
667 666
668 if (siblingFeatures && !compoundHasIdClassOrAttribute) 667 if (siblingFeatures && !compoundHasIdClassOrAttribute)
669 addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures, descendan tFeatures); 668 addFeaturesToUniversalSiblingInvalidationSet(*siblingFeatures, descendan tFeatures);
670 669
671 return simpleSelector; 670 return simpleSelector;
672 } 671 }
673 672
674 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& descendantFeatures) 673 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures* siblingFeatures, InvalidationSetFeatures& descendantFea tures)
675 { 674 {
676 // selector is the selector immediately to the left of the rightmost combina tor. 675 // selector is the selector immediately to the left of the rightmost combina tor.
677 // descendantFeatures has the features of the rightmost compound selector. 676 // descendantFeatures has the features of the rightmost compound selector.
678 677
679 InvalidationSetFeatures lastCompoundInSiblingChainFeatures; 678 InvalidationSetFeatures lastCompoundInSiblingChainFeatures;
680 InvalidationSetFeatures* siblingFeatures = descendantFeatures.maxDirectAdjac entSelectors ? &descendantFeatures : nullptr;
681
682 const CSSSelector* compound = &selector; 679 const CSSSelector* compound = &selector;
683 while (compound) { 680 while (compound) {
684 const CSSSelector* lastInCompound = addFeaturesToInvalidationSetsForComp oundSelector(*compound, siblingFeatures, descendantFeatures); 681 const CSSSelector* lastInCompound = addFeaturesToInvalidationSetsForComp oundSelector(*compound, siblingFeatures, descendantFeatures);
685 DCHECK(lastInCompound); 682 DCHECK(lastInCompound);
686 updateFeaturesFromCombinator(*lastInCompound, compound, lastCompoundInSi blingChainFeatures, siblingFeatures, descendantFeatures); 683 updateFeaturesFromCombinator(*lastInCompound, compound, lastCompoundInSi blingChainFeatures, siblingFeatures, descendantFeatures);
687 compound = lastInCompound->tagHistory(); 684 compound = lastInCompound->tagHistory();
688 } 685 }
689 } 686 }
690 687
691 RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromRuleData(con st RuleData& ruleData) 688 RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromRuleData(con st RuleData& ruleData)
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 bool RuleFeatureSet::InvalidationSetFeatures::hasFeatures() const 1031 bool RuleFeatureSet::InvalidationSetFeatures::hasFeatures() const
1035 { 1032 {
1036 return !classes.isEmpty() 1033 return !classes.isEmpty()
1037 || !attributes.isEmpty() 1034 || !attributes.isEmpty()
1038 || !ids.isEmpty() 1035 || !ids.isEmpty()
1039 || !tagNames.isEmpty() 1036 || !tagNames.isEmpty()
1040 || customPseudoElement; 1037 || customPseudoElement;
1041 } 1038 }
1042 1039
1043 } // namespace blink 1040 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/css/RuleFeature.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698