Home | History | Annotate | Download | only in v8
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef ScriptStreamer_h
      6 #define ScriptStreamer_h
      7 
      8 #include "core/dom/PendingScript.h"
      9 #include "wtf/RefCounted.h"
     10 
     11 #include <v8.h>
     12 
     13 namespace blink {
     14 
     15 class PendingScript;
     16 class Resource;
     17 class ScriptResource;
     18 class ScriptResourceClient;
     19 class ScriptState;
     20 class Settings;
     21 class SourceStream;
     22 
     23 // ScriptStreamer streams incomplete script data to V8 so that it can be parsed
     24 // while it's loaded. PendingScript holds a reference to ScriptStreamer. At the
     25 // moment, ScriptStreamer is only used for parser blocking scripts; this means
     26 // that the Document stays stable and no other scripts are executing while we're
     27 // streaming. It is possible, though, that Document and the PendingScript are
     28 // destroyed while the streaming is in progress, and ScriptStreamer handles it
     29 // gracefully.
     30 class ScriptStreamer : public RefCounted<ScriptStreamer> {
     31     WTF_MAKE_NONCOPYABLE(ScriptStreamer);
     32 public:
     33     // Launches a task (on a background thread) which will stream the given
     34     // PendingScript into V8 as it loads. It's also possible that V8 cannot
     35     // stream the given script; in that case this function returns
     36     // false. Internally, this constructs a ScriptStreamer and attaches it to
     37     // the PendingScript. Use ScriptStreamer::addClient to get notified when the
     38     // streaming finishes.
     39     static void startStreaming(PendingScript&, Settings*, ScriptState*, PendingScript::Type);
     40 
     41     bool isFinished() const
     42     {
     43         return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed);
     44     }
     45 
     46     v8::ScriptCompiler::StreamedSource* source() { return &m_source; }
     47     ScriptResource* resource() const { return m_resource; }
     48 
     49     // Called when the script is not needed any more (e.g., loading was
     50     // cancelled). After calling cancel, PendingScript can drop its reference to
     51     // ScriptStreamer, and ScriptStreamer takes care of eventually deleting
     52     // itself (after the V8 side has finished too).
     53     void cancel();
     54 
     55     // When the streaming is suppressed, the data is not given to V8, but
     56     // ScriptStreamer still watches the resource load and notifies the upper
     57     // layers when loading is finished. It is used in situations when we have
     58     // started streaming but then we detect we don't want to stream (e.g., when
     59     // we have the code cache for the script) and we still want to parse and
     60     // execute it when it has finished loading.
     61     void suppressStreaming();
     62     bool streamingSuppressed() const { return m_streamingSuppressed; }
     63 
     64     unsigned cachedDataType() const { return m_cachedDataType; }
     65 
     66     void addClient(ScriptResourceClient* client)
     67     {
     68         ASSERT(!m_client);
     69         ASSERT(!isFinished());
     70         m_client = client;
     71     }
     72 
     73     void removeClient(ScriptResourceClient* client)
     74     {
     75         ASSERT(m_client == client);
     76         m_client = 0;
     77     }
     78 
     79     // Called by PendingScript when data arrives from the network.
     80     void notifyAppendData(ScriptResource*);
     81     void notifyFinished(Resource*);
     82 
     83     // Called by ScriptStreamingTask when it has streamed all data to V8 and V8
     84     // has processed it.
     85     void streamingComplete();
     86 
     87     static void removeSmallScriptThresholdForTesting()
     88     {
     89         kSmallScriptThreshold = 0;
     90     }
     91 
     92     static size_t smallScriptThreshold() { return kSmallScriptThreshold; }
     93 
     94 private:
     95     // Scripts whose first data chunk is smaller than this constant won't be
     96     // streamed. Non-const for testing.
     97     static size_t kSmallScriptThreshold;
     98 
     99     ScriptStreamer(ScriptResource*, v8::ScriptCompiler::StreamedSource::Encoding, PendingScript::Type);
    100 
    101     void notifyFinishedToClient();
    102 
    103     static const char* startedStreamingHistogramName(PendingScript::Type);
    104 
    105     static bool startStreamingInternal(PendingScript&, Settings*, ScriptState*, PendingScript::Type);
    106 
    107     // This pointer is weak. If PendingScript and its Resource are deleted
    108     // before ScriptStreamer, PendingScript will notify ScriptStreamer of its
    109     // deletion by calling cancel().
    110     ScriptResource* m_resource;
    111     // Whether ScriptStreamer is detached from the Resource. In those cases, the
    112     // script data is not needed any more, and the client won't get notified
    113     // when the loading and streaming are done.
    114     bool m_detached;
    115 
    116     SourceStream* m_stream;
    117     v8::ScriptCompiler::StreamedSource m_source;
    118     ScriptResourceClient* m_client;
    119     v8::ScriptCompiler::ScriptStreamingTask* m_task;
    120     bool m_loadingFinished; // Whether loading from the network is done.
    121     bool m_parsingFinished; // Whether the V8 side processing is done.
    122     bool m_firstDataChunkReceived;
    123 
    124     // Whether the script source code should be retrieved from the Resource
    125     // instead of the ScriptStreamer.
    126     bool m_streamingSuppressed;
    127 
    128     // What kind of cached data V8 produces during streaming.
    129     unsigned m_cachedDataType;
    130 
    131     // For recording metrics for different types of scripts separately.
    132     PendingScript::Type m_scriptType;
    133 };
    134 
    135 } // namespace blink
    136 
    137 #endif // ScriptStreamer_h
    138