diff options
author | Michaël Zasso <targos@protonmail.com> | 2022-01-29 08:33:07 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2022-02-02 17:23:18 +0100 |
commit | 974ab4060fe3eff74dc0a62a5a27d516738f4c55 (patch) | |
tree | 30fbcca796ca5cc7b4abf917e716e2b02899cb7a /deps/v8/src/parsing/scanner-character-streams.cc | |
parent | 4318b2348dbcd5003e0c4a14b5fe378cceec3c81 (diff) | |
download | node-new-974ab4060fe3eff74dc0a62a5a27d516738f4c55.tar.gz |
deps: update V8 to 9.8.177.9
PR-URL: https://github.com/nodejs/node/pull/41610
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/scanner-character-streams.cc')
-rw-r--r-- | deps/v8/src/parsing/scanner-character-streams.cc | 145 |
1 files changed, 81 insertions, 64 deletions
diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc index 5ecd85f2f2..34a8788c57 100644 --- a/deps/v8/src/parsing/scanner-character-streams.cc +++ b/deps/v8/src/parsing/scanner-character-streams.cc @@ -153,52 +153,47 @@ template <typename Char> class ChunkedStream { public: explicit ChunkedStream(ScriptCompiler::ExternalSourceStream* source) - : source_(source) {} + : source_(source), chunks_(std::make_shared<std::vector<Chunk>>()) {} - ChunkedStream(const ChunkedStream&) V8_NOEXCEPT { - // TODO(rmcilroy): Implement cloning for chunked streams. - UNREACHABLE(); - } + ChunkedStream(const ChunkedStream& other) V8_NOEXCEPT + : source_(nullptr), + chunks_(other.chunks_) {} // The no_gc argument is only here because of the templated way this class // is used along with other implementations that require V8 heap access. Range<Char> GetDataAt(size_t pos, RuntimeCallStats* stats, DisallowGarbageCollection* no_gc = nullptr) { - Chunk chunk = FindChunk(pos, stats); + Chunk& chunk = FindChunk(pos, stats); size_t buffer_end = chunk.length; size_t buffer_pos = std::min(buffer_end, pos - chunk.position); - return {&chunk.data[buffer_pos], &chunk.data[buffer_end]}; - } - - ~ChunkedStream() { - for (Chunk& chunk : chunks_) delete[] chunk.data; + return {&chunk.data.get()[buffer_pos], &chunk.data.get()[buffer_end]}; } - static const bool kCanBeCloned = false; + static const bool kCanBeCloned = true; static const bool kCanAccessHeap = false; private: struct Chunk { Chunk(const Char* const data, size_t position, size_t length) : data(data), position(position), length(length) {} - const Char* const data; + std::unique_ptr<const Char[]> data; // The logical position of data. const size_t position; const size_t length; size_t end_position() const { return position + length; } }; - Chunk FindChunk(size_t position, RuntimeCallStats* stats) { - while (V8_UNLIKELY(chunks_.empty())) FetchChunk(size_t{0}, stats); + Chunk& FindChunk(size_t position, RuntimeCallStats* stats) { + while (V8_UNLIKELY(chunks_->empty())) FetchChunk(size_t{0}, stats); // Walk forwards while the position is in front of the current chunk. - while (position >= chunks_.back().end_position() && - chunks_.back().length > 0) { - FetchChunk(chunks_.back().end_position(), stats); + while (position >= chunks_->back().end_position() && + chunks_->back().length > 0) { + FetchChunk(chunks_->back().end_position(), stats); } // Walk backwards. - for (auto reverse_it = chunks_.rbegin(); reverse_it != chunks_.rend(); + for (auto reverse_it = chunks_->rbegin(); reverse_it != chunks_->rend(); ++reverse_it) { if (reverse_it->position <= position) return *reverse_it; } @@ -210,11 +205,15 @@ class ChunkedStream { size_t length) { // Incoming data has to be aligned to Char size. DCHECK_EQ(0, length % sizeof(Char)); - chunks_.emplace_back(reinterpret_cast<const Char*>(data), position, - length / sizeof(Char)); + chunks_->emplace_back(reinterpret_cast<const Char*>(data), position, + length / sizeof(Char)); } void FetchChunk(size_t position, RuntimeCallStats* stats) { + // Cloned ChunkedStreams have a null source, and therefore can't fetch any + // new data. + DCHECK_NOT_NULL(source_); + const uint8_t* data = nullptr; size_t length; { @@ -227,7 +226,7 @@ class ChunkedStream { ScriptCompiler::ExternalSourceStream* source_; protected: - std::vector<struct Chunk> chunks_; + std::shared_ptr<std::vector<struct Chunk>> chunks_; }; // Provides a buffered utf-16 view on the bytes from the underlying ByteStream. @@ -522,18 +521,18 @@ class Utf8ExternalStreamingStream final : public BufferedUtf16CharacterStream { public: Utf8ExternalStreamingStream( ScriptCompiler::ExternalSourceStream* source_stream) - : current_({0, {0, 0, 0, unibrow::Utf8::State::kAccept}}), + : chunks_(std::make_shared<std::vector<Chunk>>()), + current_({0, {0, 0, 0, unibrow::Utf8::State::kAccept}}), source_stream_(source_stream) {} - ~Utf8ExternalStreamingStream() final { - for (const Chunk& chunk : chunks_) delete[] chunk.data; - } + ~Utf8ExternalStreamingStream() final = default; bool can_access_heap() const final { return false; } - bool can_be_cloned() const final { return false; } + bool can_be_cloned() const final { return true; } std::unique_ptr<Utf16CharacterStream> Clone() const override { - UNREACHABLE(); + return std::unique_ptr<Utf16CharacterStream>( + new Utf8ExternalStreamingStream(*this)); } protected: @@ -563,11 +562,18 @@ class Utf8ExternalStreamingStream final : public BufferedUtf16CharacterStream { // - The chunk data (data pointer and length), and // - the position at the first byte of the chunk. struct Chunk { - const uint8_t* data; + Chunk(const uint8_t* data, size_t length, StreamPosition start) + : data(data), length(length), start(start) {} + std::unique_ptr<const uint8_t[]> data; size_t length; StreamPosition start; }; + Utf8ExternalStreamingStream(const Utf8ExternalStreamingStream& source_stream) + V8_NOEXCEPT : chunks_(source_stream.chunks_), + current_({0, {0, 0, 0, unibrow::Utf8::State::kAccept}}), + source_stream_(nullptr) {} + // Within the current chunk, skip forward from current_ towards position. bool SkipToPosition(size_t position); // Within the current chunk, fill the buffer_ (while it has capacity). @@ -578,7 +584,9 @@ class Utf8ExternalStreamingStream final : public BufferedUtf16CharacterStream { // (This call is potentially expensive.) void SearchPosition(size_t position); - std::vector<Chunk> chunks_; + Chunk& GetChunk(size_t chunk_no) { return (*chunks_)[chunk_no]; } + + std::shared_ptr<std::vector<Chunk>> chunks_; Position current_; ScriptCompiler::ExternalSourceStream* source_stream_; }; @@ -589,14 +597,14 @@ bool Utf8ExternalStreamingStream::SkipToPosition(size_t position) { // Already there? Then return immediately. if (current_.pos.chars == position) return true; - const Chunk& chunk = chunks_[current_.chunk_no]; + const Chunk& chunk = GetChunk(current_.chunk_no); DCHECK(current_.pos.bytes >= chunk.start.bytes); unibrow::Utf8::State state = chunk.start.state; uint32_t incomplete_char = chunk.start.incomplete_char; size_t it = current_.pos.bytes - chunk.start.bytes; - const uint8_t* cursor = &chunk.data[it]; - const uint8_t* end = &chunk.data[chunk.length]; + const uint8_t* cursor = &chunk.data.get()[it]; + const uint8_t* end = &chunk.data.get()[chunk.length]; size_t chars = current_.pos.chars; @@ -622,7 +630,7 @@ bool Utf8ExternalStreamingStream::SkipToPosition(size_t position) { } } - current_.pos.bytes = chunk.start.bytes + (cursor - chunk.data); + current_.pos.bytes = chunk.start.bytes + (cursor - chunk.data.get()); current_.pos.chars = chars; current_.pos.incomplete_char = incomplete_char; current_.pos.state = state; @@ -632,11 +640,11 @@ bool Utf8ExternalStreamingStream::SkipToPosition(size_t position) { } void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { - DCHECK_LT(current_.chunk_no, chunks_.size()); + DCHECK_LT(current_.chunk_no, chunks_->size()); DCHECK_EQ(buffer_start_, buffer_cursor_); DCHECK_LT(buffer_end_ + 1, buffer_start_ + kBufferSize); - const Chunk& chunk = chunks_[current_.chunk_no]; + const Chunk& chunk = GetChunk(current_.chunk_no); // The buffer_ is writable, but buffer_*_ members are const. So we get a // non-const pointer into buffer that points to the same char as buffer_end_. @@ -662,8 +670,8 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { } size_t it = current_.pos.bytes - chunk.start.bytes; - const uint8_t* cursor = chunk.data + it; - const uint8_t* end = chunk.data + chunk.length; + const uint8_t* cursor = chunk.data.get() + it; + const uint8_t* end = chunk.data.get() + chunk.length; // Deal with possible BOM. if (V8_UNLIKELY(current_.pos.bytes < 3 && current_.pos.chars == 0)) { @@ -711,7 +719,7 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { output_cursor += ascii_length; } - current_.pos.bytes = chunk.start.bytes + (cursor - chunk.data); + current_.pos.bytes = chunk.start.bytes + (cursor - chunk.data.get()); current_.pos.chars += (output_cursor - buffer_end_); current_.pos.incomplete_char = incomplete_char; current_.pos.state = state; @@ -722,12 +730,20 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { bool Utf8ExternalStreamingStream::FetchChunk() { RCS_SCOPE(runtime_call_stats(), RuntimeCallCounterId::kGetMoreDataCallback); - DCHECK_EQ(current_.chunk_no, chunks_.size()); - DCHECK(chunks_.empty() || chunks_.back().length != 0); + DCHECK_EQ(current_.chunk_no, chunks_->size()); + DCHECK(chunks_->empty() || chunks_->back().length != 0); + + // Clone Utf8ExternalStreamingStreams have a null source stream, and + // therefore can't fetch any new data. + DCHECK_NOT_NULL(source_stream_); + + // Utf8ExternalStreamingStreams that have been cloned are not allowed to fetch + // any more. + DCHECK_EQ(chunks_.use_count(), 1); const uint8_t* chunk = nullptr; size_t length = source_stream_->GetMoreData(&chunk); - chunks_.push_back({chunk, length, current_.pos}); + chunks_->emplace_back(chunk, length, current_.pos); return length > 0; } @@ -738,8 +754,8 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) { // FillBuffer right after the current buffer. if (current_.pos.chars == position) return; - // No chunks. Fetch at least one, so we can assume !chunks_.empty() below. - if (chunks_.empty()) { + // No chunks. Fetch at least one, so we can assume !chunks_->empty() below. + if (chunks_->empty()) { DCHECK_EQ(current_.chunk_no, 0u); DCHECK_EQ(current_.pos.bytes, 0u); DCHECK_EQ(current_.pos.chars, 0u); @@ -748,38 +764,39 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) { // Search for the last chunk whose start position is less or equal to // position. - size_t chunk_no = chunks_.size() - 1; - while (chunk_no > 0 && chunks_[chunk_no].start.chars > position) { + size_t chunk_no = chunks_->size() - 1; + while (chunk_no > 0 && GetChunk(chunk_no).start.chars > position) { chunk_no--; } // Did we find the terminating (zero-length) chunk? Then we're seeking // behind the end of the data, and position does not exist. // Set current_ to point to the terminating chunk. - if (chunks_[chunk_no].length == 0) { - current_ = {chunk_no, chunks_[chunk_no].start}; + if (GetChunk(chunk_no).length == 0) { + current_ = {chunk_no, GetChunk(chunk_no).start}; return; } // Did we find the non-last chunk? Then our position must be within chunk_no. - if (chunk_no + 1 < chunks_.size()) { + if (chunk_no + 1 < chunks_->size()) { // Fancy-pants optimization for ASCII chunks within a utf-8 stream. // (Many web sites declare utf-8 encoding, but use only (or almost only) the // ASCII subset for their JavaScript sources. We can exploit this, by // checking whether the # bytes in a chunk are equal to the # chars, and if // so avoid the expensive SkipToPosition.) bool ascii_only_chunk = - chunks_[chunk_no].start.incomplete_char == 0 && - (chunks_[chunk_no + 1].start.bytes - chunks_[chunk_no].start.bytes) == - (chunks_[chunk_no + 1].start.chars - chunks_[chunk_no].start.chars); + GetChunk(chunk_no).start.incomplete_char == 0 && + (GetChunk(chunk_no + 1).start.bytes - GetChunk(chunk_no).start.bytes) == + (GetChunk(chunk_no + 1).start.chars - + GetChunk(chunk_no).start.chars); if (ascii_only_chunk) { - size_t skip = position - chunks_[chunk_no].start.chars; + size_t skip = position - GetChunk(chunk_no).start.chars; current_ = {chunk_no, - {chunks_[chunk_no].start.bytes + skip, - chunks_[chunk_no].start.chars + skip, 0, + {GetChunk(chunk_no).start.bytes + skip, + GetChunk(chunk_no).start.chars + skip, 0, unibrow::Utf8::State::kAccept}}; } else { - current_ = {chunk_no, chunks_[chunk_no].start}; + current_ = {chunk_no, GetChunk(chunk_no).start}; SkipToPosition(position); } @@ -792,12 +809,12 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) { // What's left: We're in the last, non-terminating chunk. Our position // may be in the chunk, but it may also be in 'future' chunks, which we'll // have to obtain. - DCHECK_EQ(chunk_no, chunks_.size() - 1); - current_ = {chunk_no, chunks_[chunk_no].start}; + DCHECK_EQ(chunk_no, chunks_->size() - 1); + current_ = {chunk_no, GetChunk(chunk_no).start}; bool have_more_data = true; bool found = SkipToPosition(position); while (have_more_data && !found) { - DCHECK_EQ(current_.chunk_no, chunks_.size()); + DCHECK_EQ(current_.chunk_no, chunks_->size()); have_more_data = FetchChunk(); found = have_more_data && SkipToPosition(position); } @@ -805,9 +822,9 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) { // We'll return with a postion != the desired position only if we're out // of data. In that case, we'll point to the terminating chunk. DCHECK_EQ(found, current_.pos.chars == position); - DCHECK_EQ(have_more_data, chunks_.back().length != 0); + DCHECK_EQ(have_more_data, chunks_->back().length != 0); DCHECK_IMPLIES(!found, !have_more_data); - DCHECK_IMPLIES(!found, current_.chunk_no == chunks_.size() - 1); + DCHECK_IMPLIES(!found, current_.chunk_no == chunks_->size() - 1); } size_t Utf8ExternalStreamingStream::FillBuffer(size_t position) { @@ -815,8 +832,8 @@ size_t Utf8ExternalStreamingStream::FillBuffer(size_t position) { buffer_end_ = buffer_; SearchPosition(position); - bool out_of_data = current_.chunk_no != chunks_.size() && - chunks_[current_.chunk_no].length == 0 && + bool out_of_data = current_.chunk_no != chunks_->size() && + GetChunk(current_.chunk_no).length == 0 && current_.pos.incomplete_char == 0; if (out_of_data) return 0; @@ -826,7 +843,7 @@ size_t Utf8ExternalStreamingStream::FillBuffer(size_t position) { // can't guarantee progress with one chunk. Thus we iterate.) while (!out_of_data && buffer_cursor_ == buffer_end_) { // At end of current data, but there might be more? Then fetch it. - if (current_.chunk_no == chunks_.size()) { + if (current_.chunk_no == chunks_->size()) { out_of_data = !FetchChunk(); } FillBufferFromCurrentChunk(); |