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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 class SourceStream : public v8::ScriptCompiler::ExternalSourceStream { | 162 class SourceStream : public v8::ScriptCompiler::ExternalSourceStream { |
163 WTF_MAKE_NONCOPYABLE(SourceStream); | 163 WTF_MAKE_NONCOPYABLE(SourceStream); |
164 public: | 164 public: |
165 SourceStream() | 165 SourceStream() |
166 : v8::ScriptCompiler::ExternalSourceStream() | 166 : v8::ScriptCompiler::ExternalSourceStream() |
167 , m_cancelled(false) | 167 , m_cancelled(false) |
168 , m_finished(false) | 168 , m_finished(false) |
169 , m_queueLeadPosition(0) | 169 , m_queueLeadPosition(0) |
170 , m_queueTailPosition(0) | 170 , m_queueTailPosition(0) |
171 , m_bookmarkPosition(0) | 171 , m_bookmarkPosition(0) |
| 172 , m_lengthOfBOM(0) |
172 { | 173 { |
173 } | 174 } |
174 | 175 |
175 virtual ~SourceStream() override { } | 176 virtual ~SourceStream() override { } |
176 | 177 |
177 // Called by V8 on a background thread. Should block until we can return | 178 // Called by V8 on a background thread. Should block until we can return |
178 // some data. | 179 // some data. |
179 size_t GetMoreData(const uint8_t** src) override | 180 size_t GetMoreData(const uint8_t** src) override |
180 { | 181 { |
181 ASSERT(!isMainThread()); | 182 ASSERT(!isMainThread()); |
(...skipping 12 matching lines...) Expand all Loading... |
194 } | 195 } |
195 m_queueLeadPosition += length; | 196 m_queueLeadPosition += length; |
196 return length; | 197 return length; |
197 } | 198 } |
198 | 199 |
199 // Called by V8 on background thread. | 200 // Called by V8 on background thread. |
200 bool SetBookmark() override | 201 bool SetBookmark() override |
201 { | 202 { |
202 ASSERT(!isMainThread()); | 203 ASSERT(!isMainThread()); |
203 m_bookmarkPosition = m_queueLeadPosition; | 204 m_bookmarkPosition = m_queueLeadPosition; |
204 return m_bookmarkPosition != 0; // Don't mess with BOM. | 205 return true; |
205 } | 206 } |
206 | 207 |
207 // Called by V8 on background thread. | 208 // Called by V8 on background thread. |
208 void ResetToBookmark() override | 209 void ResetToBookmark() override |
209 { | 210 { |
210 ASSERT(!isMainThread()); | 211 ASSERT(!isMainThread()); |
211 { | 212 { |
212 MutexLocker locker(m_mutex); | 213 MutexLocker locker(m_mutex); |
213 m_queueLeadPosition = m_bookmarkPosition; | 214 m_queueLeadPosition = m_bookmarkPosition; |
214 m_queueTailPosition = m_bookmarkPosition; | 215 // See comments at m_lengthOfBOM declaration below for why |
| 216 // we need this here. |
| 217 m_queueTailPosition = m_bookmarkPosition + m_lengthOfBOM; |
215 m_dataQueue.clear(); | 218 m_dataQueue.clear(); |
216 } | 219 } |
217 | 220 |
218 // Inform main thread to re-queue the data. | 221 // Inform main thread to re-queue the data. |
219 Platform::current()->mainThread()->taskRunner()->postTask( | 222 Platform::current()->mainThread()->taskRunner()->postTask( |
220 FROM_HERE, bind(&SourceStream::fetchDataFromResourceBuffer, this, 0)
); | 223 FROM_HERE, bind(&SourceStream::fetchDataFromResourceBuffer, this, 0)
); |
221 } | 224 } |
222 | 225 |
223 void didFinishLoading() | 226 void didFinishLoading() |
224 { | 227 { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 // FIXME: Here we can limit based on the total length, if it tur
ns | 304 // FIXME: Here we can limit based on the total length, if it tur
ns |
302 // out that we don't want to give all the data we have (memory | 305 // out that we don't want to give all the data we have (memory |
303 // vs. speed). | 306 // vs. speed). |
304 chunks.append(data); | 307 chunks.append(data); |
305 chunkLengths.append(length); | 308 chunkLengths.append(length); |
306 dataLength += length; | 309 dataLength += length; |
307 m_queueTailPosition += length; | 310 m_queueTailPosition += length; |
308 } | 311 } |
309 } | 312 } |
310 | 313 |
| 314 if (lengthOfBOM > 0) { |
| 315 ASSERT(!m_lengthOfBOM); // There should be only one BOM. |
| 316 m_lengthOfBOM = lengthOfBOM; |
| 317 } |
| 318 |
311 // Copy the data chunks into a new buffer, since we're going to give the | 319 // Copy the data chunks into a new buffer, since we're going to give the |
312 // data to a background thread. | 320 // data to a background thread. |
313 if (dataLength > lengthOfBOM) { | 321 if (dataLength > lengthOfBOM) { |
314 dataLength -= lengthOfBOM; | 322 dataLength -= lengthOfBOM; |
315 uint8_t* copiedData = new uint8_t[dataLength]; | 323 uint8_t* copiedData = new uint8_t[dataLength]; |
316 unsigned offset = 0; | 324 unsigned offset = 0; |
317 for (size_t i = 0; i < chunks.size(); ++i) { | 325 for (size_t i = 0; i < chunks.size(); ++i) { |
318 memcpy(copiedData + offset, chunks[i] + lengthOfBOM, chunkLength
s[i] - lengthOfBOM); | 326 memcpy(copiedData + offset, chunks[i] + lengthOfBOM, chunkLength
s[i] - lengthOfBOM); |
319 offset += chunkLengths[i] - lengthOfBOM; | 327 offset += chunkLengths[i] - lengthOfBOM; |
320 // BOM is only in the first chunk | 328 // BOM is only in the first chunk |
(...skipping 18 matching lines...) Expand all Loading... |
339 RefPtr<SharedBuffer> m_resourceBuffer; // Only used by the main thread. | 347 RefPtr<SharedBuffer> m_resourceBuffer; // Only used by the main thread. |
340 | 348 |
341 // The queue contains the data to be passed to the V8 thread. | 349 // The queue contains the data to be passed to the V8 thread. |
342 // queueLeadPosition: data we have handed off to the V8 thread. | 350 // queueLeadPosition: data we have handed off to the V8 thread. |
343 // queueTailPosition: end of data we have enqued in the queue. | 351 // queueTailPosition: end of data we have enqued in the queue. |
344 // bookmarkPosition: position of the bookmark. | 352 // bookmarkPosition: position of the bookmark. |
345 SourceStreamDataQueue m_dataQueue; // Thread safe. | 353 SourceStreamDataQueue m_dataQueue; // Thread safe. |
346 unsigned m_queueLeadPosition; // Only used by v8 thread. | 354 unsigned m_queueLeadPosition; // Only used by v8 thread. |
347 unsigned m_queueTailPosition; // Used by both threads; guarded by m_mutex. | 355 unsigned m_queueTailPosition; // Used by both threads; guarded by m_mutex. |
348 unsigned m_bookmarkPosition; // Only used by v8 thread. | 356 unsigned m_bookmarkPosition; // Only used by v8 thread. |
| 357 |
| 358 // BOM (Unicode Byte Order Mark) handling: |
| 359 // This class is responsible for stripping out the BOM, since Chrome |
| 360 // delivers the input stream potentially with BOM, but V8 doesn't want |
| 361 // to see the BOM. This is mostly easy to do, except for a funky edge |
| 362 // condition with bookmarking: |
| 363 // - m_queueLeadPosition counts the bytes that V8 has received |
| 364 // (i.e., without BOM) |
| 365 // - m_queueTailPosition counts the bytes that Chrome has sent |
| 366 // (i.e., with BOM) |
| 367 // So when resetting the bookmark, we have to adjust the lead position |
| 368 // to account for the BOM (which happens implicitly in the regular |
| 369 // streaming case). |
| 370 // We store this separately, to avoid having to guard all |
| 371 // m_queueLeadPosition references with a mutex. |
| 372 unsigned m_lengthOfBOM; // Used by both threads; guarded by m_mutex. |
349 }; | 373 }; |
350 | 374 |
351 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; | 375 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024; |
352 | 376 |
353 void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type s
criptType, Settings* settings, ScriptState* scriptState) | 377 void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type s
criptType, Settings* settings, ScriptState* scriptState) |
354 { | 378 { |
355 // We don't yet know whether the script will really be streamed. E.g., | 379 // We don't yet know whether the script will really be streamed. E.g., |
356 // suppressing streaming for short scripts is done later. Record only the | 380 // suppressing streaming for short scripts is done later. Record only the |
357 // sure negative cases here. | 381 // sure negative cases here. |
358 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState); | 382 bool startedStreaming = startStreamingInternal(script, scriptType, settings,
scriptState); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 | 664 |
641 // The Resource might go out of scope if the script is no longer | 665 // The Resource might go out of scope if the script is no longer |
642 // needed. This makes PendingScript notify the ScriptStreamer when it is | 666 // needed. This makes PendingScript notify the ScriptStreamer when it is |
643 // destroyed. | 667 // destroyed. |
644 script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState,
compileOption)); | 668 script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState,
compileOption)); |
645 | 669 |
646 return true; | 670 return true; |
647 } | 671 } |
648 | 672 |
649 } // namespace blink | 673 } // namespace blink |
OLD | NEW |