Commit 05a00a93 authored by vogelheim's avatar vogelheim Committed by Commit bot

Simplify Scanner bookmarking.

- Eliminates *all* copies in the process.
- Moves (nearly) all functionality into Scanner::BookmarkScope.
- Significant code reduction.

[Needs to be rebased once crrev.com/2347883002 lands. All changes in *parser* are from that CL.]

R=marja@chromium.org
BUG=v8:4947

Review-Url: https://codereview.chromium.org/2341323002
Cr-Commit-Position: refs/heads/master@{#39554}
parent b88df1c9
...@@ -3904,7 +3904,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( ...@@ -3904,7 +3904,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
} }
if (result == kLazyParsingAborted) { if (result == kLazyParsingAborted) {
bookmark.Reset(); bookmark.Apply();
// Trigger eager (re-)parsing, just below this block. // Trigger eager (re-)parsing, just below this block.
is_lazily_parsed = false; is_lazily_parsed = false;
......
...@@ -3043,7 +3043,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -3043,7 +3043,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
function_state.materialized_literal_count(); function_state.materialized_literal_count();
if (result == kLazyParsingAborted) { if (result == kLazyParsingAborted) {
bookmark.Reset(); bookmark.Apply();
// Trigger eager (re-)parsing, just below this block. // Trigger eager (re-)parsing, just below this block.
is_lazily_parsed = false; is_lazily_parsed = false;
......
...@@ -26,21 +26,60 @@ Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const { ...@@ -26,21 +26,60 @@ Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const {
return isolate->factory()->InternalizeTwoByteString(two_byte_literal()); return isolate->factory()->InternalizeTwoByteString(two_byte_literal());
} }
// ----------------------------------------------------------------------------
// Scanner::BookmarkScope
const size_t Scanner::BookmarkScope::kBookmarkAtFirstPos =
std::numeric_limits<size_t>::max() - 2;
const size_t Scanner::BookmarkScope::kNoBookmark =
std::numeric_limits<size_t>::max() - 1;
const size_t Scanner::BookmarkScope::kBookmarkWasApplied =
std::numeric_limits<size_t>::max();
void Scanner::BookmarkScope::Set() {
DCHECK_EQ(bookmark_, kNoBookmark);
DCHECK_EQ(scanner_->next_next_.token, Token::UNINITIALIZED);
// The first token is a bit special, since current_ will still be
// uninitialized. In this case, store kBookmarkAtFirstPos and special-case it
// when
// applying the bookmark.
DCHECK_IMPLIES(
scanner_->current_.token == Token::UNINITIALIZED,
scanner_->current_.location.beg_pos == scanner_->next_.location.beg_pos);
bookmark_ = (scanner_->current_.token == Token::UNINITIALIZED)
? kBookmarkAtFirstPos
: scanner_->location().beg_pos;
}
void Scanner::BookmarkScope::Apply() {
DCHECK(HasBeenSet()); // Caller hasn't called SetBookmark.
if (bookmark_ == kBookmarkAtFirstPos) {
scanner_->SeekNext(0);
} else {
scanner_->SeekNext(bookmark_);
scanner_->Next();
DCHECK_EQ(scanner_->location().beg_pos, bookmark_);
}
bookmark_ = kBookmarkWasApplied;
}
bool Scanner::BookmarkScope::HasBeenSet() {
return bookmark_ != kNoBookmark && bookmark_ != kBookmarkWasApplied;
}
bool Scanner::BookmarkScope::HasBeenApplied() {
return bookmark_ == kBookmarkWasApplied;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scanner // Scanner
Scanner::Scanner(UnicodeCache* unicode_cache) Scanner::Scanner(UnicodeCache* unicode_cache)
: unicode_cache_(unicode_cache), : unicode_cache_(unicode_cache),
bookmark_c0_(kNoBookmark),
bookmark_position_(0),
octal_pos_(Location::invalid()), octal_pos_(Location::invalid()),
decimal_with_leading_zero_pos_(Location::invalid()), decimal_with_leading_zero_pos_(Location::invalid()),
found_html_comment_(false) { found_html_comment_(false) {
bookmark_current_.literal_chars = &bookmark_current_literal_;
bookmark_current_.raw_literal_chars = &bookmark_current_raw_literal_;
bookmark_next_.literal_chars = &bookmark_next_literal_;
bookmark_next_.raw_literal_chars = &bookmark_next_raw_literal_;
} }
...@@ -1581,56 +1620,24 @@ int Scanner::FindSymbol(DuplicateFinder* finder, int value) { ...@@ -1581,56 +1620,24 @@ int Scanner::FindSymbol(DuplicateFinder* finder, int value) {
return finder->AddTwoByteSymbol(literal_two_byte_string(), value); return finder->AddTwoByteSymbol(literal_two_byte_string(), value);
} }
void Scanner::SetBookmark() { void Scanner::SeekNext(size_t position) {
DCHECK_EQ(bookmark_c0_, kNoBookmark); // Use with care: This cleanly resets most, but not all scanner state.
DCHECK_EQ(next_next_.token, Token::UNINITIALIZED); // TODO(vogelheim): Fix this, or at least DCHECK the relevant conditions.
bookmark_c0_ = c0_;
bookmark_position_ = source_->pos(); // To re-scan from a given character position, we need to:
CopyTokenDesc(&bookmark_current_, &current_); // 1, Reset the current_, next_ and next_next_ tokens
CopyTokenDesc(&bookmark_next_, &next_); // (next_ + next_next_ will be overwrittem by Next(),
} // current_ will remain unchanged, so overwrite it fully.)
current_ = {{0, 0}, nullptr, nullptr, 0, Token::UNINITIALIZED};
next_.token = Token::UNINITIALIZED;
void Scanner::ResetToBookmark() { next_next_.token = Token::UNINITIALIZED;
DCHECK(BookmarkHasBeenSet()); // Caller hasn't called SetBookmark. // 2, reset the source to the desired position,
source_->Seek(position);
source_->Seek(bookmark_position_); // 3, re-scan, by scanning the look-ahead char + 1 token (next_).
c0_ = bookmark_c0_; c0_ = source_->Advance();
CopyToNextTokenDesc(&bookmark_current_); Next();
current_ = next_; DCHECK_EQ(next_.location.beg_pos, position);
CopyToNextTokenDesc(&bookmark_next_);
bookmark_c0_ = kBookmarkWasApplied;
}
bool Scanner::BookmarkHasBeenSet() {
return bookmark_c0_ != kNoBookmark && bookmark_c0_ != kBookmarkWasApplied;
}
bool Scanner::BookmarkHasBeenReset() {
return bookmark_c0_ == kBookmarkWasApplied;
}
void Scanner::DropBookmark() { bookmark_c0_ = kNoBookmark; }
void Scanner::CopyToNextTokenDesc(TokenDesc* from) {
StartLiteral();
StartRawLiteral();
CopyTokenDesc(&next_, from);
if (next_.literal_chars->length() == 0) next_.literal_chars = nullptr;
if (next_.raw_literal_chars->length() == 0) next_.raw_literal_chars = nullptr;
}
void Scanner::CopyTokenDesc(TokenDesc* to, TokenDesc* from) {
DCHECK_NOT_NULL(to);
DCHECK_NOT_NULL(from);
to->token = from->token;
to->location = from->location;
to->literal_chars->CopyFrom(from->literal_chars);
to->raw_literal_chars->CopyFrom(from->raw_literal_chars);
} }
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -154,18 +154,24 @@ class Scanner { ...@@ -154,18 +154,24 @@ class Scanner {
// Scoped helper for a re-settable bookmark. // Scoped helper for a re-settable bookmark.
class BookmarkScope { class BookmarkScope {
public: public:
explicit BookmarkScope(Scanner* scanner) : scanner_(scanner) { explicit BookmarkScope(Scanner* scanner)
: scanner_(scanner), bookmark_(kNoBookmark) {
DCHECK_NOT_NULL(scanner_); DCHECK_NOT_NULL(scanner_);
} }
~BookmarkScope() { scanner_->DropBookmark(); } ~BookmarkScope() {}
void Set() { scanner_->SetBookmark(); } void Set();
void Reset() { scanner_->ResetToBookmark(); } void Apply();
bool HasBeenSet() { return scanner_->BookmarkHasBeenSet(); } bool HasBeenSet();
bool HasBeenReset() { return scanner_->BookmarkHasBeenReset(); } bool HasBeenApplied();
private: private:
static const size_t kNoBookmark;
static const size_t kBookmarkWasApplied;
static const size_t kBookmarkAtFirstPos;
Scanner* scanner_; Scanner* scanner_;
size_t bookmark_;
DISALLOW_COPY_AND_ASSIGN(BookmarkScope); DISALLOW_COPY_AND_ASSIGN(BookmarkScope);
}; };
...@@ -418,23 +424,6 @@ class Scanner { ...@@ -418,23 +424,6 @@ class Scanner {
Handle<String> Internalize(Isolate* isolate) const; Handle<String> Internalize(Isolate* isolate) const;
void CopyFrom(const LiteralBuffer* other) {
if (other == nullptr) {
Reset();
} else {
is_one_byte_ = other->is_one_byte_;
position_ = other->position_;
if (position_ < backing_store_.length()) {
std::copy(other->backing_store_.begin(),
other->backing_store_.begin() + position_,
backing_store_.begin());
} else {
backing_store_.Dispose();
backing_store_ = other->backing_store_.Clone();
}
}
}
private: private:
static const int kInitialCapacity = 16; static const int kInitialCapacity = 16;
static const int kGrowthFactory = 4; static const int kGrowthFactory = 4;
...@@ -528,15 +517,6 @@ class Scanner { ...@@ -528,15 +517,6 @@ class Scanner {
scanner_error_ = MessageTemplate::kNone; scanner_error_ = MessageTemplate::kNone;
} }
// Support BookmarkScope functionality.
void SetBookmark();
void ResetToBookmark();
bool BookmarkHasBeenSet();
bool BookmarkHasBeenReset();
void DropBookmark();
void CopyToNextTokenDesc(TokenDesc* from);
static void CopyTokenDesc(TokenDesc* to, TokenDesc* from);
void ReportScannerError(const Location& location, void ReportScannerError(const Location& location,
MessageTemplate::Template error) { MessageTemplate::Template error) {
if (has_error()) return; if (has_error()) return;
...@@ -550,6 +530,9 @@ class Scanner { ...@@ -550,6 +530,9 @@ class Scanner {
scanner_error_location_ = Location(pos, pos + 1); scanner_error_location_ = Location(pos, pos + 1);
} }
// Seek to the next_ token at the given position.
void SeekNext(size_t position);
// Literal buffer support // Literal buffer support
inline void StartLiteral() { inline void StartLiteral() {
LiteralBuffer* free_buffer = LiteralBuffer* free_buffer =
...@@ -789,38 +772,6 @@ class Scanner { ...@@ -789,38 +772,6 @@ class Scanner {
TokenDesc next_; // desc for next token (one token look-ahead) TokenDesc next_; // desc for next token (one token look-ahead)
TokenDesc next_next_; // desc for the token after next (after PeakAhead()) TokenDesc next_next_; // desc for the token after next (after PeakAhead())
// Variables for Scanner::BookmarkScope and the *Bookmark implementation.
// These variables contain the scanner state when a bookmark is set.
//
// We will use bookmark_c0_ as a 'control' variable, where:
// - bookmark_c0_ >= 0: A bookmark has been set and this contains c0_.
// - bookmark_c0_ == -1: No bookmark has been set.
// - bookmark_c0_ == -2: The bookmark has been applied (ResetToBookmark).
//
// Which state is being bookmarked? The parser state is distributed over
// several variables, roughly like this:
// ... 1234 + 5678 ..... [character stream]
// [current_] [next_] c0_ | [scanner state]
// So when the scanner is logically at the beginning of an expression
// like "1234 + 4567", then:
// - current_ contains "1234"
// - next_ contains "+"
// - c0_ contains ' ' (the space between "+" and "5678",
// - the source_ character stream points to the beginning of "5678".
// To be able to restore this state, we will keep copies of current_, next_,
// and c0_; we'll ask the stream to bookmark itself, and we'll copy the
// contents of current_'s and next_'s literal buffers to bookmark_*_literal_.
static const uc32 kNoBookmark = -2;
static const uc32 kBookmarkWasApplied = -3;
uc32 bookmark_c0_;
size_t bookmark_position_;
TokenDesc bookmark_current_;
TokenDesc bookmark_next_;
LiteralBuffer bookmark_current_literal_;
LiteralBuffer bookmark_current_raw_literal_;
LiteralBuffer bookmark_next_literal_;
LiteralBuffer bookmark_next_raw_literal_;
// Input stream. Must be initialized to an Utf16CharacterStream. // Input stream. Must be initialized to an Utf16CharacterStream.
Utf16CharacterStream* source_; Utf16CharacterStream* source_;
......
...@@ -56,7 +56,7 @@ TEST(Bookmarks) { ...@@ -56,7 +56,7 @@ TEST(Bookmarks) {
DCHECK_EQ(tokens[i], scanner->Next()); DCHECK_EQ(tokens[i], scanner->Next());
} }
bookmark.Reset(); bookmark.Apply();
for (size_t i = bookmark_pos; i < tokens.size(); i++) { for (size_t i = bookmark_pos; i < tokens.size(); i++) {
DCHECK_EQ(tokens[i], scanner->Next()); DCHECK_EQ(tokens[i], scanner->Next());
} }
......
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