| 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 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 size_t OneByteExternalStreamingStream::FillBuffer(size_t position) { | 530 size_t OneByteExternalStreamingStream::FillBuffer(size_t position) { |
| 531 const Chunk& chunk = chunks_[FindChunk(chunks_, source_, position)]; | 531 const Chunk& chunk = chunks_[FindChunk(chunks_, source_, position)]; |
| 532 if (chunk.byte_length == 0) return 0; | 532 if (chunk.byte_length == 0) return 0; |
| 533 | 533 |
| 534 size_t start_pos = position - chunk.byte_pos; | 534 size_t start_pos = position - chunk.byte_pos; |
| 535 size_t len = i::Min(kBufferSize, chunk.byte_length - start_pos); | 535 size_t len = i::Min(kBufferSize, chunk.byte_length - start_pos); |
| 536 i::CopyCharsUnsigned(buffer_, chunk.data + start_pos, len); | 536 i::CopyCharsUnsigned(buffer_, chunk.data + start_pos, len); |
| 537 return len; | 537 return len; |
| 538 } | 538 } |
| 539 | 539 |
| 540 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM) | 540 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64) |
| 541 // ---------------------------------------------------------------------------- | 541 // ---------------------------------------------------------------------------- |
| 542 // TwoByteExternalStreamingStream | 542 // TwoByteExternalStreamingStream |
| 543 // | 543 // |
| 544 // A stream of ucs-2 data, delivered in chunks. Chunks may be 'cut' into the | 544 // A stream of ucs-2 data, delivered in chunks. Chunks may be 'cut' into the |
| 545 // middle of characters (or even contain only one byte), which adds a bit | 545 // middle of characters (or even contain only one byte), which adds a bit |
| 546 // of complexity. This stream avoid all data copying, except for characters | 546 // of complexity. This stream avoid all data copying, except for characters |
| 547 // that cross chunk boundaries. | 547 // that cross chunk boundaries. |
| 548 | 548 |
| 549 class TwoByteExternalStreamingStream : public Utf16CharacterStream { | 549 class TwoByteExternalStreamingStream : public Utf16CharacterStream { |
| 550 public: | 550 public: |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 // architectures. Otherwise read characters from memory directly. | 696 // architectures. Otherwise read characters from memory directly. |
| 697 if (!odd_start) { | 697 if (!odd_start) { |
| 698 buffer_start_ = reinterpret_cast<const uint16_t*>(current.data); | 698 buffer_start_ = reinterpret_cast<const uint16_t*>(current.data); |
| 699 size_t number_chars = current.byte_length / 2; | 699 size_t number_chars = current.byte_length / 2; |
| 700 buffer_end_ = buffer_start_ + number_chars; | 700 buffer_end_ = buffer_start_ + number_chars; |
| 701 buffer_pos_ = current.byte_pos / 2; | 701 buffer_pos_ = current.byte_pos / 2; |
| 702 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | 702 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); |
| 703 DCHECK_EQ(position, pos()); | 703 DCHECK_EQ(position, pos()); |
| 704 return true; | 704 return true; |
| 705 } else { | 705 } else { |
| 706 buffer_start_ = buffer_; |
| 706 buffer_pos_ = position; | 707 buffer_pos_ = position; |
| 707 buffer_cursor_ = buffer_; | 708 buffer_cursor_ = buffer_; |
| 708 buffer_end_ = buffer_ + FillBuffer(position, chunk_no); | 709 buffer_end_ = buffer_ + FillBuffer(position, chunk_no); |
| 709 DCHECK_EQ(pos(), position); | 710 DCHECK_EQ(pos(), position); |
| 710 DCHECK_LE(buffer_end_, buffer_start_ + kBufferSize); | 711 DCHECK_LE(buffer_end_, buffer_start_ + kBufferSize); |
| 711 return buffer_cursor_ < buffer_end_; | 712 return buffer_cursor_ < buffer_end_; |
| 712 } | 713 } |
| 713 } | 714 } |
| 714 | 715 |
| 715 size_t TwoByteExternalBufferedStream::FillBuffer(size_t position, | 716 size_t TwoByteExternalBufferedStream::FillBuffer(size_t position, |
| 716 size_t chunk_no) { | 717 size_t chunk_no) { |
| 718 DCHECK_EQ(chunks_[chunk_no].byte_pos % 2, 1); |
| 719 bool odd_start = true; |
| 717 // Align buffer_pos_ to the size of the buffer. | 720 // Align buffer_pos_ to the size of the buffer. |
| 718 { | 721 { |
| 719 size_t new_pos = position / kBufferSize * kBufferSize; | 722 size_t new_pos = position / kBufferSize * kBufferSize; |
| 720 if (new_pos != position) { | 723 if (new_pos != position) { |
| 721 chunk_no = FindChunk(chunks_, source_, 2 * new_pos + 1); | 724 chunk_no = FindChunk(chunks_, source_, 2 * new_pos + 1); |
| 722 buffer_pos_ = new_pos; | 725 buffer_pos_ = new_pos; |
| 723 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | 726 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); |
| 724 position = new_pos; | 727 position = new_pos; |
| 728 odd_start = chunks_[chunk_no].byte_pos % 2; |
| 725 } | 729 } |
| 726 } | 730 } |
| 727 | 731 |
| 728 Chunk* current = &chunks_[chunk_no]; | 732 Chunk* current = &chunks_[chunk_no]; |
| 729 | 733 |
| 730 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a | 734 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a |
| 731 // character may be split between the previous and the current chunk. | 735 // character may be split between the previous and the current chunk. |
| 732 // If we find such a lonely byte at the beginning of the chunk, we'll copy | 736 // If we find such a lonely byte at the beginning of the chunk, we'll copy |
| 733 // it to the first byte in buffer_. | 737 // it to the first byte in buffer_. |
| 734 size_t totalLength = 0; | 738 size_t totalLength = 0; |
| 735 bool lonely_byte = (current->byte_pos == (2 * position + 1)); | 739 bool lonely_byte = (current->byte_pos == (2 * position + 1)); |
| 736 if (lonely_byte) { | 740 if (lonely_byte) { |
| 737 DCHECK_NE(chunk_no, 0); | 741 DCHECK_NE(chunk_no, 0); |
| 738 Chunk& previous_chunk = chunks_[chunk_no - 1]; | 742 Chunk& previous_chunk = chunks_[chunk_no - 1]; |
| 739 *reinterpret_cast<uint8_t*>(buffer_) = | 743 *reinterpret_cast<uint8_t*>(buffer_) = |
| 740 previous_chunk.data[previous_chunk.byte_length - 1]; | 744 previous_chunk.data[previous_chunk.byte_length - 1]; |
| 741 totalLength++; | 745 totalLength++; |
| 742 } | 746 } |
| 743 | 747 |
| 744 // Common case: character is in current chunk. | 748 // Common case: character is in current chunk. |
| 745 DCHECK_LE(current->byte_pos, 2 * position + 1); | 749 DCHECK_LE(current->byte_pos, 2 * position + odd_start); |
| 746 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); | 750 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); |
| 747 | 751 |
| 748 // Copy characters from current chunk starting from chunk_pos to the end of | 752 // Copy characters from current chunk starting from chunk_pos to the end of |
| 749 // buffer or chunk. | 753 // buffer or chunk. |
| 750 size_t chunk_pos = position - current->byte_pos / 2; | 754 size_t chunk_pos = position - current->byte_pos / 2; |
| 751 bool middle_of_chunk = chunk_pos != 0; | 755 size_t start_offset = odd_start && chunk_pos != 0; |
| 752 size_t bytes_to_move = | 756 size_t bytes_to_move = |
| 753 i::Min(2 * kBufferSize - !middle_of_chunk, | 757 i::Min(2 * kBufferSize - lonely_byte, |
| 754 current->byte_length - 2 * chunk_pos + middle_of_chunk); | 758 current->byte_length - 2 * chunk_pos + start_offset); |
| 755 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + !middle_of_chunk, | 759 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + lonely_byte, |
| 756 current->data + 2 * chunk_pos - middle_of_chunk, bytes_to_move); | 760 current->data + 2 * chunk_pos - start_offset, bytes_to_move); |
| 757 | 761 |
| 758 // Fill up the rest of the buffer if there is space and data left. | 762 // Fill up the rest of the buffer if there is space and data left. |
| 759 totalLength += bytes_to_move; | 763 totalLength += bytes_to_move; |
| 760 position = (current->byte_pos + current->byte_length) / 2; | 764 position = (current->byte_pos + current->byte_length) / 2; |
| 761 if (position - buffer_pos_ < kBufferSize) { | 765 if (position - buffer_pos_ < kBufferSize) { |
| 762 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); | 766 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); |
| 763 current = &chunks_[chunk_no]; | 767 current = &chunks_[chunk_no]; |
| 768 odd_start = current->byte_pos % 2; |
| 764 bytes_to_move = i::Min(2 * kBufferSize - totalLength, current->byte_length); | 769 bytes_to_move = i::Min(2 * kBufferSize - totalLength, current->byte_length); |
| 765 while (bytes_to_move && current->byte_pos % 2) { | 770 while (bytes_to_move) { |
| 766 // Common case: character is in current chunk. | 771 // Common case: character is in current chunk. |
| 767 DCHECK_LE(current->byte_pos, 2 * position + 1); | 772 DCHECK_LE(current->byte_pos, 2 * position + odd_start); |
| 768 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); | 773 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); |
| 769 | 774 |
| 770 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + totalLength, | 775 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + totalLength, |
| 771 current->data, bytes_to_move); | 776 current->data, bytes_to_move); |
| 772 totalLength += bytes_to_move; | 777 totalLength += bytes_to_move; |
| 773 position = (current->byte_pos + current->byte_length) / 2; | 778 position = (current->byte_pos + current->byte_length) / 2; |
| 774 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); | 779 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); |
| 775 current = &chunks_[chunk_no]; | 780 current = &chunks_[chunk_no]; |
| 781 odd_start = current->byte_pos % 2; |
| 776 bytes_to_move = | 782 bytes_to_move = |
| 777 i::Min(2 * kBufferSize - totalLength, current->byte_length); | 783 i::Min(2 * kBufferSize - totalLength, current->byte_length); |
| 778 } | 784 } |
| 779 } | 785 } |
| 780 return totalLength / 2; | 786 return totalLength / 2; |
| 781 } | 787 } |
| 782 #endif | 788 #endif |
| 783 | 789 |
| 784 // ---------------------------------------------------------------------------- | 790 // ---------------------------------------------------------------------------- |
| 785 // ScannerStream: Create stream instances. | 791 // ScannerStream: Create stream instances. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 813 const char* data, size_t length) { | 819 const char* data, size_t length) { |
| 814 return std::unique_ptr<Utf16CharacterStream>( | 820 return std::unique_ptr<Utf16CharacterStream>( |
| 815 new ExternalOneByteStringUtf16CharacterStream(data, length)); | 821 new ExternalOneByteStringUtf16CharacterStream(data, length)); |
| 816 } | 822 } |
| 817 | 823 |
| 818 Utf16CharacterStream* ScannerStream::For( | 824 Utf16CharacterStream* ScannerStream::For( |
| 819 ScriptCompiler::ExternalSourceStream* source_stream, | 825 ScriptCompiler::ExternalSourceStream* source_stream, |
| 820 v8::ScriptCompiler::StreamedSource::Encoding encoding) { | 826 v8::ScriptCompiler::StreamedSource::Encoding encoding) { |
| 821 switch (encoding) { | 827 switch (encoding) { |
| 822 case v8::ScriptCompiler::StreamedSource::TWO_BYTE: | 828 case v8::ScriptCompiler::StreamedSource::TWO_BYTE: |
| 823 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM) | 829 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64) |
| 824 return new TwoByteExternalStreamingStream(source_stream); | 830 return new TwoByteExternalStreamingStream(source_stream); |
| 825 #else | 831 #else |
| 826 return new TwoByteExternalBufferedStream(source_stream); | 832 return new TwoByteExternalBufferedStream(source_stream); |
| 827 #endif | 833 #endif |
| 828 case v8::ScriptCompiler::StreamedSource::ONE_BYTE: | 834 case v8::ScriptCompiler::StreamedSource::ONE_BYTE: |
| 829 return new OneByteExternalStreamingStream(source_stream); | 835 return new OneByteExternalStreamingStream(source_stream); |
| 830 case v8::ScriptCompiler::StreamedSource::UTF8: | 836 case v8::ScriptCompiler::StreamedSource::UTF8: |
| 831 return new Utf8ExternalStreamingStream(source_stream); | 837 return new Utf8ExternalStreamingStream(source_stream); |
| 832 } | 838 } |
| 833 UNREACHABLE(); | 839 UNREACHABLE(); |
| 834 return nullptr; | 840 return nullptr; |
| 835 } | 841 } |
| 836 | 842 |
| 837 } // namespace internal | 843 } // namespace internal |
| 838 } // namespace v8 | 844 } // namespace v8 |
| OLD | NEW |