Changeset 225110 in webkit


Ignore:
Timestamp:
Nov 23, 2017 2:45:26 AM (6 years ago)
Author:
Antti Koivisto
Message:

RenderBlockFlow::layoutRunsAndFloatsInRange is O(n2) for runs of inlines without any text
https://bugs.webkit.org/show_bug.cgi?id=179950

Reviewed by Simon Fraser.

It calls createBidiRunsForLine for each line. createBidiRunsForLine traverses past the end of the line until
it finds the end of the current bidi run. If there is no text in the flow, it never finds anything and traverses
the entire flow. This is O(n2) for the number of renderers in the flow.

Tested by PerformanceTests/Layout/inline-layout-no-text.html

  • platform/text/BidiResolver.h:

(WebCore::BidiResolverBase::needsContinuePastEnd const):
(WebCore::BidiResolverBase::needsContinuePastEndInternal const):
(WebCore::DerivedClass>::createBidiRunsForLine):

When past end of line call needsContinuePastEnd() to see if we need to continue searching for the end of the bidi run.

  • rendering/InlineIterator.h:

(WebCore::InlineBidiResolver::needsContinuePastEndInternal const):

InlineBidiResolver only returns runs up to the last renderer on the line and can bail out.

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r225108 r225110  
     12017-11-23  Antti Koivisto  <antti@apple.com>
     2
     3        RenderBlockFlow::layoutRunsAndFloatsInRange is O(n^2) for runs of inlines without any text
     4        https://bugs.webkit.org/show_bug.cgi?id=179950
     5
     6        Reviewed by Simon Fraser.
     7
     8        It calls createBidiRunsForLine for each line. createBidiRunsForLine traverses past the end of the line until
     9        it finds the end of the current bidi run. If there is no text in the flow, it never finds anything and traverses
     10        the entire flow. This is O(n^2) for the number of renderers in the flow.
     11
     12        Tested by PerformanceTests/Layout/inline-layout-no-text.html
     13
     14        * platform/text/BidiResolver.h:
     15        (WebCore::BidiResolverBase::needsContinuePastEnd const):
     16        (WebCore::BidiResolverBase::needsContinuePastEndInternal const):
     17        (WebCore::DerivedClass>::createBidiRunsForLine):
     18
     19            When past end of line call needsContinuePastEnd() to see if we need to continue searching for the end of the bidi run.
     20
     21        * rendering/InlineIterator.h:
     22        (WebCore::InlineBidiResolver::needsContinuePastEndInternal const):
     23
     24            InlineBidiResolver only returns runs up to the last renderer on the line and can bail out.
     25
    1262017-11-23  Zan Dobersek  <zdobersek@igalia.com>
    227
  • trunk/Source/WebCore/platform/text/BidiResolver.h

    r210492 r225110  
    246246    // pass in some sort of Traits object which knows how to create runs for appending.
    247247    void appendRun() { static_cast<DerivedClass&>(*this).appendRunInternal(); }
     248    bool needsContinuePastEnd() const { return static_cast<const DerivedClass&>(*this).needsContinuePastEndInternal(); }
    248249
    249250    Iterator m_current;
     
    278279    void incrementInternal() { m_current.increment(); }
    279280    void appendRunInternal();
     281    bool needsContinuePastEndInternal() const { return true; }
    280282
    281283    Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence;
     
    293295    void incrementInternal();
    294296    void appendRunInternal();
     297    bool needsContinuePastEndInternal() const;
    295298    Vector<IsolateRun>& isolatedRuns() { return m_isolatedRuns; }
    296299
     
    881884        }
    882885
    883         if (pastEnd && m_eor == m_current) {
     886        if (pastEnd && (m_eor == m_current || !needsContinuePastEnd())) {
    884887            if (!m_reachedEndOfLine) {
    885888                m_eor = endOfLine;
  • trunk/Source/WebCore/rendering/InlineIterator.h

    r217893 r225110  
    587587}
    588588
     589template<>
     590inline bool InlineBidiResolver::needsContinuePastEndInternal() const
     591{
     592    // We don't collect runs beyond the endOfLine renderer. Stop traversing when the iterator moves to the next renderer to prevent O(n^2).
     593    return m_current.renderer() == endOfLine.renderer();
     594}
     595
    589596} // namespace WebCore
Note: See TracChangeset for help on using the changeset viewer.