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 |