提交 04bb022d 编写于 作者: A Adam Barth

Remove BackgroundHTMLInputStream

Now that we don't have checkpoints, we can just use SegmentedString directly.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/676763003
上级 c403da31
......@@ -944,8 +944,6 @@ sky_core_files = [
"html/imports/LinkImport.cpp",
"html/imports/LinkImport.h",
"html/parser/AtomicHTMLToken.h",
"html/parser/BackgroundHTMLInputStream.cpp",
"html/parser/BackgroundHTMLInputStream.h",
"html/parser/BackgroundHTMLParser.cpp",
"html/parser/BackgroundHTMLParser.h",
"html/parser/CompactHTMLToken.cpp",
......
/*
* Copyright (C) 2013 Google, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "core/html/parser/BackgroundHTMLInputStream.h"
namespace blink {
BackgroundHTMLInputStream::BackgroundHTMLInputStream()
: m_firstValidCheckpointIndex(0)
, m_firstValidSegmentIndex(0)
, m_totalCheckpointTokenCount(0)
{
}
void BackgroundHTMLInputStream::append(const String& input)
{
m_current.append(SegmentedString(input));
m_segments.append(input);
}
void BackgroundHTMLInputStream::close()
{
m_current.close();
}
HTMLInputCheckpoint BackgroundHTMLInputStream::createCheckpoint(size_t tokensExtractedSincePreviousCheckpoint)
{
HTMLInputCheckpoint checkpoint = m_checkpoints.size();
m_checkpoints.append(Checkpoint(m_segments.size(), tokensExtractedSincePreviousCheckpoint));
m_totalCheckpointTokenCount += tokensExtractedSincePreviousCheckpoint;
return checkpoint;
}
void BackgroundHTMLInputStream::invalidateCheckpointsBefore(HTMLInputCheckpoint newFirstValidCheckpointIndex)
{
ASSERT(newFirstValidCheckpointIndex < m_checkpoints.size());
// There is nothing to do for the first valid checkpoint.
if (m_firstValidCheckpointIndex == newFirstValidCheckpointIndex)
return;
ASSERT(newFirstValidCheckpointIndex > m_firstValidCheckpointIndex);
const Checkpoint& lastInvalidCheckpoint = m_checkpoints[newFirstValidCheckpointIndex - 1];
ASSERT(m_firstValidSegmentIndex <= lastInvalidCheckpoint.numberOfSegmentsAlreadyAppended);
for (size_t i = m_firstValidSegmentIndex; i < lastInvalidCheckpoint.numberOfSegmentsAlreadyAppended; ++i)
m_segments[i] = String();
m_firstValidSegmentIndex = lastInvalidCheckpoint.numberOfSegmentsAlreadyAppended;
for (size_t i = m_firstValidCheckpointIndex; i < newFirstValidCheckpointIndex; ++i)
m_checkpoints[i].clear();
m_firstValidCheckpointIndex = newFirstValidCheckpointIndex;
updateTotalCheckpointTokenCount();
}
void BackgroundHTMLInputStream::updateTotalCheckpointTokenCount()
{
m_totalCheckpointTokenCount = 0;
size_t lastCheckpointIndex = m_checkpoints.size();
for (size_t i = 0; i < lastCheckpointIndex; ++i)
m_totalCheckpointTokenCount += m_checkpoints[i].tokensExtractedSincePreviousCheckpoint;
}
}
/*
* Copyright (C) 2013 Google, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BackgroundHTMLInputStream_h
#define BackgroundHTMLInputStream_h
#include "platform/text/SegmentedString.h"
#include "wtf/Vector.h"
#include "wtf/text/WTFString.h"
namespace blink {
typedef size_t HTMLInputCheckpoint;
class BackgroundHTMLInputStream {
WTF_MAKE_NONCOPYABLE(BackgroundHTMLInputStream);
public:
BackgroundHTMLInputStream();
void append(const String&);
void close();
SegmentedString& current() { return m_current; }
// An HTMLInputCheckpoint is valid until the next call to rewindTo, at which
// point all outstanding checkpoints are invalidated.
HTMLInputCheckpoint createCheckpoint(size_t tokensExtractedSincePreviousCheckpoint);
void invalidateCheckpointsBefore(HTMLInputCheckpoint);
size_t totalCheckpointTokenCount() const { return m_totalCheckpointTokenCount; }
private:
struct Checkpoint {
Checkpoint(size_t n, size_t t) : numberOfSegmentsAlreadyAppended(n), tokensExtractedSincePreviousCheckpoint(t) { }
size_t numberOfSegmentsAlreadyAppended;
size_t tokensExtractedSincePreviousCheckpoint;
void clear() { numberOfSegmentsAlreadyAppended = 0; tokensExtractedSincePreviousCheckpoint = 0;}
};
SegmentedString m_current;
Vector<String> m_segments;
Vector<Checkpoint> m_checkpoints;
// Note: These indicies may === vector.size(), in which case there are no valid checkpoints/segments at this time.
size_t m_firstValidCheckpointIndex;
size_t m_firstValidSegmentIndex;
size_t m_totalCheckpointTokenCount;
void updateTotalCheckpointTokenCount();
};
}
#endif
......@@ -33,19 +33,6 @@
namespace blink {
// On a network with high latency and high bandwidth, using a device
// with a fast CPU, we could end up speculatively tokenizing
// the whole document, well ahead of when the main-thread actually needs it.
// This is a waste of memory (and potentially time if the speculation fails).
// So we limit our outstanding tokens arbitrarily to 10,000.
// Our maximal memory spent speculating will be approximately:
// (outstandingTokenLimit + pendingTokenLimit) * sizeof(CompactToken)
// We use a separate low and high water mark to avoid constantly topping
// off the main thread's token buffer.
// At time of writing, this is (10000 + 1000) * 28 bytes = ~308kb of memory.
// These numbers have not been tuned.
static const size_t outstandingTokenLimit = 10000;
// We limit our chucks to 1000 tokens, to make sure the main
// thread is never waiting on the parser thread for tokens.
// This was tuned in https://bugs.webkit.org/show_bug.cgi?id=110408.
......@@ -96,8 +83,8 @@ void BackgroundHTMLParser::appendRawBytesFromMainThread(PassOwnPtr<Vector<char>
void BackgroundHTMLParser::appendDecodedBytes(const String& input)
{
ASSERT(!m_input.current().isClosed());
m_input.append(input);
ASSERT(!m_input.isClosed());
m_input.append(SegmentedString(input));
pumpTokenizer();
}
......@@ -114,14 +101,6 @@ void BackgroundHTMLParser::updateDocument(const String& decodedData)
appendDecodedBytes(decodedData);
}
void BackgroundHTMLParser::startedChunkWithCheckpoint(HTMLInputCheckpoint inputCheckpoint)
{
// Note, we should not have to worry about the index being invalid
// as messages from the main thread will be processed in FIFO order.
m_input.invalidateCheckpointsBefore(inputCheckpoint);
pumpTokenizer();
}
void BackgroundHTMLParser::finish()
{
markEndOfFile();
......@@ -135,37 +114,29 @@ void BackgroundHTMLParser::stop()
void BackgroundHTMLParser::markEndOfFile()
{
ASSERT(!m_input.current().isClosed());
m_input.append(String(&kEndOfFileMarker, 1));
ASSERT(!m_input.isClosed());
m_input.append(SegmentedString(String(&kEndOfFileMarker, 1)));
m_input.close();
}
void BackgroundHTMLParser::pumpTokenizer()
{
// No need to start speculating until the main thread has almost caught up.
if (m_input.totalCheckpointTokenCount() > outstandingTokenLimit)
return;
while (true) {
if (!m_tokenizer->nextToken(m_input.current(), *m_token)) {
if (!m_tokenizer->nextToken(m_input, *m_token)) {
// We've reached the end of our current input.
sendTokensToMainThread();
break;
}
{
CompactHTMLToken token(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn()));
CompactHTMLToken token(m_token.get(), TextPosition(m_input.currentLine(), m_input.currentColumn()));
m_pendingTokens->append(token);
}
m_token->clear();
if (!m_treeBuilderSimulator.simulate(m_pendingTokens->last(), m_tokenizer.get()) || m_pendingTokens->size() >= pendingTokenLimit) {
if (!m_treeBuilderSimulator.simulate(m_pendingTokens->last(), m_tokenizer.get()) || m_pendingTokens->size() >= pendingTokenLimit)
sendTokensToMainThread();
// If we're far ahead of the main thread, yield for a bit to avoid consuming too much memory.
if (m_input.totalCheckpointTokenCount() > outstandingTokenLimit)
break;
}
}
}
......@@ -180,7 +151,6 @@ void BackgroundHTMLParser::sendTokensToMainThread()
OwnPtr<HTMLDocumentParser::ParsedChunk> chunk = adoptPtr(new HTMLDocumentParser::ParsedChunk);
chunk->tokenizerState = m_tokenizer->state();
chunk->inputCheckpoint = m_input.createCheckpoint(m_pendingTokens->size());
chunk->tokens = m_pendingTokens.release();
callOnMainThread(bind(&HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser, m_parser, chunk.release()));
......
......@@ -27,11 +27,11 @@
#define BackgroundHTMLParser_h
#include "base/memory/weak_ptr.h"
#include "core/html/parser/BackgroundHTMLInputStream.h"
#include "core/html/parser/CompactHTMLToken.h"
#include "core/html/parser/HTMLParserOptions.h"
#include "core/html/parser/HTMLTreeBuilderSimulator.h"
#include "core/html/parser/TextResourceDecoder.h"
#include "platform/text/SegmentedString.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/WeakPtr.h"
......@@ -54,7 +54,6 @@ public:
WeakPtr<HTMLDocumentParser> parser;
OwnPtr<HTMLToken> token;
OwnPtr<HTMLTokenizer> tokenizer;
HTMLInputCheckpoint inputCheckpoint;
String unparsedInput;
};
......@@ -63,7 +62,6 @@ public:
void appendRawBytesFromMainThread(PassOwnPtr<Vector<char> >);
void flush();
void resumeFrom(PassOwnPtr<Checkpoint>);
void startedChunkWithCheckpoint(HTMLInputCheckpoint);
void finish();
void stop();
......@@ -77,7 +75,7 @@ private:
void sendTokensToMainThread();
void updateDocument(const String& decodedData);
BackgroundHTMLInputStream m_input;
SegmentedString m_input;
OwnPtr<HTMLToken> m_token;
OwnPtr<HTMLTokenizer> m_tokenizer;
HTMLTreeBuilderSimulator m_treeBuilderSimulator;
......
......@@ -322,9 +322,6 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
OwnPtr<ParsedChunk> chunk(popChunk);
OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release();
HTMLParserThread::taskRunner()->PostTask(FROM_HERE,
base::Bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint));
for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != tokens->end(); ++it) {
ASSERT(!isWaitingForScripts());
......
......@@ -31,7 +31,6 @@
#include "core/dom/ScriptableDocumentParser.h"
#include "core/fetch/ResourceClient.h"
#include "core/frame/UseCounter.h"
#include "core/html/parser/BackgroundHTMLInputStream.h"
#include "core/html/parser/CompactHTMLToken.h"
#include "core/html/parser/HTMLInputStream.h"
#include "core/html/parser/HTMLParserOptions.h"
......@@ -85,7 +84,6 @@ public:
struct ParsedChunk {
OwnPtr<CompactHTMLTokenStream> tokens;
HTMLTokenizer::State tokenizerState;
HTMLInputCheckpoint inputCheckpoint;
};
void didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk>);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册