Commit 85a0542d authored by vogelheim's avatar vogelheim Committed by Commit bot

Implement bookmarks for ExternalStreamingStream.

(Requires the embedder's ExternalSourceStream implementation to cooperate.
 See crrev.com/1154883003 for Blink.)

R=jochen@chromium.org
BUG=chromium:470930
LOG=Y

Review URL: https://codereview.chromium.org/1156733002

Cr-Commit-Position: refs/heads/master@{#28610}
parent a5f61fca
......@@ -1220,6 +1220,23 @@ class V8_EXPORT ScriptCompiler {
* V8 has parsed the data it received so far.
*/
virtual size_t GetMoreData(const uint8_t** src) = 0;
/**
* V8 calls this method to set a 'bookmark' at the current position in
* the source stream, for the purpose of (maybe) later calling
* ResetToBookmark. If ResetToBookmark is called later, then subsequent
* calls to GetMoreData should return the same data as they did when
* SetBookmark was called earlier.
*
* The embedder may return 'false' to indicate it cannot provide this
* functionality.
*/
virtual bool SetBookmark();
/**
* V8 calls this to return to a previously set bookmark.
*/
virtual void ResetToBookmark();
};
......
......@@ -1527,6 +1527,12 @@ ScriptCompiler::CachedData::~CachedData() {
}
bool ScriptCompiler::ExternalSourceStream::SetBookmark() { return false; }
void ScriptCompiler::ExternalSourceStream::ResetToBookmark() { UNREACHABLE(); }
ScriptCompiler::StreamedSource::StreamedSource(ExternalSourceStream* stream,
Encoding encoding)
: impl_(new i::StreamedSource(stream, encoding)) {}
......
......@@ -356,10 +356,7 @@ size_t ExternalStreamingStream::FillBuffer(size_t position) {
// chunk. This will only happen when the chunk was really small. We
// don't handle the case where a UTF-8 character is split over several
// chunks; in that case V8 won't crash, but it will be a parse error.
delete[] current_data_;
current_data_ = NULL;
current_data_length_ = 0;
current_data_offset_ = 0;
FlushCurrent();
continue; // Request a new chunk.
}
}
......@@ -383,15 +380,76 @@ size_t ExternalStreamingStream::FillBuffer(size_t position) {
// Did we use all the data in the data chunk?
if (current_data_offset_ == current_data_length_) {
delete[] current_data_;
current_data_ = NULL;
current_data_length_ = 0;
current_data_offset_ = 0;
FlushCurrent();
}
}
return data_in_buffer;
}
bool ExternalStreamingStream::SetBookmark() {
DCHECK(utf8_split_char_buffer_length_ == 0); // We can't be within a char.
// Bookmarking for this stream is a bit more complex than expected, since
// the stream state is distributed over several places:
// - pos_ (inherited from Utf16CharacterStream)
// - buffer_cursor_ and buffer_end_ (also from Utf16CharacterStream)
// - buffer_ (from BufferedUtf16CharacterStream)
// - current_data_ (+ .._offset_ and .._length) (this class)
//
// The underlying source_stream_ instance likely could re-construct this
// local data for us, but with the given interfaces we have no way of
// accomplishing this. Thus, we'll have to save all data locally.
//
// What gets saved where:
// - pos_ => bookmark_
// - buffer_[buffer_cursor_ .. buffer_end_] => bookmark_buffer_
// - current_data_[.._offset_ .. .._length_] => bookmark_data_
bookmark_ = pos_;
size_t buffer_length = buffer_end_ - buffer_cursor_;
bookmark_buffer_.Dispose();
bookmark_buffer_ = Vector<uint16_t>::New(static_cast<int>(buffer_length));
CopyCharsUnsigned(bookmark_buffer_.start(), buffer_cursor_, buffer_length);
size_t data_length = current_data_length_ - current_data_offset_;
bookmark_data_.Dispose();
bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
data_length);
return source_stream_->SetBookmark();
}
void ExternalStreamingStream::ResetToBookmark() {
source_stream_->ResetToBookmark();
FlushCurrent();
pos_ = bookmark_;
// current_data_ can point to bookmark_data_'s buffer.
current_data_ = bookmark_data_.start();
current_data_offset_ = 0;
current_data_length_ = bookmark_data_.length();
// bookmark_buffer_ needs to be copied to buffer_.
CopyCharsUnsigned(buffer_, bookmark_buffer_.begin(),
bookmark_buffer_.length());
buffer_cursor_ = buffer_;
buffer_end_ = buffer_ + bookmark_buffer_.length();
}
void ExternalStreamingStream::FlushCurrent() {
delete[] current_data_;
current_data_ = NULL;
current_data_length_ = 0;
current_data_offset_ = 0;
}
void ExternalStreamingStream::HandleUtf8SplitCharacters(
size_t* data_in_buffer) {
// Note the following property of UTF-8 which makes this function possible:
......
......@@ -92,9 +92,14 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
current_data_(NULL),
current_data_offset_(0),
current_data_length_(0),
utf8_split_char_buffer_length_(0) {}
utf8_split_char_buffer_length_(0),
bookmark_(0) {}
virtual ~ExternalStreamingStream() { delete[] current_data_; }
virtual ~ExternalStreamingStream() {
delete[] current_data_;
bookmark_buffer_.Dispose();
bookmark_data_.Dispose();
}
size_t BufferSeekForward(size_t delta) override {
// We never need to seek forward when streaming scripts. We only seek
......@@ -107,8 +112,12 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
size_t FillBuffer(size_t position) override;
virtual bool SetBookmark() override;
virtual void ResetToBookmark() override;
private:
void HandleUtf8SplitCharacters(size_t* data_in_buffer);
void FlushCurrent();
ScriptCompiler::ExternalSourceStream* source_stream_;
v8::ScriptCompiler::StreamedSource::Encoding encoding_;
......@@ -118,6 +127,12 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
// For converting UTF-8 characters which are split across two data chunks.
uint8_t utf8_split_char_buffer_[4];
size_t utf8_split_char_buffer_length_;
// Bookmark support. See comments in ExternalStreamingStream::SetBookmark
// for additional details.
size_t bookmark_;
Vector<uint16_t> bookmark_buffer_;
Vector<uint8_t> bookmark_data_;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment