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 |