Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "bindings/core/v8/ScriptStreamer.h" | 6 #include "bindings/core/v8/ScriptStreamer.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/ScriptStreamerThread.h" | 8 #include "bindings/core/v8/ScriptStreamerThread.h" |
| 9 #include "bindings/core/v8/V8ScriptRunner.h" | 9 #include "bindings/core/v8/V8ScriptRunner.h" |
| 10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
| 11 #include "core/dom/Element.h" | 11 #include "core/dom/Element.h" |
| 12 #include "core/dom/PendingScript.h" | 12 #include "core/dom/PendingScript.h" |
| 13 #include "core/fetch/ScriptResource.h" | 13 #include "core/fetch/ScriptResource.h" |
| 14 #include "core/frame/Settings.h" | 14 #include "core/frame/Settings.h" |
| 15 #include "core/html/parser/TextResourceDecoder.h" | 15 #include "core/html/parser/TextResourceDecoder.h" |
| 16 #include "platform/SharedBuffer.h" | 16 #include "platform/SharedBuffer.h" |
| 17 #include "platform/TraceEvent.h" | 17 #include "platform/TraceEvent.h" |
| 18 #include "public/platform/Platform.h" | 18 #include "public/platform/Platform.h" |
| 19 #include "wtf/MainThread.h" | 19 #include "wtf/MainThread.h" |
| 20 #include "wtf/text/TextEncodingRegistry.h" | 20 #include "wtf/text/TextEncodingRegistry.h" |
| 21 | 21 |
| 22 namespace blink { | 22 namespace blink { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 const char* kHistogramName = "WebCore.Scripts.Async.StartedStreaming"; | 25 const char* kStartedStreamingHistogramName = "WebCore.Scripts.Async.StartedStrea ming"; |
| 26 const char* kNotStreamingReasonHistogramName = "WebCore.Scripts.Async.NotStreami ngReason"; | |
| 26 } | 27 } |
| 27 | 28 |
| 28 // For passing data between the main thread (producer) and the streamer thread | 29 // For passing data between the main thread (producer) and the streamer thread |
| 29 // (consumer). The main thread prepares the data (copies it from Resource) and | 30 // (consumer). The main thread prepares the data (copies it from Resource) and |
| 30 // the streamer thread feeds it to V8. | 31 // the streamer thread feeds it to V8. |
| 31 class SourceStreamDataQueue { | 32 class SourceStreamDataQueue { |
| 32 WTF_MAKE_NONCOPYABLE(SourceStreamDataQueue); | 33 WTF_MAKE_NONCOPYABLE(SourceStreamDataQueue); |
| 33 public: | 34 public: |
| 34 SourceStreamDataQueue() | 35 SourceStreamDataQueue() |
| 35 : m_finished(false) { } | 36 : m_finished(false) { } |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 | 223 |
| 223 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; | 224 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; |
| 224 | 225 |
| 225 void ScriptStreamer::startStreaming(PendingScript& script, Settings* settings, S criptState* scriptState) | 226 void ScriptStreamer::startStreaming(PendingScript& script, Settings* settings, S criptState* scriptState) |
| 226 { | 227 { |
| 227 // We don't yet know whether the script will really be streamed. E.g., | 228 // We don't yet know whether the script will really be streamed. E.g., |
| 228 // suppressing streaming for short scripts is done later. Record only the | 229 // suppressing streaming for short scripts is done later. Record only the |
| 229 // sure negative cases here. | 230 // sure negative cases here. |
| 230 bool startedStreaming = startStreamingInternal(script, settings, scriptState ); | 231 bool startedStreaming = startStreamingInternal(script, settings, scriptState ); |
| 231 if (!startedStreaming) | 232 if (!startedStreaming) |
| 232 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 233 blink::Platform::current()->histogramEnumeration(kStartedStreamingHistog ramName, 0, 2); |
| 233 } | 234 } |
| 234 | 235 |
| 235 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile r::StreamedSource::Encoding* encoding) | 236 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile r::StreamedSource::Encoding* encoding) |
| 236 { | 237 { |
| 237 // Here's a list of encodings we can use for streaming. These are | 238 // Here's a list of encodings we can use for streaming. These are |
| 238 // the canonical names. | 239 // the canonical names. |
| 239 if (strcmp(encodingName, "windows-1252") == 0 | 240 if (strcmp(encodingName, "windows-1252") == 0 |
| 240 || strcmp(encodingName, "ISO-8859-1") == 0 | 241 || strcmp(encodingName, "ISO-8859-1") == 0 |
| 241 || strcmp(encodingName, "US-ASCII") == 0) { | 242 || strcmp(encodingName, "US-ASCII") == 0) { |
| 242 *encoding = v8::ScriptCompiler::StreamedSource::ONE_BYTE; | 243 *encoding = v8::ScriptCompiler::StreamedSource::ONE_BYTE; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 const char* data = 0; | 317 const char* data = 0; |
| 317 unsigned length = resource->resourceBuffer()->getSomeData(data, 0); | 318 unsigned length = resource->resourceBuffer()->getSomeData(data, 0); |
| 318 | 319 |
| 319 OwnPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("applica tion/javascript", resource->encoding())); | 320 OwnPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("applica tion/javascript", resource->encoding())); |
| 320 lengthOfBOM = decoder->checkForBOM(data, length); | 321 lengthOfBOM = decoder->checkForBOM(data, length); |
| 321 | 322 |
| 322 // Maybe the encoding changed because we saw the BOM; get the encoding | 323 // Maybe the encoding changed because we saw the BOM; get the encoding |
| 323 // from the decoder. | 324 // from the decoder. |
| 324 if (!convertEncoding(decoder->encoding().name(), &m_encoding)) { | 325 if (!convertEncoding(decoder->encoding().name(), &m_encoding)) { |
| 325 suppressStreaming(); | 326 suppressStreaming(); |
| 326 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 327 blink::Platform::current()->histogramEnumeration(kNotStreamingReason HistogramName, 4, 8); |
| 328 blink::Platform::current()->histogramEnumeration(kStartedStreamingHi stogramName, 0, 2); | |
| 327 return; | 329 return; |
| 328 } | 330 } |
| 329 if (ScriptStreamerThread::shared()->isRunningTask()) { | 331 if (ScriptStreamerThread::shared()->isRunningTask()) { |
| 330 // At the moment we only have one thread for running the tasks. A | 332 // At the moment we only have one thread for running the tasks. A |
| 331 // new task shouldn't be queued before the running task completes, | 333 // new task shouldn't be queued before the running task completes, |
| 332 // because the running task can block and wait for data from the | 334 // because the running task can block and wait for data from the |
| 333 // network. | 335 // network. |
| 334 suppressStreaming(); | 336 suppressStreaming(); |
| 335 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 337 blink::Platform::current()->histogramEnumeration(kNotStreamingReason HistogramName, 5, 8); |
| 338 blink::Platform::current()->histogramEnumeration(kStartedStreamingHi stogramName, 0, 2); | |
| 336 return; | 339 return; |
| 337 } | 340 } |
| 338 | 341 |
| 339 if (!m_scriptState->contextIsValid()) { | 342 if (!m_scriptState->contextIsValid()) { |
| 340 suppressStreaming(); | 343 suppressStreaming(); |
| 341 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 344 blink::Platform::current()->histogramEnumeration(kNotStreamingReason HistogramName, 3, 8); |
| 345 blink::Platform::current()->histogramEnumeration(kStartedStreamingHi stogramName, 0, 2); | |
| 342 return; | 346 return; |
| 343 } | 347 } |
| 344 | 348 |
| 345 ASSERT(!m_stream); | 349 ASSERT(!m_stream); |
| 346 ASSERT(!m_source); | 350 ASSERT(!m_source); |
| 347 m_stream = new SourceStream(); | 351 m_stream = new SourceStream(); |
| 348 // m_source takes ownership of m_stream. | 352 // m_source takes ownership of m_stream. |
| 349 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e ncoding)); | 353 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e ncoding)); |
| 350 | 354 |
| 351 ScriptState::Scope scope(m_scriptState.get()); | 355 ScriptState::Scope scope(m_scriptState.get()); |
| 352 WTF::OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask (adoptPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_s ource.get(), m_compileOptions))); | 356 WTF::OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask (adoptPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_s ource.get(), m_compileOptions))); |
| 353 if (!scriptStreamingTask) { | 357 if (!scriptStreamingTask) { |
| 354 // V8 cannot stream the script. | 358 // V8 cannot stream the script. |
| 355 suppressStreaming(); | 359 suppressStreaming(); |
| 356 m_stream = 0; | 360 m_stream = 0; |
| 357 m_source.clear(); | 361 m_source.clear(); |
| 358 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 362 blink::Platform::current()->histogramEnumeration(kNotStreamingReason HistogramName, 6, 8); |
| 363 blink::Platform::current()->histogramEnumeration(kStartedStreamingHi stogramName, 0, 2); | |
| 359 return; | 364 return; |
| 360 } | 365 } |
| 361 | 366 |
| 362 // ScriptStreamer needs to stay alive as long as the background task is | 367 // ScriptStreamer needs to stay alive as long as the background task is |
| 363 // running. This is taken care of with a manual ref() & deref() pair; | 368 // running. This is taken care of with a manual ref() & deref() pair; |
| 364 // the corresponding deref() is in streamingComplete. | 369 // the corresponding deref() is in streamingComplete. |
| 365 ref(); | 370 ref(); |
| 366 ScriptStreamingTask* task = new ScriptStreamingTask(scriptStreamingTask. release(), this); | 371 ScriptStreamingTask* task = new ScriptStreamingTask(scriptStreamingTask. release(), this); |
| 367 ScriptStreamerThread::shared()->postTask(task); | 372 ScriptStreamerThread::shared()->postTask(task); |
| 368 blink::Platform::current()->histogramEnumeration(kHistogramName, 1, 2); | 373 blink::Platform::current()->histogramEnumeration(kStartedStreamingHistog ramName, 1, 2); |
| 369 } | 374 } |
| 370 if (m_stream) | 375 if (m_stream) |
| 371 m_stream->didReceiveData(this, lengthOfBOM); | 376 m_stream->didReceiveData(this, lengthOfBOM); |
| 372 } | 377 } |
| 373 | 378 |
| 374 void ScriptStreamer::notifyFinished(Resource* resource) | 379 void ScriptStreamer::notifyFinished(Resource* resource) |
| 375 { | 380 { |
| 376 ASSERT(isMainThread()); | 381 ASSERT(isMainThread()); |
| 377 ASSERT(m_resource == resource); | 382 ASSERT(m_resource == resource); |
| 378 // A special case: empty and small scripts. We didn't receive enough data to | 383 // A special case: empty and small scripts. We didn't receive enough data to |
| 379 // start the streaming before this notification. In that case, there won't | 384 // start the streaming before this notification. In that case, there won't |
| 380 // be a "parsing complete" notification either, and we should not wait for | 385 // be a "parsing complete" notification either, and we should not wait for |
| 381 // it. | 386 // it. |
| 382 if (!m_haveEnoughDataForStreaming) { | 387 if (!m_haveEnoughDataForStreaming) { |
| 383 blink::Platform::current()->histogramEnumeration(kHistogramName, 0, 2); | 388 blink::Platform::current()->histogramEnumeration(kNotStreamingReasonHist ogramName, 7, 8); |
| 389 blink::Platform::current()->histogramEnumeration(kStartedStreamingHistog ramName, 0, 2); | |
| 384 suppressStreaming(); | 390 suppressStreaming(); |
| 385 } | 391 } |
| 386 if (m_stream) | 392 if (m_stream) |
| 387 m_stream->didFinishLoading(); | 393 m_stream->didFinishLoading(); |
| 388 m_loadingFinished = true; | 394 m_loadingFinished = true; |
| 389 | 395 |
| 390 // Calling notifyFinishedToClient can result into the upper layers dropping | 396 // Calling notifyFinishedToClient can result into the upper layers dropping |
| 391 // references to ScriptStreamer. Keep it alive until this function ends. | 397 // references to ScriptStreamer. Keep it alive until this function ends. |
| 392 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); | 398 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); |
| 393 | 399 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 return; | 466 return; |
| 461 } | 467 } |
| 462 if (m_client) | 468 if (m_client) |
| 463 m_client->notifyFinished(m_resource); | 469 m_client->notifyFinished(m_resource); |
| 464 } | 470 } |
| 465 | 471 |
| 466 bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* set tings, ScriptState* scriptState) | 472 bool ScriptStreamer::startStreamingInternal(PendingScript& script, Settings* set tings, ScriptState* scriptState) |
| 467 { | 473 { |
| 468 ASSERT(isMainThread()); | 474 ASSERT(isMainThread()); |
| 469 ScriptResource* resource = script.resource(); | 475 ScriptResource* resource = script.resource(); |
| 470 if (resource->isLoaded()) | 476 if (resource->isLoaded()) { |
| 477 blink::Platform::current()->histogramEnumeration(kNotStreamingReasonHist ogramName, 0, 8); | |
| 471 return false; | 478 return false; |
| 472 if (!resource->url().protocolIsInHTTPFamily()) | 479 } |
| 480 if (!resource->url().protocolIsInHTTPFamily()) { | |
| 481 blink::Platform::current()->histogramEnumeration(kNotStreamingReasonHist ogramName, 1, 8); | |
| 473 return false; | 482 return false; |
| 483 } | |
| 474 if (resource->resourceToRevalidate()) { | 484 if (resource->resourceToRevalidate()) { |
| 485 blink::Platform::current()->histogramEnumeration(kNotStreamingReasonHist ogramName, 2, 8); | |
| 475 // This happens e.g., during reloads. We're actually not going to load | 486 // This happens e.g., during reloads. We're actually not going to load |
| 476 // the current Resource of the PendingScript but switch to another | 487 // the current Resource of the PendingScript but switch to another |
| 477 // Resource -> don't stream. | 488 // Resource -> don't stream. |
| 478 return false; | 489 return false; |
| 479 } | 490 } |
| 480 // We cannot filter out short scripts, even if we wait for the HTTP headers | 491 // We cannot filter out short scripts, even if we wait for the HTTP headers |
| 481 // to arrive: the Content-Length HTTP header is not sent for chunked | 492 // to arrive: the Content-Length HTTP header is not sent for chunked |
| 482 // downloads. | 493 // downloads. |
| 483 | 494 |
| 484 if (!scriptState->contextIsValid()) | 495 if (!scriptState->contextIsValid()) { |
| 496 blink::Platform::current()->histogramEnumeration(kNotStreamingReasonHist ogramName, 3, 8); | |
|
Ilya Sherman
2015/03/23 22:14:44
Could you please use enumerated constant names, ra
| |
| 485 return false; | 497 return false; |
| 498 } | |
| 486 | 499 |
| 487 // Decide what kind of cached data we should produce while streaming. By | 500 // Decide what kind of cached data we should produce while streaming. By |
| 488 // default, we generate the parser cache for streamed scripts, to emulate | 501 // default, we generate the parser cache for streamed scripts, to emulate |
| 489 // the non-streaming behavior (see V8ScriptRunner::compileScript). | 502 // the non-streaming behavior (see V8ScriptRunner::compileScript). |
| 490 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProd uceParserCache; | 503 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kProd uceParserCache; |
| 491 if (settings->v8CacheOptions() == V8CacheOptionsCode || settings->v8CacheOpt ions() == V8CacheOptionsCodeCompressed) | 504 if (settings->v8CacheOptions() == V8CacheOptionsCode || settings->v8CacheOpt ions() == V8CacheOptionsCodeCompressed) |
| 492 compileOption = v8::ScriptCompiler::kProduceCodeCache; | 505 compileOption = v8::ScriptCompiler::kProduceCodeCache; |
| 493 | 506 |
| 494 // The Resource might go out of scope if the script is no longer | 507 // The Resource might go out of scope if the script is no longer |
| 495 // needed. This makes PendingScript notify the ScriptStreamer when it is | 508 // needed. This makes PendingScript notify the ScriptStreamer when it is |
| 496 // destroyed. | 509 // destroyed. |
| 497 script.setStreamer(ScriptStreamer::create(resource, scriptState, compileOpti on)); | 510 script.setStreamer(ScriptStreamer::create(resource, scriptState, compileOpti on)); |
| 498 | 511 |
| 499 return true; | 512 return true; |
| 500 } | 513 } |
| 501 | 514 |
| 502 } // namespace blink | 515 } // namespace blink |
| OLD | NEW |