⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 79694 in webkit


Ignore:
Timestamp:
Feb 25, 2011, 10:34:15 AM (16 years ago)
Author:
mitz@apple.com
Message:

Minimize calls to ubrk_setText()
https://bugs.webkit.org/show_bug.cgi?id=54912
<rdar://problem/9032774>

Patch by Ned Holbrook <nholbrook@apple.com> on 2011-02-25
Reviewed by Dan Bernstein.

Avoid calling ubrk_setText() once per call to isBreakable() by using a LazyLineBreakIterator, which defers
break iterator creation until needed. This requires replacing the global line break iterator primitive with a
version that can be nested, since in some cases two iterators may need to be outstanding. In particular,
layoutInlineChildren() may indirectly call computePreferredLogicalWidths() and each may need an iterator.
In a test with a paragraph of Japanese text, this reduced the number of ubrk_setText() calls from 164 to 1.

  • platform/text/TextBreakIterator.h: Add LazyLineBreakIterator.

(WebCore::LazyLineBreakIterator::LazyLineBreakIterator):
(WebCore::LazyLineBreakIterator::~LazyLineBreakIterator):
(WebCore::LazyLineBreakIterator::string):
(WebCore::LazyLineBreakIterator::length):
(WebCore::LazyLineBreakIterator::get):
(WebCore::LazyLineBreakIterator::reset):

  • platform/text/TextBreakIteratorICU.cpp: Replace lineBreakIterator() primitive with acquireLineBreakIterator()/releaseLineBreakIterator().

(WebCore::acquireLineBreakIterator):
(WebCore::releaseLineBreakIterator):

  • platform/text/brew/TextBreakIteratorBrew.cpp: Ditto.

(WebCore::acquireLineBreakIterator):
(WebCore::releaseLineBreakIterator):

  • platform/text/gtk/TextBreakIteratorGtk.cpp: Ditto.

(WebCore::acquireLineBreakIterator):
(WebCore::releaseLineBreakIterator):

  • platform/text/qt/TextBreakIteratorQt.cpp: Ditto.

(WebCore::acquireLineBreakIterator):
(WebCore::releaseLineBreakIterator):

  • platform/text/wince/TextBreakIteratorWinCE.cpp: Ditto.

(WebCore::acquireLineBreakIterator):
(WebCore::releaseLineBreakIterator):

  • rendering/RenderBlock.h:
  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::layoutInlineChildren): Pass a mapping of RenderText to LazyLineBreakIterator from one call of findNextLineBreak() to the next.
(WebCore::RenderBlock::findNextLineBreak): Use said mapping, resetting LazyLineBreakIterator for any newly-encountered RenderText.

  • rendering/RenderText.cpp: Use a local LazyLineBreakIterator.

(WebCore::RenderText::computePreferredLogicalWidths):

  • rendering/break_lines.cpp: Accept LazyLineBreakIterator rather than UniChar buffer.

(WebCore::nextBreakablePosition):

  • rendering/break_lines.h: Accept LazyLineBreakIterator rather than UniChar buffer.

(WebCore::isBreakable):

Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r79691 r79694  
     12011-02-25  Ned Holbrook  <nholbrook@apple.com>
     2
     3        Reviewed by Dan Bernstein.
     4
     5        Minimize calls to ubrk_setText()
     6        https://bugs.webkit.org/show_bug.cgi?id=54912
     7        <rdar://problem/9032774>
     8
     9        Avoid calling ubrk_setText() once per call to isBreakable() by using a LazyLineBreakIterator, which defers
     10        break iterator creation until needed. This requires replacing the global line break iterator primitive with a
     11        version that can be nested, since in some cases two iterators may need to be outstanding. In particular,
     12        layoutInlineChildren() may indirectly call computePreferredLogicalWidths() and each may need an iterator.
     13        In a test with a paragraph of Japanese text, this reduced the number of ubrk_setText() calls from 164 to 1.
     14
     15        * platform/text/TextBreakIterator.h: Add LazyLineBreakIterator.
     16        (WebCore::LazyLineBreakIterator::LazyLineBreakIterator):
     17        (WebCore::LazyLineBreakIterator::~LazyLineBreakIterator):
     18        (WebCore::LazyLineBreakIterator::string):
     19        (WebCore::LazyLineBreakIterator::length):
     20        (WebCore::LazyLineBreakIterator::get):
     21        (WebCore::LazyLineBreakIterator::reset):
     22        * platform/text/TextBreakIteratorICU.cpp: Replace lineBreakIterator() primitive with acquireLineBreakIterator()/releaseLineBreakIterator().
     23        (WebCore::acquireLineBreakIterator):
     24        (WebCore::releaseLineBreakIterator):
     25        * platform/text/brew/TextBreakIteratorBrew.cpp: Ditto.
     26        (WebCore::acquireLineBreakIterator):
     27        (WebCore::releaseLineBreakIterator):
     28        * platform/text/gtk/TextBreakIteratorGtk.cpp: Ditto.
     29        (WebCore::acquireLineBreakIterator):
     30        (WebCore::releaseLineBreakIterator):
     31        * platform/text/qt/TextBreakIteratorQt.cpp: Ditto.
     32        (WebCore::acquireLineBreakIterator):
     33        (WebCore::releaseLineBreakIterator):
     34        * platform/text/wince/TextBreakIteratorWinCE.cpp: Ditto.
     35        (WebCore::acquireLineBreakIterator):
     36        (WebCore::releaseLineBreakIterator):
     37        * rendering/RenderBlock.h:
     38        * rendering/RenderBlockLineLayout.cpp:
     39        (WebCore::RenderBlock::layoutInlineChildren): Pass a mapping of RenderText to LazyLineBreakIterator from one call of findNextLineBreak() to the next.
     40        (WebCore::RenderBlock::findNextLineBreak): Use said mapping, resetting LazyLineBreakIterator for any newly-encountered RenderText.
     41        * rendering/RenderText.cpp: Use a local LazyLineBreakIterator.
     42        (WebCore::RenderText::computePreferredLogicalWidths):
     43        * rendering/break_lines.cpp: Accept LazyLineBreakIterator rather than UniChar buffer.
     44        (WebCore::nextBreakablePosition):
     45        * rendering/break_lines.h: Accept LazyLineBreakIterator rather than UniChar buffer.
     46        (WebCore::isBreakable):
     47
    1482011-02-25  David Hyatt  <hyatt@apple.com>
    249
  • trunk/Source/WebCore/platform/text/TextBreakIterator.h

    r79518 r79694  
    2929    class TextBreakIterator;
    3030
    31     // Note: The returned iterator is good only until you get another iterator.
     31    // Note: The returned iterator is good only until you get another iterator, with the exception of acquireLineBreakIterator.
    3232
    3333    // Iterates over "extended grapheme clusters", as defined in UAX #29.
     
    4444
    4545    TextBreakIterator* wordBreakIterator(const UChar*, int length);
    46     TextBreakIterator* lineBreakIterator(const UChar*, int length);
     46    TextBreakIterator* acquireLineBreakIterator(const UChar*, int length);
     47    void releaseLineBreakIterator(TextBreakIterator*);
    4748    TextBreakIterator* sentenceBreakIterator(const UChar*, int length);
    4849
     
    5859    const int TextBreakDone = -1;
    5960
     61class LazyLineBreakIterator {
     62public:
     63    LazyLineBreakIterator(const UChar* string = 0, int length = 0)
     64        : m_string(string)
     65        , m_length(length)
     66        , m_iterator(0)
     67    {
     68    }
     69
     70    ~LazyLineBreakIterator()
     71    {
     72        if (m_iterator)
     73            releaseLineBreakIterator(m_iterator);
     74    }
     75
     76    const UChar* string() const { return m_string; }
     77    int length() const { return m_length; }
     78
     79    TextBreakIterator* get()
     80    {
     81        if (!m_iterator)
     82            m_iterator = acquireLineBreakIterator(m_string, m_length);
     83        return m_iterator;
     84    }
     85
     86    void reset(const UChar* string, int length)
     87    {
     88        if (m_iterator)
     89            releaseLineBreakIterator(m_iterator);
     90
     91        m_string = string;
     92        m_length = length;
     93        m_iterator = 0;
     94    }
     95
     96private:
     97    const UChar* m_string;
     98    int m_length;
     99    TextBreakIterator* m_iterator;
     100};
     101
    60102}
    61103
  • trunk/Source/WebCore/platform/text/TextBreakIteratorICU.cpp

    r79518 r79694  
    2727#include <unicode/ubrk.h>
    2828#include <wtf/Assertions.h>
     29
     30using namespace std;
    2931
    3032namespace WebCore {
     
    6971}
    7072
    71 TextBreakIterator* lineBreakIterator(const UChar* string, int length)
    72 {
    73     static bool createdLineBreakIterator = false;
    74     static TextBreakIterator* staticLineBreakIterator;
    75     return setUpIterator(createdLineBreakIterator,
    76         staticLineBreakIterator, UBRK_LINE, string, length);
     73static bool createdLineBreakIterator = false;
     74static TextBreakIterator* staticLineBreakIterator;
     75
     76TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
     77{
     78    TextBreakIterator* lineBreakIterator = 0;
     79    if (!createdLineBreakIterator || staticLineBreakIterator) {
     80        setUpIterator(createdLineBreakIterator, staticLineBreakIterator, UBRK_LINE, string, length);
     81        swap(staticLineBreakIterator, lineBreakIterator);
     82    }
     83
     84    if (!lineBreakIterator) {
     85        bool createdNewLineBreakIterator = false;
     86        setUpIterator(createdNewLineBreakIterator, lineBreakIterator, UBRK_LINE, string, length);
     87    }
     88
     89    return lineBreakIterator;
     90}
     91
     92void releaseLineBreakIterator(TextBreakIterator* iterator)
     93{
     94    ASSERT(createdLineBreakIterator);
     95    ASSERT(iterator);
     96
     97    if (!staticLineBreakIterator)
     98        staticLineBreakIterator = iterator;
     99    else
     100        ubrk_close(reinterpret_cast<UBreakIterator*>(iterator));
    77101}
    78102
  • trunk/Source/WebCore/platform/text/brew/TextBreakIteratorBrew.cpp

    r69722 r79694  
    2727#include <wtf/unicode/Unicode.h>
    2828
     29using namespace std;
    2930using namespace WTF::Unicode;
    3031
     
    261262}
    262263
    263 TextBreakIterator* lineBreakIterator(const UChar* string, int length)
    264 {
    265     DEFINE_STATIC_LOCAL(LineBreakIterator , iterator, ());
    266     iterator.reset(string, length);
    267     return &iterator;
     264static TextBreakIterator* staticLineBreakIterator;
     265
     266TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
     267{
     268    TextBreakIterator* lineBreakIterator = 0;
     269    if (staticLineBreakIterator) {
     270        staticLineBreakIterator->reset(string, length);
     271        swap(staticLineBreakIterator, lineBreakIterator);
     272    }
     273
     274    if (!lineBreakIterator && string && length)
     275        lineBreakIterator = new LineBreakIterator(string, length);
     276
     277    return lineBreakIterator;
     278}
     279
     280void releaseLineBreakIterator(TextBreakIterator* iterator)
     281{
     282    ASSERT(iterator);
     283
     284    if (!staticLineBreakIterator)
     285        staticLineBreakIterator = iterator;
     286    else
     287        delete iterator;
    268288}
    269289
  • trunk/Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp

    r71296 r79694  
    240240}
    241241
    242 TextBreakIterator* lineBreakIterator(const UChar* string, int length)
    243 {
    244     static bool createdLineBreakIterator = false;
    245     static TextBreakIterator* staticLineBreakIterator;
    246     return setUpIterator(createdLineBreakIterator, staticLineBreakIterator, UBRK_LINE, string, length);
     242static bool createdLineBreakIterator = false;
     243static TextBreakIterator* staticLineBreakIterator;
     244
     245TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
     246{
     247    TextBreakIterator* lineBreakIterator = 0;
     248    if (!createdLineBreakIterator || staticLineBreakIterator) {
     249        setUpIterator(createdLineBreakIterator, staticLineBreakIterator, UBRK_LINE, string, length);
     250        swap(staticLineBreakIterator, lineBreakIterator);
     251    }
     252
     253    if (!lineBreakIterator) {
     254        bool createdNewLineBreakIterator = false;
     255        setUpIterator(createdNewLineBreakIterator, lineBreakIterator, UBRK_LINE, string, length);
     256    }
     257
     258    return lineBreakIterator;
     259}
     260
     261void releaseLineBreakIterator(TextBreakIterator* iterator)
     262{
     263    ASSERT(createdLineBreakIterator);
     264    ASSERT(iterator);
     265
     266    if (!staticLineBreakIterator)
     267        staticLineBreakIterator = iterator;
     268    else
     269        delete iterator;
    247270}
    248271
  • trunk/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp

    r79567 r79694  
    3131#define DEBUG if (1) {} else qDebug
    3232#endif
     33
     34using namespace std;
    3335
    3436namespace WebCore {
     
    8183    }
    8284
    83     TextBreakIterator* lineBreakIterator(const UChar* string, int length)
     85    static TextBreakIterator* staticLineBreakIterator;
     86
     87    TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
    8488    {
    85         static TextBreakIterator staticLineBreakIterator;
    86         return setUpIterator(staticLineBreakIterator, QTextBoundaryFinder::Line, string, length);
     89        TextBreakIterator* lineBreakIterator = 0;
     90        if (staticLineBreakIterator) {
     91            setUpIterator(*staticLineBreakIterator, QTextBoundaryFinder::Line, string, length);
     92            swap(staticLineBreakIterator, lineBreakIterator);
     93        }
     94
     95        if (!lineBreakIterator && string && length)
     96            lineBreakIterator = new TextBreakIterator(QTextBoundaryFinder::Line, QString(reinterpret_cast<const QChar*>(string), length));
     97
     98        return lineBreakIterator;
     99    }
     100
     101    void releaseLineBreakIterator(TextBreakIterator* iterator)
     102    {
     103        ASSERT(iterator);
     104
     105        if (!staticLineBreakIterator)
     106            staticLineBreakIterator = iterator;
     107        else
     108            delete iterator;
    87109    }
    88110
  • trunk/Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp

    r72483 r79694  
    2727#include <wtf/unicode/Unicode.h>
    2828
     29using namespace std;
    2930using namespace WTF::Unicode;
    3031
     
    242243}
    243244
    244 TextBreakIterator* lineBreakIterator(const UChar* string, int length)
    245 {
    246     DEFINE_STATIC_LOCAL(LineBreakIterator , iterator, ());
    247     iterator.reset(string, length);
    248     return &iterator;
     245static TextBreakIterator* staticLineBreakIterator;
     246
     247TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
     248{
     249    TextBreakIterator* lineBreakIterator = 0;
     250    if (staticLineBreakIterator) {
     251        staticLineBreakIterator->reset(string, length);
     252        swap(staticLineBreakIterator, lineBreakIterator);
     253    }
     254
     255    if (!lineBreakIterator && string && length)
     256        lineBreakIterator = new LineBreakIterator(string, length);
     257
     258    return lineBreakIterator;
     259}
     260
     261void releaseLineBreakIterator(TextBreakIterator* iterator)
     262{
     263    ASSERT(iterator);
     264
     265    if (!staticLineBreakIterator)
     266        staticLineBreakIterator = iterator;
     267    else
     268        delete iterator;
    249269}
    250270
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r79629 r79694  
    3636class InlineIterator;
    3737class LayoutStateMaintainer;
     38class LazyLineBreakIterator;
    3839class RenderInline;
    3940
     
    487488    int skipLeadingWhitespace(InlineBidiResolver&, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly, FloatingObject* lastFloatFromPreviousLine);
    488489    void fitBelowFloats(float widthToFit, bool firstLine, float& availableWidth);
    489     InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly, bool& hyphenated, EClear*, FloatingObject* lastFloatFromPreviousLine);
     490    typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo;
     491    InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo&, bool& previousLineBrokeCleanly, bool& hyphenated, EClear*, FloatingObject* lastFloatFromPreviousLine);
    490492    RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject);
    491493    InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine);
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r79656 r79694  
    3535#include "RenderView.h"
    3636#include "Settings.h"
     37#include "TextBreakIterator.h"
    3738#include "TextRun.h"
    3839#include "TrailingFloatsRootInlineBox.h"
     
    672673        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
    673674
     675        LineBreakIteratorInfo lineBreakIteratorInfo;
    674676        VerticalPositionCache verticalPositionCache;
    675677
     
    688690            InlineIterator oldEnd = end;
    689691            FloatingObject* lastFloatFromPreviousLine = m_floatingObjects ? m_floatingObjects->last() : 0;
    690             end = findNextLineBreak(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, hyphenated, &clear, lastFloatFromPreviousLine);
     692            end = findNextLineBreak(resolver, firstLine, isLineEmpty, lineBreakIteratorInfo, previousLineBrokeCleanly, hyphenated, &clear, lastFloatFromPreviousLine);
    691693            if (resolver.position().atEnd()) {
    692694                resolver.deleteRuns();
     
    14421444}
    14431445
    1444 InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine,  bool& isLineEmpty, bool& previousLineBrokeCleanly,
     1446InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo& lineBreakIteratorInfo, bool& previousLineBrokeCleanly,
    14451447                                              bool& hyphenated, EClear* clear, FloatingObject* lastFloatFromPreviousLine)
    14461448{
     
    17331735                }
    17341736
    1735                 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(str, pos, strlen, nextBreakable, breakNBSP) && (style->hyphens() != HyphensNone || (pos && str[pos - 1] != softHyphen)));
     1737                if (lineBreakIteratorInfo.first != t) {
     1738                    lineBreakIteratorInfo.first = t;
     1739                    lineBreakIteratorInfo.second.reset(str, strlen);
     1740                }
     1741
     1742                bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, pos, nextBreakable, breakNBSP) && (style->hyphens() != HyphensNone || (pos && str[pos - 1] != softHyphen)));
    17361743
    17371744                if (betweenWords || midWordBreak) {
  • trunk/Source/WebCore/rendering/RenderText.cpp

    r79518 r79694  
    749749    int len = textLength();
    750750    const UChar* txt = characters();
     751    LazyLineBreakIterator breakIterator(txt, len);
    751752    bool needsWordSpacing = false;
    752753    bool ignoringSpaces = false;
     
    808809        }
    809810
    810         bool hasBreak = breakAll || isBreakable(txt, i, len, nextBreakable, breakNBSP);
     811        bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
    811812        bool betweenWords = true;
    812813        int j = i;
     
    816817                break;
    817818            c = txt[j];
    818             if (isBreakable(txt, j, len, nextBreakable, breakNBSP))
     819            if (isBreakable(breakIterator, j, nextBreakable, breakNBSP))
    819820                break;
    820821            if (breakAll) {
  • trunk/Source/WebCore/rendering/break_lines.cpp

    r79518 r79694  
    155155#endif
    156156
    157 int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakSpaceAsBreak)
     157int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos, bool treatNoBreakSpaceAsBreak)
    158158{
    159 #if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
    160     TextBreakIterator* breakIterator = 0;
    161 #endif
     159    const UChar* str = lazyBreakIterator.string();
     160    int len = lazyBreakIterator.length();
    162161    int nextBreak = -1;
    163162
     
    172171            if (nextBreak < i && i) {
    173172#if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
    174                 if (!breakIterator)
    175                     breakIterator = lineBreakIterator(str, len);
     173                TextBreakIterator* breakIterator = lazyBreakIterator.get();
    176174                if (breakIterator)
    177175                    nextBreak = textBreakFollowing(breakIterator, i - 1);
  • trunk/Source/WebCore/rendering/break_lines.h

    r79518 r79694  
    2626namespace WebCore {
    2727
    28     int nextBreakablePosition(const UChar*, int pos, int len, bool breakNBSP = false);
     28class LazyLineBreakIterator;
    2929
    30     inline bool isBreakable(const UChar* str, int pos, int len, int& nextBreakable, bool breakNBSP = false)
    31     {
    32         if (pos > nextBreakable)
    33             nextBreakable = nextBreakablePosition(str, pos, len, breakNBSP);
    34         return pos == nextBreakable;
    35     }
     30int nextBreakablePosition(LazyLineBreakIterator&, int pos, bool breakNBSP = false);
     31
     32inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP = false)
     33{
     34    if (pos > nextBreakable)
     35        nextBreakable = nextBreakablePosition(lazyBreakIterator, pos, breakNBSP);
     36    return pos == nextBreakable;
     37}
    3638
    3739} // namespace WebCore
Note: See TracChangeset for help on using the changeset viewer.