Changeset 208998 in webkit


Ignore:
Timestamp:
Nov 28, 2016 7:58:35 AM (7 years ago)
Author:
Antti Koivisto
Message:

Remove FIRST_LINE_INHERITED fake pseudo style
https://bugs.webkit.org/show_bug.cgi?id=165071

Reviewed by Andreas Kling.

Source/WebCore:

These are create during layout an then cached to the RenderStyle. Cache computed first line style to
RenderObject rare data instead, avoiding style mutation an other confusing messiness.

  • rendering/RenderElement.cpp:

(WebCore::RenderElement::RenderElement):
(WebCore::RenderElement::computeFirstLineStyle):
(WebCore::RenderElement::firstLineStyle):

Cache the first line style.

(WebCore::RenderElement::invalidateCachedFirstLineStyle):
(WebCore::RenderElement::styleWillChange):

Invalidate subtree if we have cached first line style.

(WebCore::RenderElement::getUncachedPseudoStyle):
(WebCore::RenderElement::uncachedFirstLineStyle): Deleted.
(WebCore::RenderElement::cachedFirstLineStyle): Deleted.

  • rendering/RenderElement.h:
  • rendering/RenderObject.cpp:

(WebCore::RenderObject::rareDataMap):
(WebCore::RenderObject::rareData):
(WebCore::RenderObject::ensureRareData):

  • rendering/RenderObject.h:

Stop copying rare data objects.

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::changeRequiresLayout):

Use the normal mechanism for invalidating layout for first-line instead of a hack in pseudoStyleCacheIsInvalid.

  • rendering/style/RenderStyleConstants.h:
  • style/RenderTreeUpdater.cpp:

(WebCore::pseudoStyleCacheIsInvalid):

Simplify.

LayoutTests:

Expand the test case a bit.

  • fast/css/pseudo-cache-stale-expected.html:
  • fast/css/pseudo-cache-stale.html:
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208996 r208998  
     12016-11-28  Antti Koivisto  <antti@apple.com>
     2
     3        Remove FIRST_LINE_INHERITED fake pseudo style
     4        https://bugs.webkit.org/show_bug.cgi?id=165071
     5
     6        Reviewed by Andreas Kling.
     7
     8        Expand the test case a bit.
     9
     10        * fast/css/pseudo-cache-stale-expected.html:
     11        * fast/css/pseudo-cache-stale.html:
     12
    1132016-11-28  Per Arne Vollan  <pvollan@apple.com>
    214
  • trunk/LayoutTests/fast/css/pseudo-cache-stale-expected.html

    r202066 r208998  
    1111        This sentence should be extra-extra-large.
    1212    </div>
     13    <div id="first-line" style="font-size: xx-large;">
     14        This sentence should be extra-extra-large too.
     15    </div>
    1316    <input type="search" placeholder="This should be green">
    1417</body>
  • trunk/LayoutTests/fast/css/pseudo-cache-stale.html

    r202066 r208998  
    1616    }
    1717
     18    .green #first-line-inherit:first-line {
     19        font-size: xx-large;
     20    }
     21
    1822    .green input::placeholder {
    1923        color: green;
     
    2731        This sentence should be extra-extra-large.
    2832    </div>
     33    <div id="first-line-inherit">
     34        <span>This sentence should be extra-extra-large too.</span>
     35    </div>
    2936    <input type="search" placeholder="This should be green">
    3037    <script>
  • trunk/Source/WebCore/ChangeLog

    r208997 r208998  
     12016-11-28  Antti Koivisto  <antti@apple.com>
     2
     3        Remove FIRST_LINE_INHERITED fake pseudo style
     4        https://bugs.webkit.org/show_bug.cgi?id=165071
     5
     6        Reviewed by Andreas Kling.
     7
     8        These are create during layout an then cached to the RenderStyle. Cache computed first line style to
     9        RenderObject rare data instead, avoiding style mutation an other confusing messiness.
     10
     11        * rendering/RenderElement.cpp:
     12        (WebCore::RenderElement::RenderElement):
     13        (WebCore::RenderElement::computeFirstLineStyle):
     14        (WebCore::RenderElement::firstLineStyle):
     15
     16            Cache the first line style.
     17
     18        (WebCore::RenderElement::invalidateCachedFirstLineStyle):
     19        (WebCore::RenderElement::styleWillChange):
     20
     21            Invalidate subtree if we have cached first line style.
     22
     23        (WebCore::RenderElement::getUncachedPseudoStyle):
     24        (WebCore::RenderElement::uncachedFirstLineStyle): Deleted.
     25        (WebCore::RenderElement::cachedFirstLineStyle): Deleted.
     26        * rendering/RenderElement.h:
     27        * rendering/RenderObject.cpp:
     28        (WebCore::RenderObject::rareDataMap):
     29        (WebCore::RenderObject::rareData):
     30        (WebCore::RenderObject::ensureRareData):
     31        * rendering/RenderObject.h:
     32
     33            Stop copying rare data objects.
     34
     35        * rendering/style/RenderStyle.cpp:
     36        (WebCore::RenderStyle::changeRequiresLayout):
     37
     38            Use the normal mechanism for invalidating layout for first-line instead of a hack in pseudoStyleCacheIsInvalid.
     39
     40        * rendering/style/RenderStyleConstants.h:
     41        * style/RenderTreeUpdater.cpp:
     42        (WebCore::pseudoStyleCacheIsInvalid):
     43
     44            Simplify.
     45
    1462016-11-28  Miguel Gomez  <magomez@igalia.com>
    247
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r208797 r208998  
    105105    , m_isCSSAnimating(false)
    106106    , m_hasContinuation(false)
     107    , m_hasValidCachedFirstLineStyle(false)
    107108    , m_renderBlockHasMarginBeforeQuirk(false)
    108109    , m_renderBlockHasMarginAfterQuirk(false)
     
    216217}
    217218
    218 std::unique_ptr<RenderStyle> RenderElement::uncachedFirstLineStyle(RenderStyle* style) const
     219std::unique_ptr<RenderStyle> RenderElement::computeFirstLineStyle() const
     220{
     221    ASSERT(view().usesFirstLineRules());
     222
     223    RenderElement& rendererForFirstLineStyle = isBeforeOrAfterContent() ? *parent() : const_cast<RenderElement&>(*this);
     224
     225    if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
     226        RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock();
     227        if (!firstLineBlock)
     228            return nullptr;
     229        auto* firstLineStyle = firstLineBlock->getCachedPseudoStyle(FIRST_LINE, &style());
     230        if (!firstLineStyle)
     231            return nullptr;
     232        return RenderStyle::clonePtr(*firstLineStyle);
     233    }
     234
     235    if (rendererForFirstLineStyle.isAnonymous() || !rendererForFirstLineStyle.isRenderInline())
     236        return nullptr;
     237
     238    auto& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
     239    if (&parentStyle == &rendererForFirstLineStyle.parent()->style())
     240        return nullptr;
     241    return rendererForFirstLineStyle.element()->styleResolver().styleForElement(*element(), &parentStyle).renderStyle;
     242}
     243
     244const RenderStyle& RenderElement::firstLineStyle() const
    219245{
    220246    if (!view().usesFirstLineRules())
    221         return nullptr;
    222 
    223     RenderElement& rendererForFirstLineStyle = isBeforeOrAfterContent() ? *parent() : const_cast<RenderElement&>(*this);
    224 
    225     if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
    226         if (RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock())
    227             return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == this ? style : nullptr);
    228     } else if (!rendererForFirstLineStyle.isAnonymous() && rendererForFirstLineStyle.isRenderInline()) {
    229         auto& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
    230         if (&parentStyle != &rendererForFirstLineStyle.parent()->style())
    231             return rendererForFirstLineStyle.getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), &parentStyle, style);
    232     }
    233     return nullptr;
    234 }
    235 
    236 const RenderStyle* RenderElement::cachedFirstLineStyle() const
    237 {
    238     ASSERT(view().usesFirstLineRules());
    239 
    240     RenderElement& rendererForFirstLineStyle = isBeforeOrAfterContent() ? *parent() : const_cast<RenderElement&>(*this);
    241 
    242     if (rendererForFirstLineStyle.isRenderBlockFlow() || rendererForFirstLineStyle.isRenderButton()) {
    243         if (RenderBlock* firstLineBlock = rendererForFirstLineStyle.firstLineBlock())
    244             return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, &style());
    245     } else if (!rendererForFirstLineStyle.isAnonymous() && rendererForFirstLineStyle.isRenderInline()) {
    246         auto& parentStyle = rendererForFirstLineStyle.parent()->firstLineStyle();
    247         if (&parentStyle != &rendererForFirstLineStyle.parent()->style()) {
    248             // A first-line style is in effect. Cache a first-line style for ourselves.
    249             rendererForFirstLineStyle.m_style.setHasPseudoStyle(FIRST_LINE_INHERITED);
    250             return rendererForFirstLineStyle.getCachedPseudoStyle(FIRST_LINE_INHERITED, &parentStyle);
    251         }
    252     }
    253 
    254     return &style();
    255 }
    256 
    257 const RenderStyle& RenderElement::firstLineStyle() const
    258 {
    259     return view().usesFirstLineRules() ? *cachedFirstLineStyle() : style();
     247        return style();
     248
     249    if (!m_hasValidCachedFirstLineStyle) {
     250        auto firstLineStyle = computeFirstLineStyle();
     251        if (firstLineStyle || hasRareData())
     252            const_cast<RenderElement&>(*this).ensureRareData().cachedFirstLineStyle = WTFMove(firstLineStyle);
     253        m_hasValidCachedFirstLineStyle = true;
     254    }
     255
     256    return (hasRareData() && rareData().cachedFirstLineStyle) ? *rareData().cachedFirstLineStyle : style();
    260257}
    261258
     
    817814{
    818815    return renderer && renderer->hasBackground();
     816}
     817
     818void RenderElement::invalidateCachedFirstLineStyle()
     819{
     820    if (!m_hasValidCachedFirstLineStyle)
     821        return;
     822    m_hasValidCachedFirstLineStyle = false;
     823    // Invalidate the subtree as descendant's first line style may depend on ancestor's.
     824    for (auto& descendant : descendantsOfType<RenderElement>(*this))
     825        descendant.m_hasValidCachedFirstLineStyle = false;
    819826}
    820827
     
    878885            clearPositionedState();
    879886        }
     887        if (newStyle.hasPseudoStyle(FIRST_LINE) || oldStyle->hasPseudoStyle(FIRST_LINE))
     888            invalidateCachedFirstLineStyle();
     889
    880890        setHorizontalWritingMode(true);
    881891        setHasVisibleBoxDecorations(false);
     
    15461556    auto& styleResolver = element()->styleResolver();
    15471557
    1548     std::unique_ptr<RenderStyle> style;
    1549     if (pseudoStyleRequest.pseudoId == FIRST_LINE_INHERITED) {
    1550         style = styleResolver.styleForElement(*element(), parentStyle).renderStyle;
    1551         style->setStyleType(FIRST_LINE_INHERITED);
    1552     } else
    1553         style = styleResolver.pseudoStyleForElement(*element(), pseudoStyleRequest, *parentStyle);
     1558    std::unique_ptr<RenderStyle> style = styleResolver.pseudoStyleForElement(*element(), pseudoStyleRequest, *parentStyle);
    15541559
    15551560    if (style)
  • trunk/Source/WebCore/rendering/RenderElement.h

    r208797 r208998  
    132132    RenderElement& rendererForRootBackground();
    133133
    134     // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
    135     // given new style, without accessing the cache.
    136     std::unique_ptr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
    137 
    138134    // Updates only the local style ptr of the object. Does not update the state of the object,
    139135    // and so only should be called when the style is known not to have changed (or from setStyle).
     
    307303
    308304    StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
    309     const RenderStyle* cachedFirstLineStyle() const;
     305    std::unique_ptr<RenderStyle> computeFirstLineStyle() const;
     306    void invalidateCachedFirstLineStyle();
    310307
    311308    void newImageAnimationFrameAvailable(CachedImage&) final;
     
    329326    unsigned m_isCSSAnimating : 1;
    330327    unsigned m_hasContinuation : 1;
     328    mutable unsigned m_hasValidCachedFirstLineStyle : 1;
    331329
    332330    unsigned m_renderBlockHasMarginBeforeQuirk : 1;
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r208661 r208998  
    19791979}
    19801980
    1981 RenderObject::RareDataHash& RenderObject::rareDataMap()
    1982 {
    1983     static NeverDestroyed<RareDataHash> map;
     1981RenderObject::RareDataMap& RenderObject::rareDataMap()
     1982{
     1983    static NeverDestroyed<RareDataMap> map;
    19841984    return map;
    19851985}
    19861986
    1987 RenderObject::RenderObjectRareData RenderObject::rareData() const
    1988 {
    1989     if (!hasRareData())
    1990         return RenderObjectRareData();
    1991 
    1992     return rareDataMap().get(this);
     1987const RenderObject::RenderObjectRareData& RenderObject::rareData() const
     1988{
     1989    ASSERT(hasRareData());
     1990    return *rareDataMap().get(this);
    19931991}
    19941992
     
    19961994{
    19971995    setHasRareData(true);
    1998     return rareDataMap().add(this, RenderObjectRareData()).iterator->value;
     1996    return *rareDataMap().ensure(this, [] { return std::make_unique<RenderObjectRareData>(); }).iterator->value;
    19991997}
    20001998
  • trunk/Source/WebCore/rendering/RenderObject.h

    r208661 r208998  
    971971    RenderObjectBitfields m_bitfields;
    972972
     973    // FIXME: This should be RenderElementRareData.
    973974    class RenderObjectRareData {
    974975    public:
     
    990991        ADD_BOOLEAN_BITFIELD(isRegisteredForVisibleInViewportCallback, IsRegisteredForVisibleInViewportCallback);
    991992        ADD_ENUM_BITFIELD(visibleInViewportState, VisibleInViewportState, VisibleInViewportState, 2);
    992 
     993        std::unique_ptr<RenderStyle> cachedFirstLineStyle;
    993994    };
    994995   
    995     RenderObjectRareData rareData() const;
     996    const RenderObject::RenderObjectRareData& rareData() const;
    996997    RenderObjectRareData& ensureRareData();
    997998    void removeRareData();
    998999   
    999     // Note: RenderObjectRareData is stored by value.
    1000     typedef HashMap<const RenderObject*, RenderObjectRareData> RareDataHash;
    1001 
    1002     static RareDataHash& rareDataMap();
     1000    typedef HashMap<const RenderObject*, std::unique_ptr<RenderObjectRareData>> RareDataMap;
     1001
     1002    static RareDataMap& rareDataMap();
    10031003
    10041004#undef ADD_BOOLEAN_BITFIELD
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r208460 r208998  
    760760        }
    761761    }
    762    
     762
     763    bool hasFirstLineStyle = hasPseudoStyle(FIRST_LINE);
     764    if (hasFirstLineStyle != other.hasPseudoStyle(FIRST_LINE))
     765        return true;
     766    if (hasFirstLineStyle) {
     767        auto* firstLineStyle = getCachedPseudoStyle(FIRST_LINE);
     768        if (!firstLineStyle)
     769            return true;
     770        auto* otherFirstLineStyle = other.getCachedPseudoStyle(FIRST_LINE);
     771        if (!otherFirstLineStyle)
     772            return true;
     773        // FIXME: Not all first line style changes actually need layout.
     774        if (*firstLineStyle != *otherFirstLineStyle)
     775            return true;
     776    }
     777
    763778    return false;
    764779}
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r208914 r208998  
    7878enum PseudoId : unsigned char {
    7979    // The order must be NOP ID, public IDs, and then internal IDs.
    80     NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR,
     80    NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, SCROLLBAR,
    8181    // Internal IDs follow:
    8282    SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
  • trunk/Source/WebCore/style/RenderTreeUpdater.cpp

    r208985 r208998  
    236236
    237237    for (auto& cache : *pseudoStyleCache) {
    238         std::unique_ptr<RenderStyle> newPseudoStyle;
    239238        PseudoId pseudoId = cache->styleType();
    240         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
    241             newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
    242         else
    243             newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
     239        std::unique_ptr<RenderStyle> newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
    244240        if (!newPseudoStyle)
    245241            return true;
    246242        if (*newPseudoStyle != *cache) {
    247             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
    248                 newStyle->setHasPseudoStyle(pseudoId);
    249243            newStyle->addCachedPseudoStyle(WTFMove(newPseudoStyle));
    250             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
    251                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
    252                 // is needed, but for now just assume a layout will be required. The diff code
    253                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
    254                 renderer->setNeedsLayoutAndPrefWidthsRecalc();
    255             }
    256244            return true;
    257245        }
Note: See TracChangeset for help on using the changeset viewer.