| 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 "bindings/core/v8/ScriptStreamer.h" | 5 #include "bindings/core/v8/ScriptStreamer.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScriptStreamerThread.h" | 7 #include "bindings/core/v8/ScriptStreamerThread.h" |
| 8 #include "bindings/core/v8/V8ScriptRunner.h" | 8 #include "bindings/core/v8/V8ScriptRunner.h" |
| 9 #include "core/dom/Document.h" | 9 #include "core/dom/Document.h" |
| 10 #include "core/dom/Element.h" | 10 #include "core/dom/Element.h" |
| 11 #include "core/dom/PendingScript.h" | 11 #include "core/dom/PendingScript.h" |
| 12 #include "core/fetch/ScriptResource.h" | 12 #include "core/fetch/ScriptResource.h" |
| 13 #include "core/frame/Settings.h" | 13 #include "core/frame/Settings.h" |
| 14 #include "core/html/parser/TextResourceDecoder.h" | 14 #include "core/html/parser/TextResourceDecoder.h" |
| 15 #include "platform/SharedBuffer.h" | 15 #include "platform/SharedBuffer.h" |
| 16 #include "platform/Task.h" | 16 #include "platform/Task.h" |
| 17 #include "platform/ThreadSafeFunctional.h" | 17 #include "platform/ThreadSafeFunctional.h" |
| 18 #include "platform/TraceEvent.h" | 18 #include "platform/TraceEvent.h" |
| 19 #include "public/platform/Platform.h" | 19 #include "public/platform/Platform.h" |
| 20 #include "public/platform/WebScheduler.h" | 20 #include "public/platform/WebScheduler.h" |
| 21 #include "wtf/MainThread.h" | 21 #include "wtf/MainThread.h" |
| 22 #include "wtf/text/TextEncodingRegistry.h" | 22 #include "wtf/text/TextEncodingRegistry.h" |
| 23 | 23 |
| 24 namespace blink { | 24 namespace blink { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 const char* startedStreamingHistogramName(PendingScript::Type scriptType) | 28 const char* startedStreamingHistogramName(ScriptStreamer::Type scriptType) |
| 29 { | 29 { |
| 30 switch (scriptType) { | 30 switch (scriptType) { |
| 31 case PendingScript::ParsingBlocking: | 31 case ScriptStreamer::ParsingBlocking: |
| 32 return "WebCore.Scripts.ParsingBlocking.StartedStreaming"; | 32 return "WebCore.Scripts.ParsingBlocking.StartedStreaming"; |
| 33 break; | 33 break; |
| 34 case PendingScript::Deferred: | 34 case ScriptStreamer::Deferred: |
| 35 return "WebCore.Scripts.Deferred.StartedStreaming"; | 35 return "WebCore.Scripts.Deferred.StartedStreaming"; |
| 36 break; | 36 break; |
| 37 case PendingScript::Async: | 37 case ScriptStreamer::Async: |
| 38 return "WebCore.Scripts.Async.StartedStreaming"; | 38 return "WebCore.Scripts.Async.StartedStreaming"; |
| 39 break; | 39 break; |
| 40 default: | 40 default: |
| 41 ASSERT_NOT_REACHED(); | 41 ASSERT_NOT_REACHED(); |
| 42 break; | 42 break; |
| 43 } | 43 } |
| 44 return 0; | 44 return 0; |
| 45 } | 45 } |
| 46 | 46 |
| 47 // For tracking why some scripts are not streamed. Not streaming is part of | 47 // For tracking why some scripts are not streamed. Not streaming is part of |
| 48 // normal operation (e.g., script already loaded, script too small) and doesn't | 48 // normal operation (e.g., script already loaded, script too small) and doesn't |
| 49 // necessarily indicate a failure. | 49 // necessarily indicate a failure. |
| 50 enum NotStreamingReason { | 50 enum NotStreamingReason { |
| 51 AlreadyLoaded, | 51 AlreadyLoaded, |
| 52 NotHTTP, | 52 NotHTTP, |
| 53 Reload, | 53 Reload, |
| 54 ContextNotValid, | 54 ContextNotValid, |
| 55 EncodingNotSupported, | 55 EncodingNotSupported, |
| 56 ThreadBusy, | 56 ThreadBusy, |
| 57 V8CannotStream, | 57 V8CannotStream, |
| 58 ScriptTooSmall, | 58 ScriptTooSmall, |
| 59 NotStreamingReasonEnd | 59 NotStreamingReasonEnd |
| 60 }; | 60 }; |
| 61 | 61 |
| 62 const char* notStreamingReasonHistogramName(PendingScript::Type scriptType) | 62 const char* notStreamingReasonHistogramName(ScriptStreamer::Type scriptType) |
| 63 { | 63 { |
| 64 switch (scriptType) { | 64 switch (scriptType) { |
| 65 case PendingScript::ParsingBlocking: | 65 case ScriptStreamer::ParsingBlocking: |
| 66 return "WebCore.Scripts.ParsingBlocking.NotStreamingReason"; | 66 return "WebCore.Scripts.ParsingBlocking.NotStreamingReason"; |
| 67 break; | 67 break; |
| 68 case PendingScript::Deferred: | 68 case ScriptStreamer::Deferred: |
| 69 return "WebCore.Scripts.Deferred.NotStreamingReason"; | 69 return "WebCore.Scripts.Deferred.NotStreamingReason"; |
| 70 break; | 70 break; |
| 71 case PendingScript::Async: | 71 case ScriptStreamer::Async: |
| 72 return "WebCore.Scripts.Async.NotStreamingReason"; | 72 return "WebCore.Scripts.Async.NotStreamingReason"; |
| 73 break; | 73 break; |
| 74 default: | 74 default: |
| 75 ASSERT_NOT_REACHED(); | 75 ASSERT_NOT_REACHED(); |
| 76 break; | 76 break; |
| 77 } | 77 } |
| 78 return 0; | 78 return 0; |
| 79 } | 79 } |
| 80 | 80 |
| 81 } // namespace | 81 } // namespace |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 // streaming case). | 370 // streaming case). |
| 371 // We store this separately, to avoid having to guard all | 371 // We store this separately, to avoid having to guard all |
| 372 // m_queueLeadPosition references with a mutex. | 372 // m_queueLeadPosition references with a mutex. |
| 373 size_t m_lengthOfBOM; // Used by both threads; guarded by m_mutex. | 373 size_t m_lengthOfBOM; // Used by both threads; guarded by m_mutex. |
| 374 | 374 |
| 375 OwnPtr<WebTaskRunner> m_loadingTaskRunner; | 375 OwnPtr<WebTaskRunner> m_loadingTaskRunner; |
| 376 }; | 376 }; |
| 377 | 377 |
| 378 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; | 378 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; |
| 379 | 379 |
| 380 void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type s
criptType, Settings* settings, ScriptState* scriptState, WebTaskRunner* loadingT
askRunner) | 380 void ScriptStreamer::startStreaming(PendingScript* script, Type scriptType, Sett
ings* settings, ScriptState* scriptState, WebTaskRunner* loadingTaskRunner) |
| 381 { | 381 { |
| 382 // We don't yet know whether the script will really be streamed. E.g., | 382 // We don't yet know whether the script will really be streamed. E.g., |
| 383 // suppressing streaming for short scripts is done later. Record only the | 383 // suppressing streaming for short scripts is done later. Record only the |
| 384 // sure negative cases here. | 384 // sure negative cases here. |
| 385 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState, loadingTaskRunner); | 385 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState, loadingTaskRunner); |
| 386 if (!startedStreaming) | 386 if (!startedStreaming) |
| 387 Platform::current()->histogramEnumeration(startedStreamingHistogramName(
scriptType), 0, 2); | 387 Platform::current()->histogramEnumeration(startedStreamingHistogramName(
scriptType), 0, 2); |
| 388 } | 388 } |
| 389 | 389 |
| 390 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile
r::StreamedSource::Encoding* encoding) | 390 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile
r::StreamedSource::Encoding* encoding) |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 m_stream->didFinishLoading(); | 560 m_stream->didFinishLoading(); |
| 561 m_loadingFinished = true; | 561 m_loadingFinished = true; |
| 562 | 562 |
| 563 // Calling notifyFinishedToClient can result into the upper layers dropping | 563 // Calling notifyFinishedToClient can result into the upper layers dropping |
| 564 // references to ScriptStreamer. Keep it alive until this function ends. | 564 // references to ScriptStreamer. Keep it alive until this function ends. |
| 565 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); | 565 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); |
| 566 | 566 |
| 567 notifyFinishedToClient(); | 567 notifyFinishedToClient(); |
| 568 } | 568 } |
| 569 | 569 |
| 570 ScriptStreamer::ScriptStreamer(ScriptResource* resource, PendingScript::Type scr
iptType, ScriptState* scriptState, v8::ScriptCompiler::CompileOptions compileOpt
ions, WebTaskRunner* loadingTaskRunner) | 570 ScriptStreamer::ScriptStreamer(ScriptResource* resource, Type scriptType, Script
State* scriptState, v8::ScriptCompiler::CompileOptions compileOptions, WebTaskRu
nner* loadingTaskRunner) |
| 571 : m_resource(resource) | 571 : m_resource(resource) |
| 572 , m_detached(false) | 572 , m_detached(false) |
| 573 , m_stream(0) | 573 , m_stream(0) |
| 574 , m_client(0) | 574 , m_client(0) |
| 575 , m_loadingFinished(false) | 575 , m_loadingFinished(false) |
| 576 , m_parsingFinished(false) | 576 , m_parsingFinished(false) |
| 577 , m_haveEnoughDataForStreaming(false) | 577 , m_haveEnoughDataForStreaming(false) |
| 578 , m_streamingSuppressed(false) | 578 , m_streamingSuppressed(false) |
| 579 , m_compileOptions(compileOptions) | 579 , m_compileOptions(compileOptions) |
| 580 , m_scriptState(scriptState) | 580 , m_scriptState(scriptState) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 // function calling notifyFinishedToClient was already scheduled in the task | 629 // function calling notifyFinishedToClient was already scheduled in the task |
| 630 // queue and the upper layer decided that it's not interested in the script | 630 // queue and the upper layer decided that it's not interested in the script |
| 631 // and called removeClient. | 631 // and called removeClient. |
| 632 if (!isFinished()) | 632 if (!isFinished()) |
| 633 return; | 633 return; |
| 634 | 634 |
| 635 if (m_client) | 635 if (m_client) |
| 636 m_client->notifyFinished(m_resource); | 636 m_client->notifyFinished(m_resource); |
| 637 } | 637 } |
| 638 | 638 |
| 639 bool ScriptStreamer::startStreamingInternal(PendingScript& script, PendingScript
::Type scriptType, Settings* settings, ScriptState* scriptState, WebTaskRunner*
loadingTaskRunner) | 639 bool ScriptStreamer::startStreamingInternal(PendingScript* script, Type scriptTy
pe, Settings* settings, ScriptState* scriptState, WebTaskRunner* loadingTaskRunn
er) |
| 640 { | 640 { |
| 641 ASSERT(isMainThread()); | 641 ASSERT(isMainThread()); |
| 642 ASSERT(scriptState->contextIsValid()); | 642 ASSERT(scriptState->contextIsValid()); |
| 643 ScriptResource* resource = script.resource(); | 643 ScriptResource* resource = script->resource(); |
| 644 if (resource->isLoaded()) { | 644 if (resource->isLoaded()) { |
| 645 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), AlreadyLoaded, NotStreamingReasonEnd); | 645 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), AlreadyLoaded, NotStreamingReasonEnd); |
| 646 return false; | 646 return false; |
| 647 } | 647 } |
| 648 if (!resource->url().protocolIsInHTTPFamily()) { | 648 if (!resource->url().protocolIsInHTTPFamily()) { |
| 649 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), NotHTTP, NotStreamingReasonEnd); | 649 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), NotHTTP, NotStreamingReasonEnd); |
| 650 return false; | 650 return false; |
| 651 } | 651 } |
| 652 if (resource->isCacheValidator()) { | 652 if (resource->isCacheValidator()) { |
| 653 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), Reload, NotStreamingReasonEnd); | 653 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), Reload, NotStreamingReasonEnd); |
| 654 // This happens e.g., during reloads. We're actually not going to load | 654 // This happens e.g., during reloads. We're actually not going to load |
| 655 // the current Resource of the PendingScript but switch to another | 655 // the current Resource of the PendingScript but switch to another |
| 656 // Resource -> don't stream. | 656 // Resource -> don't stream. |
| 657 return false; | 657 return false; |
| 658 } | 658 } |
| 659 // We cannot filter out short scripts, even if we wait for the HTTP headers | 659 // We cannot filter out short scripts, even if we wait for the HTTP headers |
| 660 // to arrive: the Content-Length HTTP header is not sent for chunked | 660 // to arrive: the Content-Length HTTP header is not sent for chunked |
| 661 // downloads. | 661 // downloads. |
| 662 | 662 |
| 663 // Decide what kind of cached data we should produce while streaming. Only | 663 // Decide what kind of cached data we should produce while streaming. Only |
| 664 // produce parser cache if the non-streaming compile takes advantage of it. | 664 // produce parser cache if the non-streaming compile takes advantage of it. |
| 665 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo
mpileOptions; | 665 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo
mpileOptions; |
| 666 if (settings->v8CacheOptions() == V8CacheOptionsParse) | 666 if (settings->v8CacheOptions() == V8CacheOptionsParse) |
| 667 compileOption = v8::ScriptCompiler::kProduceParserCache; | 667 compileOption = v8::ScriptCompiler::kProduceParserCache; |
| 668 | 668 |
| 669 // The Resource might go out of scope if the script is no longer | 669 // The Resource might go out of scope if the script is no longer |
| 670 // needed. This makes PendingScript notify the ScriptStreamer when it is | 670 // needed. This makes PendingScript notify the ScriptStreamer when it is |
| 671 // destroyed. | 671 // destroyed. |
| 672 script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState,
compileOption, loadingTaskRunner)); | 672 script->setStreamer(ScriptStreamer::create(resource, scriptType, scriptState
, compileOption, loadingTaskRunner)); |
| 673 | 673 |
| 674 return true; | 674 return true; |
| 675 } | 675 } |
| 676 | 676 |
| 677 } // namespace blink | 677 } // namespace blink |
| OLD | NEW |