Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2013 Google, Inc. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "core/html/parser/BackgroundHTMLParser.h" | 26 #include "core/html/parser/BackgroundHTMLParser.h" |
| 27 | 27 |
| 28 #include <memory> | |
|
Yoav Weiss
2017/02/09 10:39:00
Do you know why is <memory> included both here and
Charlie Harrison
2017/02/13 22:55:31
It is for unique_ptr
Yoav Weiss
2017/02/14 06:45:47
Yeah, but I'd love to see it *only* in the h, and
Charlie Harrison
2017/02/15 03:00:07
Oh, no that is completely fair. I completely misre
| |
| 28 #include "core/HTMLNames.h" | 29 #include "core/HTMLNames.h" |
| 30 #include "core/dom/Document.h" | |
| 31 #include "core/dom/TaskRunnerHelper.h" | |
| 29 #include "core/html/parser/HTMLDocumentParser.h" | 32 #include "core/html/parser/HTMLDocumentParser.h" |
| 30 #include "core/html/parser/TextResourceDecoder.h" | 33 #include "core/html/parser/TextResourceDecoder.h" |
| 31 #include "core/html/parser/XSSAuditor.h" | 34 #include "core/html/parser/XSSAuditor.h" |
| 32 #include "platform/CrossThreadFunctional.h" | 35 #include "platform/CrossThreadFunctional.h" |
| 33 #include "platform/Histogram.h" | 36 #include "platform/Histogram.h" |
| 34 #include "platform/WebTaskRunner.h" | 37 #include "platform/WebTaskRunner.h" |
| 35 #include "platform/instrumentation/tracing/TraceEvent.h" | 38 #include "platform/instrumentation/tracing/TraceEvent.h" |
| 36 #include "public/platform/Platform.h" | 39 #include "public/platform/Platform.h" |
| 37 #include "wtf/CurrentTime.h" | 40 #include "wtf/CurrentTime.h" |
| 38 #include "wtf/Functional.h" | 41 #include "wtf/Functional.h" |
| 39 #include "wtf/PtrUtil.h" | 42 #include "wtf/PtrUtil.h" |
| 40 #include "wtf/text/TextPosition.h" | 43 #include "wtf/text/TextPosition.h" |
| 41 #include <memory> | |
| 42 | 44 |
| 43 namespace blink { | 45 namespace blink { |
| 44 | 46 |
| 45 // On a network with high latency and high bandwidth, using a device with a fast | 47 // On a network with high latency and high bandwidth, using a device with a fast |
| 46 // CPU, we could end up speculatively tokenizing the whole document, well ahead | 48 // CPU, we could end up speculatively tokenizing the whole document, well ahead |
| 47 // of when the main-thread actually needs it. This is a waste of memory (and | 49 // of when the main-thread actually needs it. This is a waste of memory (and |
| 48 // potentially time if the speculation fails). So we limit our outstanding | 50 // potentially time if the speculation fails). So we limit our outstanding |
| 49 // tokens arbitrarily to 10,000. Our maximal memory spent speculating will be | 51 // tokens arbitrarily to 10,000. Our maximal memory spent speculating will be |
| 50 // approximately: | 52 // approximately: |
| 51 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) * | 53 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) * |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 79 } | 81 } |
| 80 | 82 |
| 81 static void checkThatXSSInfosAreSafeToSendToAnotherThread( | 83 static void checkThatXSSInfosAreSafeToSendToAnotherThread( |
| 82 const XSSInfoStream& infos) { | 84 const XSSInfoStream& infos) { |
| 83 for (size_t i = 0; i < infos.size(); ++i) | 85 for (size_t i = 0; i < infos.size(); ++i) |
| 84 ASSERT(infos[i]->isSafeToSendToAnotherThread()); | 86 ASSERT(infos[i]->isSafeToSendToAnotherThread()); |
| 85 } | 87 } |
| 86 | 88 |
| 87 #endif | 89 #endif |
| 88 | 90 |
| 89 WeakPtr<BackgroundHTMLParser> BackgroundHTMLParser::create( | 91 BackgroundHTMLParser* BackgroundHTMLParser::create( |
| 90 std::unique_ptr<Configuration> config, | 92 HTMLDocumentParser* parser, |
| 91 RefPtr<WebTaskRunner> loadingTaskRunner) { | 93 Document& document, |
| 92 auto* backgroundParser = | 94 std::unique_ptr<Configuration> config) { |
| 93 new BackgroundHTMLParser(std::move(config), std::move(loadingTaskRunner)); | 95 return new BackgroundHTMLParser( |
| 94 return backgroundParser->m_weakFactory.createWeakPtr(); | 96 parser, std::move(config), |
| 97 TaskRunnerHelper::get(TaskType::Networking, &document), | |
| 98 WTF::makeUnique<TokenPreloadScanner>( | |
| 99 document.url(), CachedDocumentParameters::create(&document), | |
| 100 MediaValuesCached::MediaValuesCachedData(document))); | |
| 95 } | 101 } |
| 96 | 102 |
| 97 void BackgroundHTMLParser::init( | 103 DEFINE_TRACE(BackgroundHTMLParser) { |
| 98 const KURL& documentURL, | 104 visitor->trace(m_parser); |
| 99 std::unique_ptr<CachedDocumentParameters> cachedDocumentParameters, | |
| 100 const MediaValuesCached::MediaValuesCachedData& mediaValuesCachedData) { | |
| 101 m_preloadScanner.reset(new TokenPreloadScanner( | |
| 102 documentURL, std::move(cachedDocumentParameters), mediaValuesCachedData)); | |
| 103 } | 105 } |
| 104 | 106 |
| 105 BackgroundHTMLParser::Configuration::Configuration() | 107 BackgroundHTMLParser::Configuration::Configuration() |
| 106 : outstandingTokenLimit(defaultOutstandingTokenLimit), | 108 : outstandingTokenLimit(defaultOutstandingTokenLimit), |
| 107 pendingTokenLimit(defaultPendingTokenLimit), | 109 pendingTokenLimit(defaultPendingTokenLimit), |
| 108 shouldCoalesceChunks(false) {} | 110 shouldCoalesceChunks(false) {} |
| 109 | 111 |
| 110 BackgroundHTMLParser::BackgroundHTMLParser( | 112 BackgroundHTMLParser::BackgroundHTMLParser( |
| 113 HTMLDocumentParser* parser, | |
| 111 std::unique_ptr<Configuration> config, | 114 std::unique_ptr<Configuration> config, |
| 112 RefPtr<WebTaskRunner> loadingTaskRunner) | 115 RefPtr<WebTaskRunner> loadingTaskRunner, |
| 113 : m_weakFactory(this), | 116 std::unique_ptr<TokenPreloadScanner> scanner) |
| 114 m_token(WTF::wrapUnique(new HTMLToken)), | 117 : m_token(WTF::wrapUnique(new HTMLToken)), |
| 115 m_tokenizer(HTMLTokenizer::create(config->options)), | 118 m_tokenizer(HTMLTokenizer::create(config->options)), |
| 116 m_treeBuilderSimulator(config->options), | 119 m_treeBuilderSimulator(config->options), |
| 117 m_options(config->options), | 120 m_options(config->options), |
| 118 m_outstandingTokenLimit(config->outstandingTokenLimit), | 121 m_outstandingTokenLimit(config->outstandingTokenLimit), |
| 119 m_parser(config->parser), | 122 m_parser(parser), |
| 120 m_pendingTokens(WTF::wrapUnique(new CompactHTMLTokenStream)), | 123 m_pendingTokens(WTF::wrapUnique(new CompactHTMLTokenStream)), |
| 121 m_pendingTokenLimit(config->pendingTokenLimit), | 124 m_pendingTokenLimit(config->pendingTokenLimit), |
| 122 m_xssAuditor(std::move(config->xssAuditor)), | 125 m_xssAuditor(std::move(config->xssAuditor)), |
| 126 m_preloadScanner(std::move(scanner)), | |
| 123 m_decoder(std::move(config->decoder)), | 127 m_decoder(std::move(config->decoder)), |
| 124 m_loadingTaskRunner(std::move(loadingTaskRunner)), | 128 m_loadingTaskRunner(std::move(loadingTaskRunner)), |
| 125 m_tokenizedChunkQueue(std::move(config->tokenizedChunkQueue)), | 129 m_tokenizedChunkQueue(std::move(config->tokenizedChunkQueue)), |
| 126 m_pendingCSPMetaTokenIndex( | 130 m_pendingCSPMetaTokenIndex( |
| 127 HTMLDocumentParser::TokenizedChunk::noPendingToken), | 131 HTMLDocumentParser::TokenizedChunk::noPendingToken), |
| 128 m_startingScript(false), | 132 m_startingScript(false), |
| 129 m_lastBytesReceivedTime(0.0), | 133 m_lastBytesReceivedTime(0.0), |
| 130 m_shouldCoalesceChunks(config->shouldCoalesceChunks) { | 134 m_shouldCoalesceChunks(config->shouldCoalesceChunks) { |
| 131 ASSERT(m_outstandingTokenLimit > 0); | 135 ASSERT(m_outstandingTokenLimit > 0); |
| 132 ASSERT(m_pendingTokenLimit > 0); | 136 ASSERT(m_pendingTokenLimit > 0); |
| 133 ASSERT(m_outstandingTokenLimit >= m_pendingTokenLimit); | 137 ASSERT(m_outstandingTokenLimit >= m_pendingTokenLimit); |
| 134 } | 138 } |
| 135 | 139 |
| 136 BackgroundHTMLParser::~BackgroundHTMLParser() {} | 140 BackgroundHTMLParser::~BackgroundHTMLParser() {} |
| 137 | 141 |
| 138 void BackgroundHTMLParser::appendRawBytesFromMainThread( | 142 void BackgroundHTMLParser::appendRawBytesFromMainThread( |
| 139 std::unique_ptr<Vector<char>> buffer, | 143 std::unique_ptr<Vector<char>> buffer, |
| 140 double bytesReceivedTime) { | 144 double bytesReceivedTime) { |
| 141 ASSERT(m_decoder); | 145 ASSERT(m_decoder); |
| 142 m_lastBytesReceivedTime = bytesReceivedTime; | 146 m_lastBytesReceivedTime = bytesReceivedTime; |
| 143 DEFINE_STATIC_LOCAL(CustomCountHistogram, queueDelay, | 147 DEFINE_STATIC_LOCAL(CustomCountHistogram, queueDelay, |
| 144 ("Parser.AppendBytesDelay", 1, 5000, 50)); | 148 ("Parser.AppendBytesDelay", 1, 5000, 50)); |
| 145 queueDelay.count(monotonicallyIncreasingTimeMS() - bytesReceivedTime); | 149 queueDelay.count(monotonicallyIncreasingTimeMS() - bytesReceivedTime); |
| 146 updateDocument(m_decoder->decode(buffer->data(), buffer->size())); | 150 m_loadingTaskRunner->postTask( |
| 151 BLINK_FROM_HERE, | |
| 152 WTF::bind(&BackgroundHTMLParser::updateDocument, wrapPersistent(this), | |
| 153 m_decoder->decode(buffer->data(), buffer->size()))); | |
| 147 } | 154 } |
| 148 | 155 |
| 149 void BackgroundHTMLParser::appendDecodedBytes(const String& input) { | 156 void BackgroundHTMLParser::appendDecodedBytes(const String& input) { |
| 150 ASSERT(!m_input.current().isClosed()); | 157 ASSERT(!m_input.current().isClosed()); |
| 151 m_input.append(input); | 158 m_input.append(input); |
| 152 pumpTokenizer(); | 159 pumpTokenizer(); |
| 153 } | 160 } |
| 154 | 161 |
| 155 void BackgroundHTMLParser::setDecoder( | 162 void BackgroundHTMLParser::setDecoder( |
| 156 std::unique_ptr<TextResourceDecoder> decoder) { | 163 std::unique_ptr<TextResourceDecoder> decoder) { |
| 157 ASSERT(decoder); | 164 ASSERT(decoder); |
| 158 m_decoder = std::move(decoder); | 165 m_decoder = std::move(decoder); |
| 159 } | 166 } |
| 160 | 167 |
| 161 void BackgroundHTMLParser::flush() { | 168 void BackgroundHTMLParser::flush() { |
| 162 ASSERT(m_decoder); | 169 ASSERT(m_decoder); |
| 163 updateDocument(m_decoder->flush()); | 170 m_loadingTaskRunner->postTask( |
| 171 BLINK_FROM_HERE, WTF::bind(&BackgroundHTMLParser::updateDocument, | |
| 172 wrapPersistent(this), m_decoder->flush())); | |
| 164 } | 173 } |
| 165 | 174 |
| 166 void BackgroundHTMLParser::updateDocument(const String& decodedData) { | 175 void BackgroundHTMLParser::updateDocument(const String& decodedData) { |
| 167 DocumentEncodingData encodingData(*m_decoder.get()); | 176 DocumentEncodingData encodingData(*m_decoder.get()); |
| 168 | 177 |
| 169 if (encodingData != m_lastSeenEncodingData) { | 178 if (encodingData != m_lastSeenEncodingData) { |
| 170 m_lastSeenEncodingData = encodingData; | 179 m_lastSeenEncodingData = encodingData; |
| 171 | 180 |
| 172 m_xssAuditor->setEncoding(encodingData.encoding()); | 181 m_xssAuditor->setEncoding(encodingData.encoding()); |
| 173 runOnMainThread( | 182 m_parser->didReceiveEncodingDataFromBackgroundParser(encodingData); |
| 174 &HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, | |
| 175 m_parser, encodingData); | |
| 176 } | 183 } |
| 177 | 184 |
| 178 if (decodedData.isEmpty()) | 185 if (decodedData.isEmpty()) |
| 179 return; | 186 return; |
| 180 | 187 |
| 181 appendDecodedBytes(decodedData); | 188 appendDecodedBytes(decodedData); |
| 182 } | 189 } |
| 183 | 190 |
| 184 void BackgroundHTMLParser::resumeFrom(std::unique_ptr<Checkpoint> checkpoint) { | 191 void BackgroundHTMLParser::resumeFrom(std::unique_ptr<Checkpoint> checkpoint) { |
| 185 m_parser = checkpoint->parser; | 192 m_loadingTaskRunner->postTask( |
| 193 BLINK_FROM_HERE, | |
| 194 WTF::bind(&BackgroundHTMLParser::onResumeFrom, wrapPersistent(this), | |
| 195 WTF::passed(std::move(checkpoint)))); | |
|
Yoav Weiss
2017/02/09 10:39:00
Is this switch from sync to async calls related to
Charlie Harrison
2017/02/13 22:55:32
No, I'm also moving the postTasks from outside the
Yoav Weiss
2017/02/14 06:45:47
You can leave it as part of this patch
| |
| 196 } | |
| 197 | |
| 198 void BackgroundHTMLParser::onResumeFrom( | |
| 199 std::unique_ptr<Checkpoint> checkpoint) { | |
| 186 m_token = std::move(checkpoint->token); | 200 m_token = std::move(checkpoint->token); |
| 187 m_tokenizer = std::move(checkpoint->tokenizer); | 201 m_tokenizer = std::move(checkpoint->tokenizer); |
| 188 m_treeBuilderSimulator.setState(checkpoint->treeBuilderState); | 202 m_treeBuilderSimulator.setState(checkpoint->treeBuilderState); |
| 189 m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput); | 203 m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput); |
| 190 m_preloadScanner->rewindTo(checkpoint->preloadScannerCheckpoint); | 204 m_preloadScanner->rewindTo(checkpoint->preloadScannerCheckpoint); |
| 191 m_startingScript = false; | 205 m_startingScript = false; |
| 192 m_tokenizedChunkQueue->clear(); | 206 m_tokenizedChunkQueue->clear(); |
| 193 m_lastBytesReceivedTime = monotonicallyIncreasingTimeMS(); | 207 m_lastBytesReceivedTime = monotonicallyIncreasingTimeMS(); |
| 194 pumpTokenizer(); | 208 pumpTokenizer(); |
| 195 } | 209 } |
| 196 | 210 |
| 197 void BackgroundHTMLParser::startedChunkWithCheckpoint( | 211 void BackgroundHTMLParser::startedChunkWithCheckpoint( |
| 198 HTMLInputCheckpoint inputCheckpoint) { | 212 HTMLInputCheckpoint inputCheckpoint) { |
| 199 // Note, we should not have to worry about the index being invalid as messages | 213 // Note, we should not have to worry about the index being invalid as messages |
| 200 // from the main thread will be processed in FIFO order. | 214 // from the main thread will be processed in FIFO order. |
| 201 m_input.invalidateCheckpointsBefore(inputCheckpoint); | 215 m_input.invalidateCheckpointsBefore(inputCheckpoint); |
| 216 m_loadingTaskRunner->postTask( | |
| 217 BLINK_FROM_HERE, | |
| 218 WTF::bind(&BackgroundHTMLParser::pumpTokenizer, wrapPersistent(this))); | |
| 219 } | |
| 220 | |
| 221 void BackgroundHTMLParser::onFinish() { | |
| 222 markEndOfFile(); | |
| 202 pumpTokenizer(); | 223 pumpTokenizer(); |
| 203 } | 224 } |
| 204 | 225 |
| 205 void BackgroundHTMLParser::finish() { | 226 void BackgroundHTMLParser::finish() { |
| 206 markEndOfFile(); | 227 m_loadingTaskRunner->postTask( |
| 207 pumpTokenizer(); | 228 BLINK_FROM_HERE, |
| 208 } | 229 WTF::bind(&BackgroundHTMLParser::onFinish, wrapPersistent(this))); |
| 209 | |
| 210 void BackgroundHTMLParser::stop() { | |
| 211 delete this; | |
| 212 } | 230 } |
| 213 | 231 |
| 214 void BackgroundHTMLParser::forcePlaintextForTextDocument() { | 232 void BackgroundHTMLParser::forcePlaintextForTextDocument() { |
| 215 // This is only used by the TextDocumentParser (a subclass of | 233 // This is only used by the TextDocumentParser (a subclass of |
| 216 // HTMLDocumentParser) to force us into the PLAINTEXT state w/o using a | 234 // HTMLDocumentParser) to force us into the PLAINTEXT state w/o using a |
| 217 // <plaintext> tag. The TextDocumentParser uses a <pre> tag for historical / | 235 // <plaintext> tag. The TextDocumentParser uses a <pre> tag for historical / |
| 218 // compatibility reasons. | 236 // compatibility reasons. |
| 219 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 237 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 220 } | 238 } |
| 221 | 239 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 simulatedToken == HTMLTreeBuilderSimulator::Link || | 313 simulatedToken == HTMLTreeBuilderSimulator::Link || |
| 296 m_pendingTokens->size() >= m_pendingTokenLimit) { | 314 m_pendingTokens->size() >= m_pendingTokenLimit) { |
| 297 shouldNotifyMainThread |= queueChunkForMainThread(); | 315 shouldNotifyMainThread |= queueChunkForMainThread(); |
| 298 // If we're far ahead of the main thread, yield for a bit to avoid | 316 // If we're far ahead of the main thread, yield for a bit to avoid |
| 299 // consuming too much memory. | 317 // consuming too much memory. |
| 300 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit) | 318 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit) |
| 301 break; | 319 break; |
| 302 } | 320 } |
| 303 | 321 |
| 304 if (!m_shouldCoalesceChunks && shouldNotifyMainThread) { | 322 if (!m_shouldCoalesceChunks && shouldNotifyMainThread) { |
| 305 runOnMainThread(&HTMLDocumentParser::notifyPendingTokenizedChunks, | 323 m_parser->notifyPendingTokenizedChunks(); |
| 306 m_parser); | |
| 307 shouldNotifyMainThread = false; | 324 shouldNotifyMainThread = false; |
| 308 } | 325 } |
| 309 } | 326 } |
| 310 // Wait to notify the main thread about the chunks until we're at the limit. | 327 // Wait to notify the main thread about the chunks until we're at the limit. |
| 311 // This lets the background parser generate lots of valuable preloads before | 328 // This lets the background parser generate lots of valuable preloads before |
| 312 // anything expensive (extensions, scripts) take up time on the main thread. A | 329 // anything expensive (extensions, scripts) take up time on the main thread. A |
| 313 // busy main thread can cause preload delays. | 330 // busy main thread can cause preload delays. |
| 314 if (shouldNotifyMainThread) { | 331 if (shouldNotifyMainThread) { |
| 315 runOnMainThread(&HTMLDocumentParser::notifyPendingTokenizedChunks, | 332 m_parser->notifyPendingTokenizedChunks(); |
| 316 m_parser); | |
| 317 } | 333 } |
| 318 } | 334 } |
| 319 | 335 |
| 320 bool BackgroundHTMLParser::queueChunkForMainThread() { | 336 bool BackgroundHTMLParser::queueChunkForMainThread() { |
| 321 if (m_pendingTokens->isEmpty()) | 337 if (m_pendingTokens->isEmpty()) |
| 322 return false; | 338 return false; |
| 323 | 339 |
| 324 #if DCHECK_IS_ON() | 340 #if DCHECK_IS_ON() |
| 325 checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get()); | 341 checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get()); |
| 326 checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads); | 342 checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 bool isEmpty = m_tokenizedChunkQueue->enqueue(std::move(chunk)); | 377 bool isEmpty = m_tokenizedChunkQueue->enqueue(std::move(chunk)); |
| 362 | 378 |
| 363 DEFINE_STATIC_LOCAL(CustomCountHistogram, chunkEnqueueTime, | 379 DEFINE_STATIC_LOCAL(CustomCountHistogram, chunkEnqueueTime, |
| 364 ("Parser.ChunkEnqueueTime", 1, 10000, 50)); | 380 ("Parser.ChunkEnqueueTime", 1, 10000, 50)); |
| 365 chunkEnqueueTime.count(monotonicallyIncreasingTimeMS() - chunkStartTime); | 381 chunkEnqueueTime.count(monotonicallyIncreasingTimeMS() - chunkStartTime); |
| 366 | 382 |
| 367 m_pendingTokens = WTF::wrapUnique(new CompactHTMLTokenStream); | 383 m_pendingTokens = WTF::wrapUnique(new CompactHTMLTokenStream); |
| 368 return isEmpty; | 384 return isEmpty; |
| 369 } | 385 } |
| 370 | 386 |
| 371 // If the background parser is already running on the main thread, then it is | |
| 372 // not necessary to post a task to the main thread to run asynchronously. The | |
| 373 // main parser deals with chunking up its own work. | |
| 374 // TODO(csharrison): This is a pretty big hack because we don't actually need a | |
| 375 // CrossThreadClosure in these cases. This is just experimental. | |
| 376 template <typename FunctionType, typename... Ps> | |
| 377 void BackgroundHTMLParser::runOnMainThread(FunctionType function, | |
| 378 Ps&&... parameters) { | |
| 379 if (isMainThread()) { | |
| 380 (*WTF::bind(function, std::forward<Ps>(parameters)...))(); | |
| 381 } else { | |
| 382 m_loadingTaskRunner->postTask( | |
| 383 BLINK_FROM_HERE, | |
| 384 crossThreadBind(function, std::forward<Ps>(parameters)...)); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 } // namespace blink | 387 } // namespace blink |
| OLD | NEW |