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/Histogram.h" | 15 #include "platform/Histogram.h" |
16 #include "platform/SharedBuffer.h" | 16 #include "platform/SharedBuffer.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/WebScheduler.h" | 19 #include "public/platform/WebScheduler.h" |
| 20 #include "wtf/Deque.h" |
20 #include "wtf/text/TextEncodingRegistry.h" | 21 #include "wtf/text/TextEncodingRegistry.h" |
21 | 22 |
22 namespace blink { | 23 namespace blink { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 void recordStartedStreamingHistogram(ScriptStreamer::Type scriptType, int reason
) | 27 void recordStartedStreamingHistogram(ScriptStreamer::Type scriptType, int reason
) |
27 { | 28 { |
28 switch (scriptType) { | 29 switch (scriptType) { |
29 case ScriptStreamer::ParsingBlocking: { | 30 case ScriptStreamer::ParsingBlocking: { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 } | 150 } |
150 | 151 |
151 void discardQueuedData() | 152 void discardQueuedData() |
152 { | 153 { |
153 while (!m_data.isEmpty()) { | 154 while (!m_data.isEmpty()) { |
154 std::pair<const uint8_t*, size_t> next_data = m_data.takeFirst(); | 155 std::pair<const uint8_t*, size_t> next_data = m_data.takeFirst(); |
155 delete[] next_data.first; | 156 delete[] next_data.first; |
156 } | 157 } |
157 } | 158 } |
158 | 159 |
159 WTF::Deque<std::pair<const uint8_t*, size_t>> m_data; | 160 Deque<std::pair<const uint8_t*, size_t>> m_data; |
160 bool m_finished; | 161 bool m_finished; |
161 Mutex m_mutex; | 162 Mutex m_mutex; |
162 ThreadCondition m_haveData; | 163 ThreadCondition m_haveData; |
163 }; | 164 }; |
164 | 165 |
165 | 166 |
166 // SourceStream implements the streaming interface towards V8. The main | 167 // SourceStream implements the streaming interface towards V8. The main |
167 // functionality is preparing the data to give to V8 on main thread, and | 168 // functionality is preparing the data to give to V8 on main thread, and |
168 // actually giving the data (via GetMoreData which is called on a background | 169 // actually giving the data (via GetMoreData which is called on a background |
169 // thread). | 170 // thread). |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 return; | 523 return; |
523 } | 524 } |
524 | 525 |
525 ASSERT(!m_stream); | 526 ASSERT(!m_stream); |
526 ASSERT(!m_source); | 527 ASSERT(!m_source); |
527 m_stream = new SourceStream(m_loadingTaskRunner.get()); | 528 m_stream = new SourceStream(m_loadingTaskRunner.get()); |
528 // m_source takes ownership of m_stream. | 529 // m_source takes ownership of m_stream. |
529 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e
ncoding)); | 530 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e
ncoding)); |
530 | 531 |
531 ScriptState::Scope scope(m_scriptState.get()); | 532 ScriptState::Scope scope(m_scriptState.get()); |
532 WTF::OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask
(adoptPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_s
ource.get(), m_compileOptions))); | 533 OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask(adop
tPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_source
.get(), m_compileOptions))); |
533 if (!scriptStreamingTask) { | 534 if (!scriptStreamingTask) { |
534 // V8 cannot stream the script. | 535 // V8 cannot stream the script. |
535 suppressStreaming(); | 536 suppressStreaming(); |
536 m_stream = 0; | 537 m_stream = 0; |
537 m_source.clear(); | 538 m_source.clear(); |
538 recordNotStreamingReasonHistogram(m_scriptType, V8CannotStream); | 539 recordNotStreamingReasonHistogram(m_scriptType, V8CannotStream); |
539 recordStartedStreamingHistogram(m_scriptType, 0); | 540 recordStartedStreamingHistogram(m_scriptType, 0); |
540 return; | 541 return; |
541 } | 542 } |
542 | 543 |
543 // ScriptStreamer needs to stay alive as long as the background task is | |
544 // running. This is taken care of with a manual ref() & deref() pair; | |
545 // the corresponding deref() is in streamingComplete. | |
546 ref(); | |
547 ScriptStreamerThread::shared()->postTask(threadSafeBind(&ScriptStreamerT
hread::runScriptStreamingTask, scriptStreamingTask.release(), AllowCrossThreadAc
cess(this))); | 544 ScriptStreamerThread::shared()->postTask(threadSafeBind(&ScriptStreamerT
hread::runScriptStreamingTask, scriptStreamingTask.release(), AllowCrossThreadAc
cess(this))); |
548 recordStartedStreamingHistogram(m_scriptType, 1); | 545 recordStartedStreamingHistogram(m_scriptType, 1); |
549 } | 546 } |
550 if (m_stream) | 547 if (m_stream) |
551 m_stream->didReceiveData(this, lengthOfBOM); | 548 m_stream->didReceiveData(this, lengthOfBOM); |
552 } | 549 } |
553 | 550 |
554 void ScriptStreamer::notifyFinished(Resource* resource) | 551 void ScriptStreamer::notifyFinished(Resource* resource) |
555 { | 552 { |
556 ASSERT(isMainThread()); | 553 ASSERT(isMainThread()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 { | 605 { |
609 // The background task is completed; do the necessary ramp-down in the main | 606 // The background task is completed; do the necessary ramp-down in the main |
610 // thread. | 607 // thread. |
611 ASSERT(isMainThread()); | 608 ASSERT(isMainThread()); |
612 | 609 |
613 // It's possible that the corresponding Resource was deleted before V8 | 610 // It's possible that the corresponding Resource was deleted before V8 |
614 // finished streaming. In that case, the data or the notification is not | 611 // finished streaming. In that case, the data or the notification is not |
615 // needed. In addition, if the streaming is suppressed, the non-streaming | 612 // needed. In addition, if the streaming is suppressed, the non-streaming |
616 // code path will resume after the resource has loaded, before the | 613 // code path will resume after the resource has loaded, before the |
617 // background task finishes. | 614 // background task finishes. |
618 if (m_detached || m_streamingSuppressed) { | 615 if (m_detached || m_streamingSuppressed) |
619 deref(); | |
620 return; | 616 return; |
621 } | |
622 | 617 |
623 // We have now streamed the whole script to V8 and it has parsed the | 618 // We have now streamed the whole script to V8 and it has parsed the |
624 // script. We're ready for the next step: compiling and executing the | 619 // script. We're ready for the next step: compiling and executing the |
625 // script. | 620 // script. |
626 notifyFinishedToClient(); | 621 notifyFinishedToClient(); |
627 | |
628 // The background thread no longer holds an implicit reference. | |
629 deref(); | |
630 } | 622 } |
631 | 623 |
632 void ScriptStreamer::notifyFinishedToClient() | 624 void ScriptStreamer::notifyFinishedToClient() |
633 { | 625 { |
634 ASSERT(isMainThread()); | 626 ASSERT(isMainThread()); |
635 // Usually, the loading will be finished first, and V8 will still need some | 627 // Usually, the loading will be finished first, and V8 will still need some |
636 // time to catch up. But the other way is possible too: if V8 detects a | 628 // time to catch up. But the other way is possible too: if V8 detects a |
637 // parse error, the V8 side can complete before loading has finished. Send | 629 // parse error, the V8 side can complete before loading has finished. Send |
638 // the notification after both loading and V8 side operations have | 630 // the notification after both loading and V8 side operations have |
639 // completed. Here we also check that we have a client: it can happen that a | 631 // completed. Here we also check that we have a client: it can happen that a |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 | 670 |
679 // The Resource might go out of scope if the script is no longer | 671 // The Resource might go out of scope if the script is no longer |
680 // needed. This makes PendingScript notify the ScriptStreamer when it is | 672 // needed. This makes PendingScript notify the ScriptStreamer when it is |
681 // destroyed. | 673 // destroyed. |
682 script->setStreamer(ScriptStreamer::create(script, scriptType, scriptState,
compileOption, loadingTaskRunner)); | 674 script->setStreamer(ScriptStreamer::create(script, scriptType, scriptState,
compileOption, loadingTaskRunner)); |
683 | 675 |
684 return true; | 676 return true; |
685 } | 677 } |
686 | 678 |
687 } // namespace blink | 679 } // namespace blink |
OLD | NEW |