Chromium Code Reviews| 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 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 // to point to position. Be careful when converting the byte positions (in | 623 // to point to position. Be careful when converting the byte positions (in |
| 624 // Chunk) to the ucs-2 character positions (in buffer_*_ members). | 624 // Chunk) to the ucs-2 character positions (in buffer_*_ members). |
| 625 buffer_start_ = reinterpret_cast<const uint16_t*>(current.data + odd_start); | 625 buffer_start_ = reinterpret_cast<const uint16_t*>(current.data + odd_start); |
| 626 buffer_end_ = buffer_start_ + number_chars; | 626 buffer_end_ = buffer_start_ + number_chars; |
| 627 buffer_pos_ = (current.byte_pos + odd_start) / 2; | 627 buffer_pos_ = (current.byte_pos + odd_start) / 2; |
| 628 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | 628 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); |
| 629 DCHECK_EQ(position, pos()); | 629 DCHECK_EQ(position, pos()); |
| 630 return true; | 630 return true; |
| 631 } | 631 } |
| 632 | 632 |
| 633 class TwoByteExternalBufferedStream : public Utf16CharacterStream { | |
| 634 public: | |
| 635 explicit TwoByteExternalBufferedStream( | |
| 636 ScriptCompiler::ExternalSourceStream* source); | |
| 637 ~TwoByteExternalBufferedStream(); | |
| 638 | |
| 639 protected: | |
| 640 static const size_t kBufferSize = 512; | |
| 641 | |
| 642 bool ReadBlock() override; | |
| 643 | |
| 644 // FillBuffer should read up to kBufferSize characters at position and store | |
| 645 // them into buffer_[0..]. It returns the number of characters stored. | |
| 646 size_t FillBuffer(size_t position, size_t chunk_no); | |
| 647 | |
| 648 // Fixed sized buffer that this class reads from. | |
| 649 // The base class' buffer_start_ should always point to buffer_. | |
| 650 uc16 buffer_[kBufferSize]; | |
| 651 | |
| 652 Chunks chunks_; | |
| 653 ScriptCompiler::ExternalSourceStream* source_; | |
| 654 }; | |
| 655 | |
| 656 TwoByteExternalBufferedStream::TwoByteExternalBufferedStream( | |
| 657 ScriptCompiler::ExternalSourceStream* source) | |
| 658 : Utf16CharacterStream(buffer_, buffer_, buffer_, 0), source_(source) {} | |
| 659 | |
| 660 TwoByteExternalBufferedStream::~TwoByteExternalBufferedStream() { | |
| 661 DeleteChunks(chunks_); | |
| 662 } | |
| 663 | |
| 664 bool TwoByteExternalBufferedStream::ReadBlock() { | |
| 665 size_t position = pos(); | |
| 666 // Find chunk in which the position belongs | |
| 667 size_t chunk_no = FindChunk(chunks_, source_, 2 * position + 1); | |
| 668 | |
| 669 // Out of data? Return 0. | |
| 670 if (chunks_[chunk_no].byte_length == 0) { | |
| 671 buffer_cursor_ = buffer_start_; | |
| 672 buffer_end_ = buffer_start_; | |
| 673 return false; | |
| 674 } | |
| 675 | |
| 676 Chunk& current = chunks_[chunk_no]; | |
| 677 | |
| 678 bool odd_start = current.byte_pos % 2; | |
| 679 // Common case: character is in current chunk. | |
| 680 DCHECK_LE(current.byte_pos, 2 * position + odd_start); | |
| 681 DCHECK_LT(2 * position + 1, current.byte_pos + current.byte_length); | |
| 682 | |
| 683 // If character starts on odd address copy text in buffer so there is always | |
| 684 // aligned access to characters. This is important on MIPS and ARM | |
| 685 // architectures. Otherwise read characters from memory directly. | |
| 686 if (!odd_start) { | |
| 687 buffer_start_ = reinterpret_cast<const uint16_t*>(current.data); | |
| 688 size_t number_chars = current.byte_length / 2; | |
| 689 buffer_end_ = buffer_start_ + number_chars; | |
| 690 buffer_pos_ = current.byte_pos / 2; | |
| 691 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | |
| 692 DCHECK_EQ(position, pos()); | |
| 693 return true; | |
| 694 } else { | |
| 695 buffer_pos_ = position; | |
| 696 buffer_cursor_ = buffer_; | |
| 697 buffer_end_ = buffer_ + FillBuffer(position, chunk_no); | |
| 698 DCHECK_EQ(pos(), position); | |
| 699 DCHECK_LE(buffer_end_, buffer_start_ + kBufferSize); | |
| 700 return buffer_cursor_ < buffer_end_; | |
| 701 } | |
| 702 } | |
| 703 | |
| 704 size_t TwoByteExternalBufferedStream::FillBuffer(size_t position, | |
| 705 size_t chunk_no) { | |
| 706 // Align buffer_pos_ to the size of the buffer. | |
| 707 { | |
| 708 size_t new_pos = position / kBufferSize * kBufferSize; | |
| 709 if (new_pos != position) { | |
| 710 chunk_no = FindChunk(chunks_, source_, 2 * new_pos + 1); | |
| 711 buffer_pos_ = new_pos; | |
| 712 buffer_cursor_ = buffer_start_ + (position - buffer_pos_); | |
| 713 position = new_pos; | |
| 714 } | |
| 715 } | |
| 716 | |
| 717 Chunk* current = &chunks_[chunk_no]; | |
| 718 | |
| 719 // Annoying edge case: Chunks may not be 2-byte aligned, meaning that a | |
| 720 // character may be split between the previous and the current chunk. | |
| 721 // If we find such a lonely byte at the beginning of the chunk, we'll copy | |
| 722 // it to the first byte in buffer_. | |
| 723 size_t totalLength = 0; | |
| 724 bool lonely_byte = (current->byte_pos == (2 * position + 1)); | |
| 725 if (lonely_byte) { | |
| 726 DCHECK_NE(chunk_no, 0); | |
| 727 Chunk& previous_chunk = chunks_[chunk_no - 1]; | |
| 728 *reinterpret_cast<uint8_t*>(buffer_) = | |
| 729 previous_chunk.data[previous_chunk.byte_length - 1]; | |
| 730 totalLength++; | |
| 731 } | |
| 732 | |
| 733 // Common case: character is in current chunk. | |
| 734 DCHECK_LE(current->byte_pos, 2 * position + 1); | |
| 735 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); | |
| 736 | |
| 737 // Copy characters from current chunk starting from chunk_pos to the end of | |
| 738 // buffer or chunk. | |
| 739 size_t chunk_pos = position - current->byte_pos / 2; | |
| 740 bool middle_of_chunk = chunk_pos != 0; | |
| 741 size_t bytes_to_move = | |
| 742 i::Min(2 * kBufferSize - !middle_of_chunk, | |
| 743 current->byte_length - 2 * chunk_pos + middle_of_chunk); | |
| 744 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + !middle_of_chunk, | |
| 745 current->data + 2 * chunk_pos - middle_of_chunk, bytes_to_move); | |
| 746 | |
| 747 // Fill up the rest of the buffer if there is space and data left. | |
| 748 totalLength += bytes_to_move; | |
| 749 position = (current->byte_pos + current->byte_length) / 2; | |
| 750 if (position - buffer_pos_ < kBufferSize) { | |
| 751 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); | |
| 752 current = &chunks_[chunk_no]; | |
| 753 bytes_to_move = i::Min(2 * kBufferSize - totalLength, current->byte_length); | |
| 754 while (bytes_to_move && current->byte_pos % 2) { | |
| 755 // Common case: character is in current chunk. | |
| 756 DCHECK_LE(current->byte_pos, 2 * position + 1); | |
| 757 DCHECK_LT(2 * position + 1, current->byte_pos + current->byte_length); | |
| 758 | |
| 759 i::MemMove(reinterpret_cast<uint8_t*>(buffer_) + totalLength, | |
| 760 current->data, bytes_to_move); | |
| 761 totalLength += bytes_to_move; | |
| 762 position = (current->byte_pos + current->byte_length) / 2; | |
| 763 chunk_no = FindChunk(chunks_, source_, 2 * position + 1); | |
| 764 current = &chunks_[chunk_no]; | |
| 765 bytes_to_move = | |
| 766 i::Min(2 * kBufferSize - totalLength, current->byte_length); | |
| 767 } | |
| 768 } | |
| 769 return totalLength / 2; | |
| 770 } | |
| 771 | |
| 633 // ---------------------------------------------------------------------------- | 772 // ---------------------------------------------------------------------------- |
| 634 // ScannerStream: Create stream instances. | 773 // ScannerStream: Create stream instances. |
| 635 | 774 |
| 636 Utf16CharacterStream* ScannerStream::For(Handle<String> data) { | 775 Utf16CharacterStream* ScannerStream::For(Handle<String> data) { |
| 637 return ScannerStream::For(data, 0, data->length()); | 776 return ScannerStream::For(data, 0, data->length()); |
| 638 } | 777 } |
| 639 | 778 |
| 640 Utf16CharacterStream* ScannerStream::For(Handle<String> data, int start_pos, | 779 Utf16CharacterStream* ScannerStream::For(Handle<String> data, int start_pos, |
| 641 int end_pos) { | 780 int end_pos) { |
| 642 DCHECK(start_pos >= 0); | 781 DCHECK(start_pos >= 0); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 662 const char* data, size_t length) { | 801 const char* data, size_t length) { |
| 663 return std::unique_ptr<Utf16CharacterStream>( | 802 return std::unique_ptr<Utf16CharacterStream>( |
| 664 new ExternalOneByteStringUtf16CharacterStream(data, length)); | 803 new ExternalOneByteStringUtf16CharacterStream(data, length)); |
| 665 } | 804 } |
| 666 | 805 |
| 667 Utf16CharacterStream* ScannerStream::For( | 806 Utf16CharacterStream* ScannerStream::For( |
| 668 ScriptCompiler::ExternalSourceStream* source_stream, | 807 ScriptCompiler::ExternalSourceStream* source_stream, |
| 669 v8::ScriptCompiler::StreamedSource::Encoding encoding) { | 808 v8::ScriptCompiler::StreamedSource::Encoding encoding) { |
| 670 switch (encoding) { | 809 switch (encoding) { |
| 671 case v8::ScriptCompiler::StreamedSource::TWO_BYTE: | 810 case v8::ScriptCompiler::StreamedSource::TWO_BYTE: |
| 811 #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM) | |
|
vogelheim
2016/10/26 16:44:45
Please add the same #if around the two implementat
| |
| 672 return new TwoByteExternalStreamingStream(source_stream); | 812 return new TwoByteExternalStreamingStream(source_stream); |
| 813 #else | |
| 814 return new TwoByteExternalBufferedStream(source_stream); | |
| 815 #endif | |
| 673 case v8::ScriptCompiler::StreamedSource::ONE_BYTE: | 816 case v8::ScriptCompiler::StreamedSource::ONE_BYTE: |
| 674 return new OneByteExternalStreamingStream(source_stream); | 817 return new OneByteExternalStreamingStream(source_stream); |
| 675 case v8::ScriptCompiler::StreamedSource::UTF8: | 818 case v8::ScriptCompiler::StreamedSource::UTF8: |
| 676 return new Utf8ExternalStreamingStream(source_stream); | 819 return new Utf8ExternalStreamingStream(source_stream); |
| 677 } | 820 } |
| 678 UNREACHABLE(); | 821 UNREACHABLE(); |
| 679 return nullptr; | 822 return nullptr; |
| 680 } | 823 } |
| 681 | 824 |
| 682 } // namespace internal | 825 } // namespace internal |
| 683 } // namespace v8 | 826 } // namespace v8 |
| OLD | NEW |