File: ScriptStreamer.h

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (171 lines) | stat: -rw-r--r-- 6,798 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ScriptStreamer_h
#define ScriptStreamer_h

#include "bindings/core/v8/ScriptStreamingMode.h"
#include "core/dom/PendingScript.h"
#include "wtf/RefCounted.h"

#include <v8.h>

namespace blink {

class PendingScript;
class Resource;
class ScriptResource;
class ScriptResourceClient;
class ScriptState;
class Settings;
class SourceStream;

// ScriptStreamer streams incomplete script data to V8 so that it can be parsed
// while it's loaded. PendingScript holds a reference to ScriptStreamer. At the
// moment, ScriptStreamer is only used for parser blocking scripts; this means
// that the Document stays stable and no other scripts are executing while we're
// streaming. It is possible, though, that Document and the PendingScript are
// destroyed while the streaming is in progress, and ScriptStreamer handles it
// gracefully.
class ScriptStreamer : public RefCounted<ScriptStreamer> {
    WTF_MAKE_NONCOPYABLE(ScriptStreamer);
public:
    // Launches a task (on a background thread) which will stream the given
    // PendingScript into V8 as it loads. It's also possible that V8 cannot
    // stream the given script; in that case this function returns
    // false. Internally, this constructs a ScriptStreamer and attaches it to
    // the PendingScript. Use ScriptStreamer::addClient to get notified when the
    // streaming finishes.
    static void startStreaming(PendingScript&, Settings*, ScriptState*, PendingScript::Type);

    // Returns false if we cannot stream the given encoding.
    static bool convertEncoding(const char* encodingName, v8::ScriptCompiler::StreamedSource::Encoding*);

    bool isFinished() const
    {
        return m_loadingFinished && (m_parsingFinished || m_streamingSuppressed);
    }

    v8::ScriptCompiler::StreamedSource* source() { return m_source.get(); }
    ScriptResource* resource() const { return m_resource; }

    // Called when the script is not needed any more (e.g., loading was
    // cancelled). After calling cancel, PendingScript can drop its reference to
    // ScriptStreamer, and ScriptStreamer takes care of eventually deleting
    // itself (after the V8 side has finished too).
    void cancel();

    // When the streaming is suppressed, the data is not given to V8, but
    // ScriptStreamer still watches the resource load and notifies the upper
    // layers when loading is finished. It is used in situations when we have
    // started streaming but then we detect we don't want to stream (e.g., when
    // we have the code cache for the script) and we still want to parse and
    // execute it when it has finished loading.
    void suppressStreaming();
    bool streamingSuppressed() const { return m_streamingSuppressed; }

    v8::ScriptCompiler::CompileOptions compileOptions() const
    {
        return m_compileOptions;
    }

    void addClient(ScriptResourceClient* client)
    {
        ASSERT(!m_client);
        m_client = client;
        notifyFinishedToClient();
    }

    void removeClient(ScriptResourceClient* client)
    {
        ASSERT(m_client == client);
        m_client = 0;
    }

    // Called by PendingScript when data arrives from the network.
    void notifyAppendData(ScriptResource*);
    void notifyFinished(Resource*);

    // Called by ScriptStreamingTask when it has streamed all data to V8 and V8
    // has processed it.
    void streamingCompleteOnBackgroundThread();

    v8::ScriptCompiler::StreamedSource::Encoding encoding() const { return m_encoding; }

    static void setSmallScriptThresholdForTesting(size_t threshold)
    {
        kSmallScriptThreshold = threshold;
    }

    static size_t smallScriptThreshold() { return kSmallScriptThreshold; }

private:
    // Scripts whose first data chunk is smaller than this constant won't be
    // streamed. Non-const for testing.
    static size_t kSmallScriptThreshold;

    ScriptStreamer(ScriptResource*, PendingScript::Type, ScriptStreamingMode, ScriptState*, v8::ScriptCompiler::CompileOptions);

    void streamingComplete();
    void notifyFinishedToClient();

    bool shouldBlockMainThread() const
    {
        return m_scriptStreamingMode == ScriptStreamingModeAllPlusBlockParsingBlocking && m_scriptType == PendingScript::ParsingBlocking;
    }

    static const char* startedStreamingHistogramName(PendingScript::Type);

    static bool startStreamingInternal(PendingScript&, Settings*, ScriptState*, PendingScript::Type);

    // This pointer is weak. If PendingScript and its Resource are deleted
    // before ScriptStreamer, PendingScript will notify ScriptStreamer of its
    // deletion by calling cancel().
    ScriptResource* m_resource;
    // Whether ScriptStreamer is detached from the Resource. In those cases, the
    // script data is not needed any more, and the client won't get notified
    // when the loading and streaming are done.
    bool m_detached;

    SourceStream* m_stream;
    OwnPtr<v8::ScriptCompiler::StreamedSource> m_source;
    ScriptResourceClient* m_client;
    bool m_loadingFinished; // Whether loading from the network is done.
    // Whether the V8 side processing is done. Will be used by the main thread
    // and the streamer thread; guarded by m_mutex.
    bool m_parsingFinished;
    // Whether we have received enough data to start the streaming.
    bool m_haveEnoughDataForStreaming;

    // Whether the script source code should be retrieved from the Resource
    // instead of the ScriptStreamer; guarded by m_mutex.
    bool m_streamingSuppressed;

    // What kind of cached data V8 produces during streaming.
    v8::ScriptCompiler::CompileOptions m_compileOptions;

    RefPtr<ScriptState> m_scriptState;

    // For recording metrics for different types of scripts separately.
    PendingScript::Type m_scriptType;

    // Streaming mode defines whether the main thread should block and wait for
    // the parsing to complete after the load has finished. See
    // ScriptStreamer::notifyFinished for more information.
    ScriptStreamingMode m_scriptStreamingMode;
    Mutex m_mutex;
    ThreadCondition m_parsingFinishedCondition;
    // Whether the main thread is currently waiting on the parser thread in
    // notifyFinished(). This also defines which thread should do the cleanup of
    // the parsing task: if the main thread is waiting, the main thread should
    // do it, otherwise the parser thread should do it. Guarded by m_mutex.
    bool m_mainThreadWaitingForParserThread;

    // Encoding of the streamed script. Saved for sanity checking purposes.
    v8::ScriptCompiler::StreamedSource::Encoding m_encoding;
};

} // namespace blink

#endif // ScriptStreamer_h