| 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" |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 | 276 |
| 277 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; | 277 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; |
| 278 | 278 |
| 279 void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type s
criptType, Settings* settings, ScriptState* scriptState) | 279 void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type s
criptType, Settings* settings, ScriptState* scriptState) |
| 280 { | 280 { |
| 281 // We don't yet know whether the script will really be streamed. E.g., | 281 // We don't yet know whether the script will really be streamed. E.g., |
| 282 // suppressing streaming for short scripts is done later. Record only the | 282 // suppressing streaming for short scripts is done later. Record only the |
| 283 // sure negative cases here. | 283 // sure negative cases here. |
| 284 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState); | 284 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState); |
| 285 if (!startedStreaming) | 285 if (!startedStreaming) |
| 286 blink::Platform::current()->histogramEnumeration(startedStreamingHistogr
amName(scriptType), 0, 2); | 286 Platform::current()->histogramEnumeration(startedStreamingHistogramName(
scriptType), 0, 2); |
| 287 } | 287 } |
| 288 | 288 |
| 289 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile
r::StreamedSource::Encoding* encoding) | 289 bool ScriptStreamer::convertEncoding(const char* encodingName, v8::ScriptCompile
r::StreamedSource::Encoding* encoding) |
| 290 { | 290 { |
| 291 // Here's a list of encodings we can use for streaming. These are | 291 // Here's a list of encodings we can use for streaming. These are |
| 292 // the canonical names. | 292 // the canonical names. |
| 293 if (strcmp(encodingName, "windows-1252") == 0 | 293 if (strcmp(encodingName, "windows-1252") == 0 |
| 294 || strcmp(encodingName, "ISO-8859-1") == 0 | 294 || strcmp(encodingName, "ISO-8859-1") == 0 |
| 295 || strcmp(encodingName, "US-ASCII") == 0) { | 295 || strcmp(encodingName, "US-ASCII") == 0) { |
| 296 *encoding = v8::ScriptCompiler::StreamedSource::ONE_BYTE; | 296 *encoding = v8::ScriptCompiler::StreamedSource::ONE_BYTE; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 const char* data = 0; | 378 const char* data = 0; |
| 379 unsigned length = resource->resourceBuffer()->getSomeData(data, 0); | 379 unsigned length = resource->resourceBuffer()->getSomeData(data, 0); |
| 380 | 380 |
| 381 OwnPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("applica
tion/javascript", resource->encoding())); | 381 OwnPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("applica
tion/javascript", resource->encoding())); |
| 382 lengthOfBOM = decoder->checkForBOM(data, length); | 382 lengthOfBOM = decoder->checkForBOM(data, length); |
| 383 | 383 |
| 384 // Maybe the encoding changed because we saw the BOM; get the encoding | 384 // Maybe the encoding changed because we saw the BOM; get the encoding |
| 385 // from the decoder. | 385 // from the decoder. |
| 386 if (!convertEncoding(decoder->encoding().name(), &m_encoding)) { | 386 if (!convertEncoding(decoder->encoding().name(), &m_encoding)) { |
| 387 suppressStreaming(); | 387 suppressStreaming(); |
| 388 blink::Platform::current()->histogramEnumeration(notStreamingReasonH
istogramName(m_scriptType), EncodingNotSupported, NotStreamingReasonEnd); | 388 Platform::current()->histogramEnumeration(notStreamingReasonHistogra
mName(m_scriptType), EncodingNotSupported, NotStreamingReasonEnd); |
| 389 blink::Platform::current()->histogramEnumeration(startedStreamingHis
togramName(m_scriptType), 0, 2); | 389 Platform::current()->histogramEnumeration(startedStreamingHistogramN
ame(m_scriptType), 0, 2); |
| 390 return; | 390 return; |
| 391 } | 391 } |
| 392 if (ScriptStreamerThread::shared()->isRunningTask()) { | 392 if (ScriptStreamerThread::shared()->isRunningTask()) { |
| 393 // At the moment we only have one thread for running the tasks. A | 393 // At the moment we only have one thread for running the tasks. A |
| 394 // new task shouldn't be queued before the running task completes, | 394 // new task shouldn't be queued before the running task completes, |
| 395 // because the running task can block and wait for data from the | 395 // because the running task can block and wait for data from the |
| 396 // network. | 396 // network. |
| 397 suppressStreaming(); | 397 suppressStreaming(); |
| 398 blink::Platform::current()->histogramEnumeration(notStreamingReasonH
istogramName(m_scriptType), ThreadBusy, NotStreamingReasonEnd); | 398 Platform::current()->histogramEnumeration(notStreamingReasonHistogra
mName(m_scriptType), ThreadBusy, NotStreamingReasonEnd); |
| 399 blink::Platform::current()->histogramEnumeration(startedStreamingHis
togramName(m_scriptType), 0, 2); | 399 Platform::current()->histogramEnumeration(startedStreamingHistogramN
ame(m_scriptType), 0, 2); |
| 400 return; | 400 return; |
| 401 } | 401 } |
| 402 | 402 |
| 403 if (!m_scriptState->contextIsValid()) { | 403 if (!m_scriptState->contextIsValid()) { |
| 404 suppressStreaming(); | 404 suppressStreaming(); |
| 405 blink::Platform::current()->histogramEnumeration(notStreamingReasonH
istogramName(m_scriptType), ContextNotValid, NotStreamingReasonEnd); | 405 Platform::current()->histogramEnumeration(notStreamingReasonHistogra
mName(m_scriptType), ContextNotValid, NotStreamingReasonEnd); |
| 406 blink::Platform::current()->histogramEnumeration(startedStreamingHis
togramName(m_scriptType), 0, 2); | 406 Platform::current()->histogramEnumeration(startedStreamingHistogramN
ame(m_scriptType), 0, 2); |
| 407 return; | 407 return; |
| 408 } | 408 } |
| 409 | 409 |
| 410 ASSERT(!m_stream); | 410 ASSERT(!m_stream); |
| 411 ASSERT(!m_source); | 411 ASSERT(!m_source); |
| 412 m_stream = new SourceStream(); | 412 m_stream = new SourceStream(); |
| 413 // m_source takes ownership of m_stream. | 413 // m_source takes ownership of m_stream. |
| 414 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e
ncoding)); | 414 m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_e
ncoding)); |
| 415 | 415 |
| 416 ScriptState::Scope scope(m_scriptState.get()); | 416 ScriptState::Scope scope(m_scriptState.get()); |
| 417 WTF::OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask
(adoptPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_s
ource.get(), m_compileOptions))); | 417 WTF::OwnPtr<v8::ScriptCompiler::ScriptStreamingTask> scriptStreamingTask
(adoptPtr(v8::ScriptCompiler::StartStreamingScript(m_scriptState->isolate(), m_s
ource.get(), m_compileOptions))); |
| 418 if (!scriptStreamingTask) { | 418 if (!scriptStreamingTask) { |
| 419 // V8 cannot stream the script. | 419 // V8 cannot stream the script. |
| 420 suppressStreaming(); | 420 suppressStreaming(); |
| 421 m_stream = 0; | 421 m_stream = 0; |
| 422 m_source.clear(); | 422 m_source.clear(); |
| 423 blink::Platform::current()->histogramEnumeration(notStreamingReasonH
istogramName(m_scriptType), V8CannotStream, NotStreamingReasonEnd); | 423 Platform::current()->histogramEnumeration(notStreamingReasonHistogra
mName(m_scriptType), V8CannotStream, NotStreamingReasonEnd); |
| 424 blink::Platform::current()->histogramEnumeration(startedStreamingHis
togramName(m_scriptType), 0, 2); | 424 Platform::current()->histogramEnumeration(startedStreamingHistogramN
ame(m_scriptType), 0, 2); |
| 425 return; | 425 return; |
| 426 } | 426 } |
| 427 | 427 |
| 428 // ScriptStreamer needs to stay alive as long as the background task is | 428 // ScriptStreamer needs to stay alive as long as the background task is |
| 429 // running. This is taken care of with a manual ref() & deref() pair; | 429 // running. This is taken care of with a manual ref() & deref() pair; |
| 430 // the corresponding deref() is in streamingComplete. | 430 // the corresponding deref() is in streamingComplete. |
| 431 ref(); | 431 ref(); |
| 432 ScriptStreamingTask* task = new ScriptStreamingTask(scriptStreamingTask.
release(), this); | 432 ScriptStreamingTask* task = new ScriptStreamingTask(scriptStreamingTask.
release(), this); |
| 433 ScriptStreamerThread::shared()->postTask(task); | 433 ScriptStreamerThread::shared()->postTask(task); |
| 434 blink::Platform::current()->histogramEnumeration(startedStreamingHistogr
amName(m_scriptType), 1, 2); | 434 Platform::current()->histogramEnumeration(startedStreamingHistogramName(
m_scriptType), 1, 2); |
| 435 } | 435 } |
| 436 if (m_stream) | 436 if (m_stream) |
| 437 m_stream->didReceiveData(this, lengthOfBOM); | 437 m_stream->didReceiveData(this, lengthOfBOM); |
| 438 } | 438 } |
| 439 | 439 |
| 440 void ScriptStreamer::notifyFinished(Resource* resource) | 440 void ScriptStreamer::notifyFinished(Resource* resource) |
| 441 { | 441 { |
| 442 ASSERT(isMainThread()); | 442 ASSERT(isMainThread()); |
| 443 ASSERT(m_resource == resource); | 443 ASSERT(m_resource == resource); |
| 444 // A special case: empty and small scripts. We didn't receive enough data to | 444 // A special case: empty and small scripts. We didn't receive enough data to |
| 445 // start the streaming before this notification. In that case, there won't | 445 // start the streaming before this notification. In that case, there won't |
| 446 // be a "parsing complete" notification either, and we should not wait for | 446 // be a "parsing complete" notification either, and we should not wait for |
| 447 // it. | 447 // it. |
| 448 if (!m_haveEnoughDataForStreaming) { | 448 if (!m_haveEnoughDataForStreaming) { |
| 449 blink::Platform::current()->histogramEnumeration(notStreamingReasonHisto
gramName(m_scriptType), ScriptTooSmall, NotStreamingReasonEnd); | 449 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(m_scriptType), ScriptTooSmall, NotStreamingReasonEnd); |
| 450 blink::Platform::current()->histogramEnumeration(startedStreamingHistogr
amName(m_scriptType), 0, 2); | 450 Platform::current()->histogramEnumeration(startedStreamingHistogramName(
m_scriptType), 0, 2); |
| 451 suppressStreaming(); | 451 suppressStreaming(); |
| 452 } | 452 } |
| 453 if (m_stream) | 453 if (m_stream) |
| 454 m_stream->didFinishLoading(); | 454 m_stream->didFinishLoading(); |
| 455 m_loadingFinished = true; | 455 m_loadingFinished = true; |
| 456 | 456 |
| 457 // Calling notifyFinishedToClient can result into the upper layers dropping | 457 // Calling notifyFinishedToClient can result into the upper layers dropping |
| 458 // references to ScriptStreamer. Keep it alive until this function ends. | 458 // references to ScriptStreamer. Keep it alive until this function ends. |
| 459 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); | 459 RefPtrWillBeRawPtr<ScriptStreamer> protect(this); |
| 460 | 460 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 } | 529 } |
| 530 if (m_client) | 530 if (m_client) |
| 531 m_client->notifyFinished(m_resource); | 531 m_client->notifyFinished(m_resource); |
| 532 } | 532 } |
| 533 | 533 |
| 534 bool ScriptStreamer::startStreamingInternal(PendingScript& script, PendingScript
::Type scriptType, Settings* settings, ScriptState* scriptState) | 534 bool ScriptStreamer::startStreamingInternal(PendingScript& script, PendingScript
::Type scriptType, Settings* settings, ScriptState* scriptState) |
| 535 { | 535 { |
| 536 ASSERT(isMainThread()); | 536 ASSERT(isMainThread()); |
| 537 ScriptResource* resource = script.resource(); | 537 ScriptResource* resource = script.resource(); |
| 538 if (resource->isLoaded()) { | 538 if (resource->isLoaded()) { |
| 539 blink::Platform::current()->histogramEnumeration(notStreamingReasonHisto
gramName(scriptType), AlreadyLoaded, NotStreamingReasonEnd); | 539 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), AlreadyLoaded, NotStreamingReasonEnd); |
| 540 return false; | 540 return false; |
| 541 } | 541 } |
| 542 if (!resource->url().protocolIsInHTTPFamily()) { | 542 if (!resource->url().protocolIsInHTTPFamily()) { |
| 543 blink::Platform::current()->histogramEnumeration(notStreamingReasonHisto
gramName(scriptType), NotHTTP, NotStreamingReasonEnd); | 543 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), NotHTTP, NotStreamingReasonEnd); |
| 544 return false; | 544 return false; |
| 545 } | 545 } |
| 546 if (resource->resourceToRevalidate()) { | 546 if (resource->resourceToRevalidate()) { |
| 547 blink::Platform::current()->histogramEnumeration(notStreamingReasonHisto
gramName(scriptType), Reload, NotStreamingReasonEnd); | 547 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), Reload, NotStreamingReasonEnd); |
| 548 // This happens e.g., during reloads. We're actually not going to load | 548 // This happens e.g., during reloads. We're actually not going to load |
| 549 // the current Resource of the PendingScript but switch to another | 549 // the current Resource of the PendingScript but switch to another |
| 550 // Resource -> don't stream. | 550 // Resource -> don't stream. |
| 551 return false; | 551 return false; |
| 552 } | 552 } |
| 553 // We cannot filter out short scripts, even if we wait for the HTTP headers | 553 // We cannot filter out short scripts, even if we wait for the HTTP headers |
| 554 // to arrive: the Content-Length HTTP header is not sent for chunked | 554 // to arrive: the Content-Length HTTP header is not sent for chunked |
| 555 // downloads. | 555 // downloads. |
| 556 | 556 |
| 557 if (!scriptState->contextIsValid()) { | 557 if (!scriptState->contextIsValid()) { |
| 558 blink::Platform::current()->histogramEnumeration(notStreamingReasonHisto
gramName(scriptType), ContextNotValid, NotStreamingReasonEnd); | 558 Platform::current()->histogramEnumeration(notStreamingReasonHistogramNam
e(scriptType), ContextNotValid, NotStreamingReasonEnd); |
| 559 return false; | 559 return false; |
| 560 } | 560 } |
| 561 | 561 |
| 562 // Decide what kind of cached data we should produce while streaming. Only | 562 // Decide what kind of cached data we should produce while streaming. Only |
| 563 // produce parser cache if the non-streaming compile takes advantage of it. | 563 // produce parser cache if the non-streaming compile takes advantage of it. |
| 564 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo
mpileOptions; | 564 v8::ScriptCompiler::CompileOptions compileOption = v8::ScriptCompiler::kNoCo
mpileOptions; |
| 565 if (settings->v8CacheOptions() == V8CacheOptionsParseMemory || settings->v8C
acheOptions() == V8CacheOptionsParse) | 565 if (settings->v8CacheOptions() == V8CacheOptionsParseMemory || settings->v8C
acheOptions() == V8CacheOptionsParse) |
| 566 compileOption = v8::ScriptCompiler::kProduceParserCache; | 566 compileOption = v8::ScriptCompiler::kProduceParserCache; |
| 567 | 567 |
| 568 // The Resource might go out of scope if the script is no longer | 568 // The Resource might go out of scope if the script is no longer |
| 569 // needed. This makes PendingScript notify the ScriptStreamer when it is | 569 // needed. This makes PendingScript notify the ScriptStreamer when it is |
| 570 // destroyed. | 570 // destroyed. |
| 571 script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState,
compileOption)); | 571 script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState,
compileOption)); |
| 572 | 572 |
| 573 return true; | 573 return true; |
| 574 } | 574 } |
| 575 | 575 |
| 576 } // namespace blink | 576 } // namespace blink |
| OLD | NEW |