Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/parsing/scanner-character-streams.cc

Issue 2469723002: Corrected implementation of TwoByteExternalBufferedStream. (Closed)
Patch Set: Corrected implementation of TwoByteExternalBufferedStream Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/cctest/parsing/test-scanner-streams.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/cctest/parsing/test-scanner-streams.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698