| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project 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 "src/parsing/scanner-character-streams.h" | 5 #include "src/parsing/scanner-character-streams.h" |
| 6 | 6 |
| 7 #include "include/v8.h" | 7 #include "include/v8.h" |
| 8 #include "src/globals.h" | 8 #include "src/globals.h" |
| 9 #include "src/handles.h" | 9 #include "src/handles.h" |
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 | 342 |
| 343 void Utf8ExternalStreamingStream::SearchPosition(size_t position) { | 343 void Utf8ExternalStreamingStream::SearchPosition(size_t position) { |
| 344 // If current_ already points to the right position, we're done. | 344 // If current_ already points to the right position, we're done. |
| 345 // | 345 // |
| 346 // This is expected to be the common case, since we typically call | 346 // This is expected to be the common case, since we typically call |
| 347 // FillBuffer right after the current buffer. | 347 // FillBuffer right after the current buffer. |
| 348 if (current_.pos.chars == position) return; | 348 if (current_.pos.chars == position) return; |
| 349 | 349 |
| 350 // No chunks. Fetch at least one, so we can assume !chunks_.empty() below. | 350 // No chunks. Fetch at least one, so we can assume !chunks_.empty() below. |
| 351 if (chunks_.empty()) { | 351 if (chunks_.empty()) { |
| 352 DCHECK_EQ(current_.chunk_no, 0); | 352 DCHECK_EQ(current_.chunk_no, 0u); |
| 353 DCHECK_EQ(current_.pos.bytes, 0); | 353 DCHECK_EQ(current_.pos.bytes, 0u); |
| 354 DCHECK_EQ(current_.pos.chars, 0); | 354 DCHECK_EQ(current_.pos.chars, 0u); |
| 355 FetchChunk(); | 355 FetchChunk(); |
| 356 } | 356 } |
| 357 | 357 |
| 358 // Search for the last chunk whose start position is less or equal to | 358 // Search for the last chunk whose start position is less or equal to |
| 359 // position. | 359 // position. |
| 360 size_t chunk_no = chunks_.size() - 1; | 360 size_t chunk_no = chunks_.size() - 1; |
| 361 while (chunk_no > 0 && chunks_[chunk_no].start.chars > position) { | 361 while (chunk_no > 0 && chunks_[chunk_no].start.chars > position) { |
| 362 chunk_no--; | 362 chunk_no--; |
| 363 } | 363 } |
| 364 | 364 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 // (The embedder might give us 1-byte blocks within a utf-8 char, so we | 431 // (The embedder might give us 1-byte blocks within a utf-8 char, so we |
| 432 // can't guarantee progress with one chunk. Thus we iterate.) | 432 // can't guarantee progress with one chunk. Thus we iterate.) |
| 433 while (!out_of_data && buffer_cursor_ == buffer_end_) { | 433 while (!out_of_data && buffer_cursor_ == buffer_end_) { |
| 434 // At end of current data, but there might be more? Then fetch it. | 434 // At end of current data, but there might be more? Then fetch it. |
| 435 if (current_.chunk_no == chunks_.size()) { | 435 if (current_.chunk_no == chunks_.size()) { |
| 436 out_of_data = !FetchChunk(); | 436 out_of_data = !FetchChunk(); |
| 437 } | 437 } |
| 438 FillBufferFromCurrentChunk(); | 438 FillBufferFromCurrentChunk(); |
| 439 } | 439 } |
| 440 | 440 |
| 441 DCHECK_EQ(current_.pos.chars - position, buffer_end_ - buffer_cursor_); | 441 DCHECK_EQ(current_.pos.chars - position, |
| 442 static_cast<size_t>(buffer_end_ - buffer_cursor_)); |
| 442 return buffer_end_ - buffer_cursor_; | 443 return buffer_end_ - buffer_cursor_; |
| 443 } | 444 } |
| 444 | 445 |
| 445 // ---------------------------------------------------------------------------- | 446 // ---------------------------------------------------------------------------- |
| 446 // Chunks - helper for One- + TwoByteExternalStreamingStream | 447 // Chunks - helper for One- + TwoByteExternalStreamingStream |
| 447 namespace { | 448 namespace { |
| 448 | 449 |
| 449 struct Chunk { | 450 struct Chunk { |
| 450 const uint8_t* data; | 451 const uint8_t* data; |
| 451 size_t byte_length; | 452 size_t byte_length; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 // chunk to indicate the end of the stream. | 491 // chunk to indicate the end of the stream. |
| 491 if (position >= end_pos) { | 492 if (position >= end_pos) { |
| 492 DCHECK(out_of_data); | 493 DCHECK(out_of_data); |
| 493 return chunks.size() - 1; | 494 return chunks.size() - 1; |
| 494 } | 495 } |
| 495 | 496 |
| 496 // We almost always 'stream', meaning we want data from the last chunk, so | 497 // We almost always 'stream', meaning we want data from the last chunk, so |
| 497 // let's look at chunks back-to-front. | 498 // let's look at chunks back-to-front. |
| 498 size_t chunk_no = chunks.size() - 1; | 499 size_t chunk_no = chunks.size() - 1; |
| 499 while (chunks[chunk_no].byte_pos > position) { | 500 while (chunks[chunk_no].byte_pos > position) { |
| 500 DCHECK_NE(chunk_no, 0); | 501 DCHECK_NE(chunk_no, 0u); |
| 501 chunk_no--; | 502 chunk_no--; |
| 502 } | 503 } |
| 503 DCHECK_LE(chunks[chunk_no].byte_pos, position); | 504 DCHECK_LE(chunks[chunk_no].byte_pos, position); |
| 504 DCHECK_LT(position, chunks[chunk_no].byte_pos + chunks[chunk_no].byte_length); | 505 DCHECK_LT(position, chunks[chunk_no].byte_pos + chunks[chunk_no].byte_length); |
| 505 return chunk_no; | 506 return chunk_no; |
| 506 } | 507 } |
| 507 | 508 |
| 508 } // anonymous namespace | 509 } // anonymous namespace |
| 509 | 510 |
| 510 // ---------------------------------------------------------------------------- | 511 // ---------------------------------------------------------------------------- |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 } | 587 } |
| 587 | 588 |
| 588 Chunk& current = chunks_[chunk_no]; | 589 Chunk& current = chunks_[chunk_no]; |
| 589 | 590 |
| 590 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a | 591 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a |
| 591 // character may be split between the previous and the current chunk. | 592 // character may be split between the previous and the current chunk. |
| 592 // If we find such a lonely byte at the beginning of the chunk, we'll use | 593 // If we find such a lonely byte at the beginning of the chunk, we'll use |
| 593 // one_char_buffer_ to hold the full character. | 594 // one_char_buffer_ to hold the full character. |
| 594 bool lonely_byte = (chunks_[chunk_no].byte_pos == (2 * position + 1)); | 595 bool lonely_byte = (chunks_[chunk_no].byte_pos == (2 * position + 1)); |
| 595 if (lonely_byte) { | 596 if (lonely_byte) { |
| 596 DCHECK_NE(chunk_no, 0); | 597 DCHECK_NE(chunk_no, 0u); |
| 597 Chunk& previous_chunk = chunks_[chunk_no - 1]; | 598 Chunk& previous_chunk = chunks_[chunk_no - 1]; |
| 598 #ifdef V8_TARGET_BIG_ENDIAN | 599 #ifdef V8_TARGET_BIG_ENDIAN |
| 599 uc16 character = current.data[0] | | 600 uc16 character = current.data[0] | |
| 600 previous_chunk.data[previous_chunk.byte_length - 1] << 8; | 601 previous_chunk.data[previous_chunk.byte_length - 1] << 8; |
| 601 #else | 602 #else |
| 602 uc16 character = previous_chunk.data[previous_chunk.byte_length - 1] | | 603 uc16 character = previous_chunk.data[previous_chunk.byte_length - 1] | |
| 603 current.data[0] << 8; | 604 current.data[0] << 8; |
| 604 #endif | 605 #endif |
| 605 | 606 |
| 606 one_char_buffer_ = character; | 607 one_char_buffer_ = character; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 buffer_cursor_ = buffer_; | 709 buffer_cursor_ = buffer_; |
| 709 buffer_end_ = buffer_ + FillBuffer(position, chunk_no); | 710 buffer_end_ = buffer_ + FillBuffer(position, chunk_no); |
| 710 DCHECK_EQ(pos(), position); | 711 DCHECK_EQ(pos(), position); |
| 711 DCHECK_LE(buffer_end_, buffer_start_ + kBufferSize); | 712 DCHECK_LE(buffer_end_, buffer_start_ + kBufferSize); |
| 712 return buffer_cursor_ < buffer_end_; | 713 return buffer_cursor_ < buffer_end_; |
| 713 } | 714 } |
| 714 } | 715 } |
| 715 | 716 |
| 716 size_t TwoByteExternalBufferedStream::FillBuffer(size_t position, | 717 size_t TwoByteExternalBufferedStream::FillBuffer(size_t position, |
| 717 size_t chunk_no) { | 718 size_t chunk_no) { |
| 718 DCHECK_EQ(chunks_[chunk_no].byte_pos % 2, 1); | 719 DCHECK_EQ(chunks_[chunk_no].byte_pos % 2, 1u); |
| 719 bool odd_start = true; | 720 bool odd_start = true; |
| 720 // Align buffer_pos_ to the size of the buffer. | 721 // Align buffer_pos_ to the size of the buffer. |
| 721 { | 722 { |
| 722 size_t new_pos = position / kBufferSize * kBufferSize; | 723 size_t new_pos = position / kBufferSize * kBufferSize; |
| 723 if (new_pos != position) { | 724 if (new_pos != position) { |
| 724 chunk_no = FindChunk(chunks_, source_, 2 * new_pos + 1); | 725 chunk_no = FindChunk(chunks_, source_, 2 * new_pos + 1); |
| 725 buffer_pos_ = new_pos; | 726 buffer_pos_ = new_pos; |
| 726 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | 727 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); |
| 727 position = new_pos; | 728 position = new_pos; |
| 728 odd_start = chunks_[chunk_no].byte_pos % 2; | 729 odd_start = chunks_[chunk_no].byte_pos % 2; |
| 729 } | 730 } |
| 730 } | 731 } |
| 731 | 732 |
| 732 Chunk* current = &chunks_[chunk_no]; | 733 Chunk* current = &chunks_[chunk_no]; |
| 733 | 734 |
| 734 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a | 735 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a |
| 735 // character may be split between the previous and the current chunk. | 736 // character may be split between the previous and the current chunk. |
| 736 // If we find such a lonely byte at the beginning of the chunk, we'll copy | 737 // If we find such a lonely byte at the beginning of the chunk, we'll copy |
| 737 // it to the first byte in buffer_. | 738 // it to the first byte in buffer_. |
| 738 size_t totalLength = 0; | 739 size_t totalLength = 0; |
| 739 bool lonely_byte = (current->byte_pos == (2 * position + 1)); | 740 bool lonely_byte = (current->byte_pos == (2 * position + 1)); |
| 740 if (lonely_byte) { | 741 if (lonely_byte) { |
| 741 DCHECK_NE(chunk_no, 0); | 742 DCHECK_NE(chunk_no, 0u); |
| 742 Chunk& previous_chunk = chunks_[chunk_no - 1]; | 743 Chunk& previous_chunk = chunks_[chunk_no - 1]; |
| 743 *reinterpret_cast<uint8_t*>(buffer_) = | 744 *reinterpret_cast<uint8_t*>(buffer_) = |
| 744 previous_chunk.data[previous_chunk.byte_length - 1]; | 745 previous_chunk.data[previous_chunk.byte_length - 1]; |
| 745 totalLength++; | 746 totalLength++; |
| 746 } | 747 } |
| 747 | 748 |
| 748 // Common case: character is in current chunk. | 749 // Common case: character is in current chunk. |
| 749 DCHECK_LE(current->byte_pos, 2 * position + odd_start); | 750 DCHECK_LE(current->byte_pos, 2 * position + odd_start); |
| 750 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); | 751 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); |
| 751 | 752 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 return new OneByteExternalStreamingStream(source_stream); | 836 return new OneByteExternalStreamingStream(source_stream); |
| 836 case v8::ScriptCompiler::StreamedSource::UTF8: | 837 case v8::ScriptCompiler::StreamedSource::UTF8: |
| 837 return new Utf8ExternalStreamingStream(source_stream); | 838 return new Utf8ExternalStreamingStream(source_stream); |
| 838 } | 839 } |
| 839 UNREACHABLE(); | 840 UNREACHABLE(); |
| 840 return nullptr; | 841 return nullptr; |
| 841 } | 842 } |
| 842 | 843 |
| 843 } // namespace internal | 844 } // namespace internal |
| 844 } // namespace v8 | 845 } // namespace v8 |
| OLD | NEW |