| 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 |