17242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 27242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Use of this source code is governed by a BSD-style license that can be 37242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// found in the LICENSE file. 47242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 57242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#ifndef ScriptStreamer_h 67242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#define ScriptStreamer_h 77242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 87242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/dom/PendingScript.h" 97242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "wtf/RefCounted.h" 107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include <v8.h> 127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccinamespace blink { 147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass PendingScript; 167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass Resource; 177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass ScriptResource; 187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass ScriptResourceClient; 197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass ScriptState; 207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass Settings; 217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass SourceStream; 227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// ScriptStreamer streams incomplete script data to V8 so that it can be parsed 247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// while it's loaded. PendingScript holds a reference to ScriptStreamer. At the 257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// moment, ScriptStreamer is only used for parser blocking scripts; this means 267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// that the Document stays stable and no other scripts are executing while we're 277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// streaming. It is possible, though, that Document and the PendingScript are 287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// destroyed while the streaming is in progress, and ScriptStreamer handles it 297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// gracefully. 307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass ScriptStreamer : public RefCounted<ScriptStreamer> { 317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci WTF_MAKE_NONCOPYABLE(ScriptStreamer); 327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic: 337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Launches a task (on a background thread) which will stream the given 347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // PendingScript into V8 as it loads. It's also possible that V8 cannot 357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // stream the given script; in that case this function returns 367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // false. Internally, this constructs a ScriptStreamer and attaches it to 377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // the PendingScript. Use ScriptStreamer::addClient to get notified when the 387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // streaming finishes. 397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static void startStreaming(PendingScript&, Settings*, ScriptState*, PendingScript::Type); 407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool isFinished() const 427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed); 447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::ScriptCompiler::StreamedSource* source() { return &m_source; } 477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptResource* resource() const { return m_resource; } 487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Called when the script is not needed any more (e.g., loading was 507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // cancelled). After calling cancel, PendingScript can drop its reference to 517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // ScriptStreamer, and ScriptStreamer takes care of eventually deleting 527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // itself (after the V8 side has finished too). 537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void cancel(); 547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // When the streaming is suppressed, the data is not given to V8, but 567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // ScriptStreamer still watches the resource load and notifies the upper 577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // layers when loading is finished. It is used in situations when we have 587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // started streaming but then we detect we don't want to stream (e.g., when 597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // we have the code cache for the script) and we still want to parse and 607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // execute it when it has finished loading. 617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void suppressStreaming(); 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool streamingSuppressed() const { return m_streamingSuppressed; } 637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci unsigned cachedDataType() const { return m_cachedDataType; } 657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void addClient(ScriptResourceClient* client) 677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT(!m_client); 697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT(!isFinished()); 707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_client = client; 717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void removeClient(ScriptResourceClient* client) 747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT(m_client == client); 767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_client = 0; 777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Called by PendingScript when data arrives from the network. 807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void notifyAppendData(ScriptResource*); 817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void notifyFinished(Resource*); 827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Called by ScriptStreamingTask when it has streamed all data to V8 and V8 847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // has processed it. 857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void streamingComplete(); 867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static void removeSmallScriptThresholdForTesting() 887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci kSmallScriptThreshold = 0; 907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static size_t smallScriptThreshold() { return kSmallScriptThreshold; } 937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate: 957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Scripts whose first data chunk is smaller than this constant won't be 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // streamed. Non-const for testing. 977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static size_t kSmallScriptThreshold; 987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptStreamer(ScriptResource*, v8::ScriptCompiler::StreamedSource::Encoding, PendingScript::Type); 1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void notifyFinishedToClient(); 1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static const char* startedStreamingHistogramName(PendingScript::Type); 1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static bool startStreamingInternal(PendingScript&, Settings*, ScriptState*, PendingScript::Type); 1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // This pointer is weak. If PendingScript and its Resource are deleted 1087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // before ScriptStreamer, PendingScript will notify ScriptStreamer of its 1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // deletion by calling cancel(). 1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptResource* m_resource; 1117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Whether ScriptStreamer is detached from the Resource. In those cases, the 1127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // script data is not needed any more, and the client won't get notified 1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // when the loading and streaming are done. 1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_detached; 1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SourceStream* m_stream; 1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::ScriptCompiler::StreamedSource m_source; 1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptResourceClient* m_client; 1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::ScriptCompiler::ScriptStreamingTask* m_task; 1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_loadingFinished; // Whether loading from the network is done. 1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_parsingFinished; // Whether the V8 side processing is done. 1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_firstDataChunkReceived; 1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Whether the script source code should be retrieved from the Resource 1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // instead of the ScriptStreamer. 1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_streamingSuppressed; 1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // What kind of cached data V8 produces during streaming. 1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci unsigned m_cachedDataType; 1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // For recording metrics for different types of scripts separately. 1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci PendingScript::Type m_scriptType; 1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}; 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} // namespace blink 1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#endif // ScriptStreamer_h 138