| 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" |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 return true; | 352 return true; |
| 353 } | 353 } |
| 354 // We don't stream other encodings; especially we don't stream two | 354 // We don't stream other encodings; especially we don't stream two |
| 355 // byte scripts to avoid the handling of endianness. Most scripts | 355 // byte scripts to avoid the handling of endianness. Most scripts |
| 356 // are Latin1 or UTF-8 anyway, so this should be enough for most | 356 // are Latin1 or UTF-8 anyway, so this should be enough for most |
| 357 // real world purposes. | 357 // real world purposes. |
| 358 return false; | 358 return false; |
| 359 } | 359 } |
| 360 | 360 |
| 361 bool ScriptStreamer::isFinished() const { | 361 bool ScriptStreamer::isFinished() const { |
| 362 MutexLocker locker(m_mutex); | 362 DCHECK(isMainThread()); |
| 363 return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed); | 363 return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed); |
| 364 } | 364 } |
| 365 | 365 |
| 366 void ScriptStreamer::streamingCompleteOnBackgroundThread() { | 366 void ScriptStreamer::streamingCompleteOnBackgroundThread() { |
| 367 DCHECK(!isMainThread()); | 367 DCHECK(!isMainThread()); |
| 368 { | |
| 369 MutexLocker locker(m_mutex); | |
| 370 m_parsingFinished = true; | |
| 371 } | |
| 372 | 368 |
| 373 // notifyFinished might already be called, or it might be called in the | 369 // notifyFinished might already be called, or it might be called in the |
| 374 // future (if the parsing finishes earlier because of a parse error). | 370 // future (if the parsing finishes earlier because of a parse error). |
| 375 m_loadingTaskRunner->postTask( | 371 m_loadingTaskRunner->postTask( |
| 376 BLINK_FROM_HERE, crossThreadBind(&ScriptStreamer::streamingComplete, | 372 BLINK_FROM_HERE, crossThreadBind(&ScriptStreamer::streamingComplete, |
| 377 wrapCrossThreadPersistent(this))); | 373 wrapCrossThreadPersistent(this))); |
| 378 | 374 |
| 379 // The task might delete ScriptStreamer, so it's not safe to do anything | 375 // The task might delete ScriptStreamer, so it's not safe to do anything |
| 380 // after posting it. Note that there's no way to guarantee that this | 376 // after posting it. Note that there's no way to guarantee that this |
| 381 // function has returned before the task is ran - however, we should not | 377 // function has returned before the task is ran - however, we should not |
| 382 // access the "this" object after posting the task. (Especially, we should | 378 // access the "this" object after posting the task. |
| 383 // not be holding the mutex at this point.) | |
| 384 } | 379 } |
| 385 | 380 |
| 386 void ScriptStreamer::cancel() { | 381 void ScriptStreamer::cancel() { |
| 387 DCHECK(isMainThread()); | 382 DCHECK(isMainThread()); |
| 388 // The upper layer doesn't need the script any more, but streaming might | 383 // The upper layer doesn't need the script any more, but streaming might |
| 389 // still be ongoing. Tell SourceStream to try to cancel it whenever it gets | 384 // still be ongoing. Tell SourceStream to try to cancel it whenever it gets |
| 390 // the control the next time. It can also be that V8 has already completed | 385 // the control the next time. It can also be that V8 has already completed |
| 391 // its operations and streamingComplete will be called soon. | 386 // its operations and streamingComplete will be called soon. |
| 392 m_detached = true; | 387 m_detached = true; |
| 393 m_resource = 0; | 388 m_resource = 0; |
| 394 if (m_stream) | 389 if (m_stream) |
| 395 m_stream->cancel(); | 390 m_stream->cancel(); |
| 396 } | 391 } |
| 397 | 392 |
| 398 void ScriptStreamer::suppressStreaming() { | 393 void ScriptStreamer::suppressStreaming() { |
| 399 MutexLocker locker(m_mutex); | 394 DCHECK(isMainThread()); |
| 400 DCHECK(!m_loadingFinished); | 395 DCHECK(!m_loadingFinished); |
| 401 // It can be that the parsing task has already finished (e.g., if there was | 396 // It can be that the parsing task has already finished (e.g., if there was |
| 402 // a parse error). | 397 // a parse error). |
| 403 m_streamingSuppressed = true; | 398 m_streamingSuppressed = true; |
| 404 } | 399 } |
| 405 | 400 |
| 406 void ScriptStreamer::notifyAppendData(ScriptResource* resource) { | 401 void ScriptStreamer::notifyAppendData(ScriptResource* resource) { |
| 407 DCHECK(isMainThread()); | 402 DCHECK(isMainThread()); |
| 408 CHECK_EQ(m_resource, resource); | 403 CHECK_EQ(m_resource, resource); |
| 409 { | 404 if (m_streamingSuppressed) |
| 410 MutexLocker locker(m_mutex); | 405 return; |
| 411 if (m_streamingSuppressed) | |
| 412 return; | |
| 413 } | |
| 414 if (!m_haveEnoughDataForStreaming) { | 406 if (!m_haveEnoughDataForStreaming) { |
| 415 // Even if the first data chunk is small, the script can still be big | 407 // Even if the first data chunk is small, the script can still be big |
| 416 // enough - wait until the next data chunk comes before deciding whether | 408 // enough - wait until the next data chunk comes before deciding whether |
| 417 // to start the streaming. | 409 // to start the streaming. |
| 418 DCHECK(resource->resourceBuffer()); | 410 DCHECK(resource->resourceBuffer()); |
| 419 if (resource->resourceBuffer()->size() < s_smallScriptThreshold) | 411 if (resource->resourceBuffer()->size() < s_smallScriptThreshold) |
| 420 return; | 412 return; |
| 421 m_haveEnoughDataForStreaming = true; | 413 m_haveEnoughDataForStreaming = true; |
| 422 | 414 |
| 423 { | 415 { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 | 538 |
| 547 DEFINE_TRACE(ScriptStreamer) { | 539 DEFINE_TRACE(ScriptStreamer) { |
| 548 visitor->trace(m_pendingScript); | 540 visitor->trace(m_pendingScript); |
| 549 visitor->trace(m_resource); | 541 visitor->trace(m_resource); |
| 550 } | 542 } |
| 551 | 543 |
| 552 void ScriptStreamer::streamingComplete() { | 544 void ScriptStreamer::streamingComplete() { |
| 553 // The background task is completed; do the necessary ramp-down in the main | 545 // The background task is completed; do the necessary ramp-down in the main |
| 554 // thread. | 546 // thread. |
| 555 DCHECK(isMainThread()); | 547 DCHECK(isMainThread()); |
| 548 m_parsingFinished = true; |
| 556 | 549 |
| 557 // It's possible that the corresponding Resource was deleted before V8 | 550 // It's possible that the corresponding Resource was deleted before V8 |
| 558 // finished streaming. In that case, the data or the notification is not | 551 // finished streaming. In that case, the data or the notification is not |
| 559 // needed. In addition, if the streaming is suppressed, the non-streaming | 552 // needed. In addition, if the streaming is suppressed, the non-streaming |
| 560 // code path will resume after the resource has loaded, before the | 553 // code path will resume after the resource has loaded, before the |
| 561 // background task finishes. | 554 // background task finishes. |
| 562 if (m_detached || m_streamingSuppressed) | 555 if (m_detached || m_streamingSuppressed) |
| 563 return; | 556 return; |
| 564 | 557 |
| 565 // We have now streamed the whole script to V8 and it has parsed the | 558 // We have now streamed the whole script to V8 and it has parsed the |
| 566 // script. We're ready for the next step: compiling and executing the | 559 // script. We're ready for the next step: compiling and executing the |
| 567 // script. | 560 // script. |
| 568 notifyFinishedToClient(); | 561 notifyFinishedToClient(); |
| 569 } | 562 } |
| 570 | 563 |
| 571 void ScriptStreamer::notifyFinishedToClient() { | 564 void ScriptStreamer::notifyFinishedToClient() { |
| 572 DCHECK(isMainThread()); | 565 DCHECK(isMainThread()); |
| 573 // Usually, the loading will be finished first, and V8 will still need some | 566 // Usually, the loading will be finished first, and V8 will still need some |
| 574 // time to catch up. But the other way is possible too: if V8 detects a | 567 // time to catch up. But the other way is possible too: if V8 detects a |
| 575 // parse error, the V8 side can complete before loading has finished. Send | 568 // parse error, the V8 side can complete before loading has finished. Send |
| 576 // the notification after both loading and V8 side operations have | 569 // the notification after both loading and V8 side operations have |
| 577 // completed. Here we also check that we have a client: it can happen that a | 570 // completed. |
| 578 // function calling notifyFinishedToClient was already scheduled in the task | |
| 579 // queue and the upper layer decided that it's not interested in the script | |
| 580 // and called removeClient. | |
| 581 if (!isFinished()) | 571 if (!isFinished()) |
| 582 return; | 572 return; |
| 583 | 573 |
| 584 m_pendingScript->streamingFinished(); | 574 m_pendingScript->streamingFinished(); |
| 585 } | 575 } |
| 586 | 576 |
| 587 bool ScriptStreamer::startStreamingInternal( | 577 bool ScriptStreamer::startStreamingInternal( |
| 588 PendingScript* script, | 578 PendingScript* script, |
| 589 Type scriptType, | 579 Type scriptType, |
| 590 Settings* settings, | 580 Settings* settings, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 // needed. This makes PendingScript notify the ScriptStreamer when it is | 613 // needed. This makes PendingScript notify the ScriptStreamer when it is |
| 624 // destroyed. | 614 // destroyed. |
| 625 script->setStreamer(ScriptStreamer::create(script, scriptType, scriptState, | 615 script->setStreamer(ScriptStreamer::create(script, scriptType, scriptState, |
| 626 compileOption, | 616 compileOption, |
| 627 std::move(loadingTaskRunner))); | 617 std::move(loadingTaskRunner))); |
| 628 | 618 |
| 629 return true; | 619 return true; |
| 630 } | 620 } |
| 631 | 621 |
| 632 } // namespace blink | 622 } // namespace blink |
| OLD | NEW |