Changeset 145277 in webkit


Ignore:
Timestamp:
Mar 8, 2013 3:39:25 PM (11 years ago)
Author:
eric@webkit.org
Message:

Free up background parser's checkpoints when speculation succeeds
https://bugs.webkit.org/show_bug.cgi?id=110547

Reviewed by Adam Barth.

This should be a memory (and possible perf) win while parsing
pages, as we will no longer hold multiple copies of every
source byte during the whole parse.

Many LayoutTests exercise this code path, and I've manually (debugger and printf)
that we're hitting this code, but we'll have to wait for the memory/perf bots
to tell us if this shows up as a win.

We only bother to message the parser at the end of a speculation chain, so as not
to send too many messages to the background parser.

  • html/parser/BackgroundHTMLInputStream.cpp:

(WebCore::BackgroundHTMLInputStream::BackgroundHTMLInputStream):
(WebCore::BackgroundHTMLInputStream::invalidateCheckpointsUpThrough):
(WebCore):
(WebCore::BackgroundHTMLInputStream::rewindTo):

  • html/parser/BackgroundHTMLInputStream.h:

(BackgroundHTMLInputStream):
(Checkpoint):
(WebCore::BackgroundHTMLInputStream::Checkpoint::isNull):
(WebCore::BackgroundHTMLInputStream::Checkpoint::clear):

  • html/parser/BackgroundHTMLParser.cpp:

(WebCore::BackgroundHTMLParser::passedCheckpoint):
(WebCore):

  • html/parser/BackgroundHTMLParser.h:

(BackgroundHTMLParser):

  • html/parser/HTMLDocumentParser.cpp:

(WebCore::HTMLDocumentParser::pumpPendingSpeculations):

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r145276 r145277  
     12013-03-08  Eric Seidel  <eric@webkit.org>
     2
     3        Free up background parser's checkpoints when speculation succeeds
     4        https://bugs.webkit.org/show_bug.cgi?id=110547
     5
     6        Reviewed by Adam Barth.
     7
     8        This should be a memory (and possible perf) win while parsing
     9        pages, as we will no longer hold multiple copies of every
     10        source byte during the whole parse.
     11
     12        Many LayoutTests exercise this code path, and I've manually (debugger and printf)
     13        that we're hitting this code, but we'll have to wait for the memory/perf bots
     14        to tell us if this shows up as a win.
     15
     16        We only bother to message the parser at the end of a speculation chain, so as not
     17        to send too many messages to the background parser.
     18
     19        * html/parser/BackgroundHTMLInputStream.cpp:
     20        (WebCore::BackgroundHTMLInputStream::BackgroundHTMLInputStream):
     21        (WebCore::BackgroundHTMLInputStream::invalidateCheckpointsUpThrough):
     22        (WebCore):
     23        (WebCore::BackgroundHTMLInputStream::rewindTo):
     24        * html/parser/BackgroundHTMLInputStream.h:
     25        (BackgroundHTMLInputStream):
     26        (Checkpoint):
     27        (WebCore::BackgroundHTMLInputStream::Checkpoint::isNull):
     28        (WebCore::BackgroundHTMLInputStream::Checkpoint::clear):
     29        * html/parser/BackgroundHTMLParser.cpp:
     30        (WebCore::BackgroundHTMLParser::passedCheckpoint):
     31        (WebCore):
     32        * html/parser/BackgroundHTMLParser.h:
     33        (BackgroundHTMLParser):
     34        * html/parser/HTMLDocumentParser.cpp:
     35        (WebCore::HTMLDocumentParser::pumpPendingSpeculations):
     36
    1372013-03-08  Chandra Shekar Vallala  <brk376@motorola.com>
    238
  • trunk/Source/WebCore/html/parser/BackgroundHTMLInputStream.cpp

    r144714 r145277  
    3333
    3434BackgroundHTMLInputStream::BackgroundHTMLInputStream()
     35    : m_firstValidCheckpointIndex(0)
     36    , m_firstValidSegmentIndex(0)
    3537{
    3638}
     
    5456}
    5557
     58void BackgroundHTMLInputStream::invalidateCheckpointsUpThrough(HTMLInputCheckpoint checkpointIndex)
     59{
     60    ASSERT(checkpointIndex < m_checkpoints.size());
     61    ASSERT(checkpointIndex >= m_firstValidCheckpointIndex);
     62    const Checkpoint& checkpoint = m_checkpoints[checkpointIndex];
     63    ASSERT(m_firstValidSegmentIndex <= checkpoint.numberOfSegmentsAlreadyAppended);
     64    for (size_t i = m_firstValidSegmentIndex; i < checkpoint.numberOfSegmentsAlreadyAppended; ++i)
     65        m_segments[i] = String();
     66    m_firstValidSegmentIndex = checkpoint.numberOfSegmentsAlreadyAppended;
     67
     68    for (size_t i = m_firstValidCheckpointIndex; i <= checkpointIndex; ++i)
     69        m_checkpoints[i].clear();
     70    m_firstValidCheckpointIndex = checkpointIndex + 1;
     71}
     72
    5673void BackgroundHTMLInputStream::rewindTo(HTMLInputCheckpoint checkpointIndex, const String& unparsedInput)
    5774{
    5875    ASSERT(checkpointIndex < m_checkpoints.size()); // If this ASSERT fires, checkpointIndex is invalid.
    5976    const Checkpoint& checkpoint = m_checkpoints[checkpointIndex];
     77    ASSERT(!checkpoint.isNull());
    6078
    6179    bool isClosed = m_current.isClosed();
     
    6381    m_current = checkpoint.input;
    6482
    65     for (size_t i = checkpoint.numberOfSegmentsAlreadyAppended; i < m_segments.size(); ++i)
     83    for (size_t i = checkpoint.numberOfSegmentsAlreadyAppended; i < m_segments.size(); ++i) {
     84        ASSERT(!m_segments[i].isNull());
    6685        m_current.append(SegmentedString(m_segments[i]));
     86    }
    6787
    6888    if (!unparsedInput.isEmpty())
     
    7696    m_segments.clear();
    7797    m_checkpoints.clear();
     98    m_firstValidCheckpointIndex = 0;
     99    m_firstValidSegmentIndex = 0;
    78100}
    79101
  • trunk/Source/WebCore/html/parser/BackgroundHTMLInputStream.h

    r142673 r145277  
    5151    HTMLInputCheckpoint createCheckpoint();
    5252    void rewindTo(HTMLInputCheckpoint, const String& unparsedInput);
     53    void invalidateCheckpointsUpThrough(HTMLInputCheckpoint);
    5354
    5455private:
     
    5859        SegmentedString input;
    5960        size_t numberOfSegmentsAlreadyAppended;
     61
     62#ifndef NDEBUG
     63        bool isNull() const { return input.isEmpty() && !numberOfSegmentsAlreadyAppended; }
     64#endif
     65        void clear() { input.clear(); numberOfSegmentsAlreadyAppended = 0; }
    6066    };
    6167
     
    6369    Vector<String> m_segments;
    6470    Vector<Checkpoint> m_checkpoints;
     71
     72    // Note: These indicies may === vector.size(), in which case there are no valid checkpoints/segments at this time.
     73    size_t m_firstValidCheckpointIndex;
     74    size_t m_firstValidSegmentIndex;
    6575};
    6676
  • trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp

    r144801 r145277  
    168168}
    169169
     170void BackgroundHTMLParser::passedCheckpoint(HTMLInputCheckpoint inputCheckpoint)
     171{
     172    // Note, we should not have to worry about the index being invalid
     173    // as messages from the main thread will be processed in FIFO order.
     174    m_input.invalidateCheckpointsUpThrough(inputCheckpoint);
     175}
     176
    170177void BackgroundHTMLParser::finish()
    171178{
  • trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h

    r144801 r145277  
    7575    void append(const String&);
    7676    void resumeFrom(PassOwnPtr<Checkpoint>);
     77    void passedCheckpoint(HTMLInputCheckpoint);
    7778    void finish();
    7879    void stop();
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp

    r145248 r145277  
    458458
    459459    double startTime = currentTime();
     460    HTMLInputCheckpoint lastCheckpointPassed = 0;
    460461
    461462    while (!m_speculations.isEmpty()) {
    462         processParsedChunkFromBackgroundParser(m_speculations.takeFirst());
    463 
    464         if (isWaitingForScripts() || isStopped())
     463        OwnPtr<ParsedChunk> chunk = m_speculations.takeFirst();
     464        lastCheckpointPassed = chunk->inputCheckpoint;
     465        processParsedChunkFromBackgroundParser(chunk.release());
     466
     467        // Processing a chunk can call document.write, causing us to invalidate any remaining speculations.
     468        if (m_speculations.isEmpty() || isStopped()) {
     469            // We're aborting these speculations, so don't tell the parser we've passed a checkpoint (its already cleared its checkpoints).
     470            lastCheckpointPassed = 0;
    465471            break;
    466 
    467         if (currentTime() - startTime > parserTimeLimit && !m_speculations.isEmpty()) {
     472        }
     473
     474        if (isWaitingForScripts())
     475            break;
     476
     477        if (currentTime() - startTime > parserTimeLimit) {
    468478            m_parserScheduler->scheduleForResume();
    469479            break;
    470480        }
    471481    }
     482
     483    if (lastCheckpointPassed)
     484        HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::passedCheckpoint, m_backgroundParser, lastCheckpointPassed));
    472485
    473486    InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt());
Note: See TracChangeset for help on using the changeset viewer.