Changeset 229372 in webkit


Ignore:
Timestamp:
Mar 7, 2018 12:29:17 PM (6 years ago)
Author:
Antti Koivisto
Message:

Don't invalidate descendants for sibling combinators unless needed
https://bugs.webkit.org/show_bug.cgi?id=183410
<rdar://problem/38227297>

Reviewed by Zalan Bujtas.

If we know the matched sibling combinator doesn't affect descendants we shouldn't invalidate them.

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::matchRecursively const):

Use different bit for the descendant case.

  • cssjit/SelectorCompiler.cpp:

(WebCore::SelectorCompiler::fragmentMatchesTheRightmostElement):

Remove unneeded context assert.

(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):

Use different bit for the descendant case.

(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPseudoElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateRequestedPseudoElementEqualsToSelectorPseudoElement):

  • dom/Element.cpp:

(WebCore::invalidateForSiblingCombinators):

Invalidate the target sibling or all descendants based on the bits.

  • dom/Element.h:

(WebCore::Element::descendantsAffectedByPreviousSibling const):
(WebCore::Element::setDescendantsAffectedByPreviousSibling const):

  • dom/Node.h:
  • style/StyleRelations.cpp:

(WebCore::Style::commitRelationsToRenderStyle):
(WebCore::Style::commitRelations):

  • style/StyleRelations.h:

Add DescendantsAffectedByPreviousSibling bit. AffectedByPreviousSibling is now just about the target element.

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r229368 r229372  
     12018-03-07  Antti Koivisto  <antti@apple.com>
     2
     3        Don't invalidate descendants for sibling combinators unless needed
     4        https://bugs.webkit.org/show_bug.cgi?id=183410
     5        <rdar://problem/38227297>
     6
     7        Reviewed by Zalan Bujtas.
     8
     9        If we know the matched sibling combinator doesn't affect descendants we shouldn't invalidate them.
     10
     11        * css/SelectorChecker.cpp:
     12        (WebCore::SelectorChecker::matchRecursively const):
     13
     14            Use different bit for the descendant case.
     15
     16        * cssjit/SelectorCompiler.cpp:
     17        (WebCore::SelectorCompiler::fragmentMatchesTheRightmostElement):
     18
     19            Remove unneeded context assert.
     20
     21        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
     22
     23            Use different bit for the descendant case.
     24
     25        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorCheckerExcludingPseudoElements):
     26        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPseudoElement):
     27        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateRequestedPseudoElementEqualsToSelectorPseudoElement):
     28        * dom/Element.cpp:
     29        (WebCore::invalidateForSiblingCombinators):
     30
     31            Invalidate the target sibling or all descendants based on the bits.
     32
     33        * dom/Element.h:
     34        (WebCore::Element::descendantsAffectedByPreviousSibling const):
     35        (WebCore::Element::setDescendantsAffectedByPreviousSibling const):
     36        * dom/Node.h:
     37        * style/StyleRelations.cpp:
     38        (WebCore::Style::commitRelationsToRenderStyle):
     39        (WebCore::Style::commitRelations):
     40        * style/StyleRelations.h:
     41
     42            Add DescendantsAffectedByPreviousSibling bit. AffectedByPreviousSibling is now just about the target element.
     43
    1442018-03-07  Antti Koivisto  <antti@apple.com>
    245
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r229368 r229372  
    363363    case CSSSelector::DirectAdjacent:
    364364        {
    365             addStyleRelation(checkingContext, *context.element, Style::Relation::AffectedByPreviousSibling);
     365            auto relation = context.isMatchElement ? Style::Relation::AffectedByPreviousSibling : Style::Relation::DescendantsAffectedByPreviousSibling;
     366            addStyleRelation(checkingContext, *context.element, relation);
    366367
    367368            Element* previousElement = context.element->previousElementSibling();
     
    383384            return MatchResult::updateWithMatchType(result, matchType);
    384385        }
    385     case CSSSelector::IndirectAdjacent:
    386         addStyleRelation(checkingContext, *context.element, Style::Relation::AffectedByPreviousSibling);
     386    case CSSSelector::IndirectAdjacent: {
     387        auto relation = context.isMatchElement ? Style::Relation::AffectedByPreviousSibling : Style::Relation::DescendantsAffectedByPreviousSibling;
     388        addStyleRelation(checkingContext, *context.element, relation);
    387389
    388390        nextContext.element = context.element->previousElementSibling();
     
    403405        };
    404406        return MatchResult::fails(Match::SelectorFailsAllSiblings);
    405 
     407    }
    406408    case CSSSelector::Subselector:
    407409        {
  • trunk/Source/WebCore/cssjit/SelectorCompiler.cpp

    r229307 r229372  
    423423}
    424424
    425 static inline bool fragmentMatchesTheRightmostElement(SelectorContext selectorContext, const SelectorFragment& fragment)
    426 {
    427     // Return true if the position of this fragment is Rightmost in the root fragments.
    428     // In this case, we should use the RenderStyle stored in the CheckingContext.
    429     ASSERT_UNUSED(selectorContext, selectorContext != SelectorContext::QuerySelector);
     425static inline bool fragmentMatchesTheRightmostElement(const SelectorFragment& fragment)
     426{
    430427    return fragment.relationToRightFragment == FragmentRelation::Rightmost && fragment.positionInRootFragments == FragmentPositionInRootFragments::Rightmost;
    431428}
     
    17351732    // Test selector's pseudo element equals to requested PseudoId.
    17361733    if (m_selectorContext != SelectorContext::QuerySelector && m_functionType == FunctionType::SelectorCheckerWithCheckingContext) {
    1737         ASSERT_WITH_MESSAGE(fragmentMatchesTheRightmostElement(m_selectorContext, m_selectorFragments.first()), "Matching pseudo elements only make sense for the rightmost fragment.");
     1734        ASSERT_WITH_MESSAGE(fragmentMatchesTheRightmostElement(m_selectorFragments.first()), "Matching pseudo elements only make sense for the rightmost fragment.");
    17381735        generateRequestedPseudoElementEqualsToSelectorPseudoElement(failureOnFunctionEntry, m_selectorFragments.first(), checkingContextRegister);
    17391736    }
     
    18961893            break;
    18971894        }
    1898         if (shouldMarkStyleIsAffectedByPreviousSibling(fragment))
    1899             generateAddStyleRelationIfResolvingStyle(elementAddressRegister, Style::Relation::AffectedByPreviousSibling);
     1895        if (shouldMarkStyleIsAffectedByPreviousSibling(fragment)) {
     1896            if (fragmentMatchesTheRightmostElement(fragment))
     1897                generateAddStyleRelationIfResolvingStyle(elementAddressRegister, Style::Relation::AffectedByPreviousSibling);
     1898            else
     1899                generateAddStyleRelationIfResolvingStyle(elementAddressRegister, Style::Relation::DescendantsAffectedByPreviousSibling);
     1900        }
    19001901        generateBacktrackingTailsIfNeeded(failureCases, fragment);
    19011902    }
     
    37323733    ASSERT_UNUSED(fragment, fragment.pseudoElementSelector);
    37333734    ASSERT_WITH_MESSAGE(m_selectorContext != SelectorContext::QuerySelector, "When the fragment has pseudo element, the selector becomes CannotMatchAnything for QuerySelector and this test function is not called.");
    3734     ASSERT_WITH_MESSAGE_UNUSED(fragment, fragmentMatchesTheRightmostElement(m_selectorContext, fragment), "Virtual pseudo elements handling is only effective in the rightmost fragment. If the current fragment is not rightmost fragment, CSS JIT compiler makes it CannotMatchAnything in fragment construction phase, so never reach here.");
     3735    ASSERT_WITH_MESSAGE_UNUSED(fragment, fragmentMatchesTheRightmostElement(fragment), "Virtual pseudo elements handling is only effective in the rightmost fragment. If the current fragment is not rightmost fragment, CSS JIT compiler makes it CannotMatchAnything in fragment construction phase, so never reach here.");
    37353736}
    37363737
     
    37423743    // If the rightmost fragment doesn't have a pseudo element, the requested pseudoId need to be NOPSEUDO to succeed the matching.
    37433744    // Otherwise, if the requested pseudoId is not NOPSEUDO, the requested pseudoId need to equal to the pseudo element of the rightmost fragment.
    3744     if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
     3745    if (fragmentMatchesTheRightmostElement(fragment)) {
    37453746        if (!fragment.pseudoElementSelector)
    37463747            failureCases.append(m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(SelectorChecker::CheckingContext, pseudoId)), Assembler::TrustedImm32(NOPSEUDO)));
  • trunk/Source/WebCore/dom/Element.cpp

    r229368 r229372  
    14851485    for (; sibling; sibling = sibling->nextElementSibling()) {
    14861486        if (sibling->styleIsAffectedByPreviousSibling())
    1487             sibling->invalidateStyleForSubtreeInternal();
     1487            sibling->invalidateStyleInternal();
     1488        if (sibling->descendantsAffectedByPreviousSibling()) {
     1489            for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
     1490                siblingChild->invalidateStyleForSubtreeInternal();
     1491        }
    14881492        if (!sibling->affectsNextSiblingElementStyle())
    14891493            return;
  • trunk/Source/WebCore/dom/Element.h

    r229307 r229372  
    328328    bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
    329329    bool styleAffectedByFocusWithin() const { return hasRareData() && rareDataStyleAffectedByFocusWithin(); }
     330    bool descendantsAffectedByPreviousSibling() const { return getFlag(DescendantsAffectedByPreviousSiblingFlag); }
    330331    bool childrenAffectedByHover() const { return getFlag(ChildrenAffectedByHoverRulesFlag); }
    331332    bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
     
    342343    void setStyleAffectedByEmpty();
    343344    void setStyleAffectedByFocusWithin();
     345    void setDescendantsAffectedByPreviousSibling() const { return setFlag(DescendantsAffectedByPreviousSiblingFlag); }
    344346    void setChildrenAffectedByHover() { setFlag(ChildrenAffectedByHoverRulesFlag); }
    345347    void setStyleAffectedByActive();
  • trunk/Source/WebCore/dom/Node.h

    r224740 r229372  
    570570        IsHTMLFlag = 1 << 4,
    571571        IsSVGFlag = 1 << 5,
    572         // One free bit left.
     572        DescendantsAffectedByPreviousSiblingFlag = 1 << 6,
    573573        ChildNeedsStyleRecalcFlag = 1 << 7,
    574574        IsConnectedFlag = 1 << 8,
  • trunk/Source/WebCore/style/StyleRelations.cpp

    r229307 r229372  
    7676        case Relation::AffectedByFocusWithin:
    7777        case Relation::AffectedByPreviousSibling:
     78        case Relation::DescendantsAffectedByPreviousSibling:
    7879        case Relation::AffectsNextSibling:
    7980        case Relation::ChildrenAffectedByForwardPositionalRules:
     
    114115        case Relation::AffectedByPreviousSibling:
    115116            element.setStyleIsAffectedByPreviousSibling();
     117            break;
     118        case Relation::DescendantsAffectedByPreviousSibling:
     119            element.setDescendantsAffectedByPreviousSibling();
    116120            break;
    117121        case Relation::AffectsNextSibling: {
  • trunk/Source/WebCore/style/StyleRelations.h

    r229307 r229372  
    4545        AffectedByHover,
    4646        AffectedByPreviousSibling,
     47        DescendantsAffectedByPreviousSibling,
    4748        // For AffectsNextSibling 'value' tells how many element siblings to mark starting with 'element'.
    4849        AffectsNextSibling,
Note: See TracChangeset for help on using the changeset viewer.