LCOV - code coverage report
Current view: top level - src/parsing - scanner.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 571 582 98.1 %
Date: 2017-04-26 Functions: 50 54 92.6 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : // Features shared by parsing and pre-parsing scanners.
       6             : 
       7             : #include "src/parsing/scanner.h"
       8             : 
       9             : #include <stdint.h>
      10             : 
      11             : #include <cmath>
      12             : 
      13             : #include "src/ast/ast-value-factory.h"
      14             : #include "src/char-predicates-inl.h"
      15             : #include "src/conversions-inl.h"
      16             : #include "src/list-inl.h"
      17             : #include "src/parsing/duplicate-finder.h"  // For Scanner::FindSymbol
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : class Scanner::ErrorState {
      23             :  public:
      24             :   ErrorState(MessageTemplate::Template* message_stack,
      25             :              Scanner::Location* location_stack)
      26             :       : message_stack_(message_stack),
      27             :         old_message_(*message_stack),
      28             :         location_stack_(location_stack),
      29      337302 :         old_location_(*location_stack) {
      30      337302 :     *message_stack_ = MessageTemplate::kNone;
      31      337302 :     *location_stack_ = Location::invalid();
      32             :   }
      33             : 
      34             :   ~ErrorState() {
      35      337302 :     *message_stack_ = old_message_;
      36      337302 :     *location_stack_ = old_location_;
      37             :   }
      38             : 
      39             :   void MoveErrorTo(TokenDesc* dest) {
      40       63496 :     if (*message_stack_ == MessageTemplate::kNone) {
      41             :       return;
      42             :     }
      43       27692 :     if (dest->invalid_template_escape_message == MessageTemplate::kNone) {
      44       27692 :       dest->invalid_template_escape_message = *message_stack_;
      45       27692 :       dest->invalid_template_escape_location = *location_stack_;
      46             :     }
      47       27692 :     *message_stack_ = MessageTemplate::kNone;
      48       27692 :     *location_stack_ = Location::invalid();
      49             :   }
      50             : 
      51             :  private:
      52             :   MessageTemplate::Template* const message_stack_;
      53             :   MessageTemplate::Template const old_message_;
      54             :   Scanner::Location* const location_stack_;
      55             :   Scanner::Location const old_location_;
      56             : };
      57             : 
      58             : // ----------------------------------------------------------------------------
      59             : // Scanner::LiteralBuffer
      60             : 
      61        2439 : Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const {
      62        2439 :   if (is_one_byte()) {
      63        2439 :     return isolate->factory()->InternalizeOneByteString(one_byte_literal());
      64             :   }
      65           0 :   return isolate->factory()->InternalizeTwoByteString(two_byte_literal());
      66             : }
      67             : 
      68           0 : int Scanner::LiteralBuffer::NewCapacity(int min_capacity) {
      69     4621452 :   int capacity = Max(min_capacity, backing_store_.length());
      70     4621460 :   int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
      71           0 :   return new_capacity;
      72             : }
      73             : 
      74     4621452 : void Scanner::LiteralBuffer::ExpandBuffer() {
      75             :   Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
      76     4621463 :   MemCopy(new_store.start(), backing_store_.start(), position_);
      77             :   backing_store_.Dispose();
      78     4621463 :   backing_store_ = new_store;
      79     4621463 : }
      80             : 
      81       67037 : void Scanner::LiteralBuffer::ConvertToTwoByte() {
      82             :   DCHECK(is_one_byte_);
      83             :   Vector<byte> new_store;
      84       67037 :   int new_content_size = position_ * kUC16Size;
      85      134074 :   if (new_content_size >= backing_store_.length()) {
      86             :     // Ensure room for all currently read code units as UC16 as well
      87             :     // as the code unit about to be stored.
      88             :     new_store = Vector<byte>::New(NewCapacity(new_content_size));
      89             :   } else {
      90       67029 :     new_store = backing_store_;
      91             :   }
      92             :   uint8_t* src = backing_store_.start();
      93             :   uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.start());
      94      142596 :   for (int i = position_ - 1; i >= 0; i--) {
      95       75559 :     dst[i] = src[i];
      96             :   }
      97       67037 :   if (new_store.start() != backing_store_.start()) {
      98             :     backing_store_.Dispose();
      99           8 :     backing_store_ = new_store;
     100             :   }
     101       67037 :   position_ = new_content_size;
     102       67037 :   is_one_byte_ = false;
     103       67037 : }
     104             : 
     105     1457068 : void Scanner::LiteralBuffer::AddCharSlow(uc32 code_unit) {
     106     2930082 :   if (position_ >= backing_store_.length()) ExpandBuffer();
     107     1457068 :   if (is_one_byte_) {
     108       67037 :     if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
     109           0 :       backing_store_[position_] = static_cast<byte>(code_unit);
     110           0 :       position_ += kOneByteSize;
     111     1457068 :       return;
     112             :     }
     113       67037 :     ConvertToTwoByte();
     114             :   }
     115     1457068 :   if (code_unit <=
     116             :       static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
     117     2898190 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
     118     1449095 :     position_ += kUC16Size;
     119             :   } else {
     120        7973 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
     121       15946 :         unibrow::Utf16::LeadSurrogate(code_unit);
     122        7973 :     position_ += kUC16Size;
     123        7973 :     if (position_ >= backing_store_.length()) ExpandBuffer();
     124        7973 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
     125        7973 :         unibrow::Utf16::TrailSurrogate(code_unit);
     126        7973 :     position_ += kUC16Size;
     127             :   }
     128             : }
     129             : 
     130             : // ----------------------------------------------------------------------------
     131             : // Scanner::BookmarkScope
     132             : 
     133             : const size_t Scanner::BookmarkScope::kBookmarkAtFirstPos =
     134             :     std::numeric_limits<size_t>::max() - 2;
     135             : const size_t Scanner::BookmarkScope::kNoBookmark =
     136             :     std::numeric_limits<size_t>::max() - 1;
     137             : const size_t Scanner::BookmarkScope::kBookmarkWasApplied =
     138             :     std::numeric_limits<size_t>::max();
     139             : 
     140     1434328 : void Scanner::BookmarkScope::Set() {
     141             :   DCHECK_EQ(bookmark_, kNoBookmark);
     142             :   DCHECK_EQ(scanner_->next_next_.token, Token::UNINITIALIZED);
     143             : 
     144             :   // The first token is a bit special, since current_ will still be
     145             :   // uninitialized. In this case, store kBookmarkAtFirstPos and special-case it
     146             :   // when
     147             :   // applying the bookmark.
     148             :   DCHECK_IMPLIES(
     149             :       scanner_->current_.token == Token::UNINITIALIZED,
     150             :       scanner_->current_.location.beg_pos == scanner_->next_.location.beg_pos);
     151     1434328 :   bookmark_ = (scanner_->current_.token == Token::UNINITIALIZED)
     152             :                   ? kBookmarkAtFirstPos
     153     1434328 :                   : scanner_->location().beg_pos;
     154     1434328 : }
     155             : 
     156         178 : void Scanner::BookmarkScope::Apply() {
     157             :   DCHECK(HasBeenSet());  // Caller hasn't called SetBookmark.
     158         178 :   if (bookmark_ == kBookmarkAtFirstPos) {
     159           7 :     scanner_->SeekNext(0);
     160             :   } else {
     161         171 :     scanner_->SeekNext(bookmark_);
     162         171 :     scanner_->Next();
     163             :     DCHECK_EQ(scanner_->location().beg_pos, static_cast<int>(bookmark_));
     164             :   }
     165         178 :   bookmark_ = kBookmarkWasApplied;
     166         178 : }
     167             : 
     168           0 : bool Scanner::BookmarkScope::HasBeenSet() {
     169           0 :   return bookmark_ != kNoBookmark && bookmark_ != kBookmarkWasApplied;
     170             : }
     171             : 
     172           0 : bool Scanner::BookmarkScope::HasBeenApplied() {
     173           0 :   return bookmark_ == kBookmarkWasApplied;
     174             : }
     175             : 
     176             : // ----------------------------------------------------------------------------
     177             : // Scanner
     178             : 
     179     4054678 : Scanner::Scanner(UnicodeCache* unicode_cache)
     180             :     : unicode_cache_(unicode_cache),
     181             :       octal_pos_(Location::invalid()),
     182             :       octal_message_(MessageTemplate::kNone),
     183    12164034 :       found_html_comment_(false) {}
     184             : 
     185     4050466 : void Scanner::Initialize(Utf16CharacterStream* source) {
     186             :   DCHECK_NOT_NULL(source);
     187     4050466 :   source_ = source;
     188             :   // Need to capture identifiers in order to recognize "get" and "set"
     189             :   // in object literals.
     190     4050466 :   Init();
     191             :   // Skip initial whitespace allowing HTML comment ends just like
     192             :   // after a newline and scan first token.
     193     4050467 :   has_line_terminator_before_next_ = true;
     194     4050467 :   SkipWhiteSpace();
     195     4050472 :   Scan();
     196     4050469 : }
     197             : 
     198             : template <bool capture_raw, bool unicode>
     199       70658 : uc32 Scanner::ScanHexNumber(int expected_length) {
     200             :   DCHECK(expected_length <= 4);  // prevent overflow
     201             : 
     202       70658 :   int begin = source_pos() - 2;
     203             :   uc32 x = 0;
     204      308934 :   for (int i = 0; i < expected_length; i++) {
     205      252189 :     int d = HexValue(c0_);
     206      252189 :     if (d < 0) {
     207             :       ReportScannerError(Location(begin, begin + expected_length + 2),
     208             :                          unicode
     209             :                              ? MessageTemplate::kInvalidUnicodeEscapeSequence
     210       13913 :                              : MessageTemplate::kInvalidHexEscapeSequence);
     211             :       return -1;
     212             :     }
     213      238276 :     x = x * 16 + d;
     214      238276 :     Advance<capture_raw>();
     215             :   }
     216             : 
     217             :   return x;
     218             : }
     219             : 
     220             : template <bool capture_raw>
     221       38536 : uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value, int beg_pos) {
     222             :   uc32 x = 0;
     223       35784 :   int d = HexValue(c0_);
     224       35784 :   if (d < 0) return -1;
     225             : 
     226      139562 :   while (d >= 0) {
     227      113554 :     x = x * 16 + d;
     228      113554 :     if (x > max_value) {
     229             :       ReportScannerError(Location(beg_pos, source_pos() + 1),
     230             :                          MessageTemplate::kUndefinedUnicodeCodePoint);
     231             :       return -1;
     232             :     }
     233      110802 :     Advance<capture_raw>();
     234      110802 :     d = HexValue(c0_);
     235             :   }
     236             : 
     237             :   return x;
     238             : }
     239             : 
     240             : 
     241             : // Ensure that tokens can be stored in a byte.
     242             : STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
     243             : 
     244             : // Table of one-character tokens, by character (0x00..0x7f only).
     245             : static const byte one_char_tokens[] = {
     246             :   Token::ILLEGAL,
     247             :   Token::ILLEGAL,
     248             :   Token::ILLEGAL,
     249             :   Token::ILLEGAL,
     250             :   Token::ILLEGAL,
     251             :   Token::ILLEGAL,
     252             :   Token::ILLEGAL,
     253             :   Token::ILLEGAL,
     254             :   Token::ILLEGAL,
     255             :   Token::ILLEGAL,
     256             :   Token::ILLEGAL,
     257             :   Token::ILLEGAL,
     258             :   Token::ILLEGAL,
     259             :   Token::ILLEGAL,
     260             :   Token::ILLEGAL,
     261             :   Token::ILLEGAL,
     262             :   Token::ILLEGAL,
     263             :   Token::ILLEGAL,
     264             :   Token::ILLEGAL,
     265             :   Token::ILLEGAL,
     266             :   Token::ILLEGAL,
     267             :   Token::ILLEGAL,
     268             :   Token::ILLEGAL,
     269             :   Token::ILLEGAL,
     270             :   Token::ILLEGAL,
     271             :   Token::ILLEGAL,
     272             :   Token::ILLEGAL,
     273             :   Token::ILLEGAL,
     274             :   Token::ILLEGAL,
     275             :   Token::ILLEGAL,
     276             :   Token::ILLEGAL,
     277             :   Token::ILLEGAL,
     278             :   Token::ILLEGAL,
     279             :   Token::ILLEGAL,
     280             :   Token::ILLEGAL,
     281             :   Token::ILLEGAL,
     282             :   Token::ILLEGAL,
     283             :   Token::ILLEGAL,
     284             :   Token::ILLEGAL,
     285             :   Token::ILLEGAL,
     286             :   Token::LPAREN,       // 0x28
     287             :   Token::RPAREN,       // 0x29
     288             :   Token::ILLEGAL,
     289             :   Token::ILLEGAL,
     290             :   Token::COMMA,        // 0x2c
     291             :   Token::ILLEGAL,
     292             :   Token::ILLEGAL,
     293             :   Token::ILLEGAL,
     294             :   Token::ILLEGAL,
     295             :   Token::ILLEGAL,
     296             :   Token::ILLEGAL,
     297             :   Token::ILLEGAL,
     298             :   Token::ILLEGAL,
     299             :   Token::ILLEGAL,
     300             :   Token::ILLEGAL,
     301             :   Token::ILLEGAL,
     302             :   Token::ILLEGAL,
     303             :   Token::ILLEGAL,
     304             :   Token::COLON,        // 0x3a
     305             :   Token::SEMICOLON,    // 0x3b
     306             :   Token::ILLEGAL,
     307             :   Token::ILLEGAL,
     308             :   Token::ILLEGAL,
     309             :   Token::CONDITIONAL,  // 0x3f
     310             :   Token::ILLEGAL,
     311             :   Token::ILLEGAL,
     312             :   Token::ILLEGAL,
     313             :   Token::ILLEGAL,
     314             :   Token::ILLEGAL,
     315             :   Token::ILLEGAL,
     316             :   Token::ILLEGAL,
     317             :   Token::ILLEGAL,
     318             :   Token::ILLEGAL,
     319             :   Token::ILLEGAL,
     320             :   Token::ILLEGAL,
     321             :   Token::ILLEGAL,
     322             :   Token::ILLEGAL,
     323             :   Token::ILLEGAL,
     324             :   Token::ILLEGAL,
     325             :   Token::ILLEGAL,
     326             :   Token::ILLEGAL,
     327             :   Token::ILLEGAL,
     328             :   Token::ILLEGAL,
     329             :   Token::ILLEGAL,
     330             :   Token::ILLEGAL,
     331             :   Token::ILLEGAL,
     332             :   Token::ILLEGAL,
     333             :   Token::ILLEGAL,
     334             :   Token::ILLEGAL,
     335             :   Token::ILLEGAL,
     336             :   Token::ILLEGAL,
     337             :   Token::LBRACK,     // 0x5b
     338             :   Token::ILLEGAL,
     339             :   Token::RBRACK,     // 0x5d
     340             :   Token::ILLEGAL,
     341             :   Token::ILLEGAL,
     342             :   Token::ILLEGAL,
     343             :   Token::ILLEGAL,
     344             :   Token::ILLEGAL,
     345             :   Token::ILLEGAL,
     346             :   Token::ILLEGAL,
     347             :   Token::ILLEGAL,
     348             :   Token::ILLEGAL,
     349             :   Token::ILLEGAL,
     350             :   Token::ILLEGAL,
     351             :   Token::ILLEGAL,
     352             :   Token::ILLEGAL,
     353             :   Token::ILLEGAL,
     354             :   Token::ILLEGAL,
     355             :   Token::ILLEGAL,
     356             :   Token::ILLEGAL,
     357             :   Token::ILLEGAL,
     358             :   Token::ILLEGAL,
     359             :   Token::ILLEGAL,
     360             :   Token::ILLEGAL,
     361             :   Token::ILLEGAL,
     362             :   Token::ILLEGAL,
     363             :   Token::ILLEGAL,
     364             :   Token::ILLEGAL,
     365             :   Token::ILLEGAL,
     366             :   Token::ILLEGAL,
     367             :   Token::ILLEGAL,
     368             :   Token::ILLEGAL,
     369             :   Token::LBRACE,       // 0x7b
     370             :   Token::ILLEGAL,
     371             :   Token::RBRACE,       // 0x7d
     372             :   Token::BIT_NOT,      // 0x7e
     373             :   Token::ILLEGAL
     374             : };
     375             : 
     376             : 
     377   892451859 : Token::Value Scanner::Next() {
     378   691898255 :   if (next_.token == Token::EOS) {
     379        3578 :     next_.location.beg_pos = current_.location.beg_pos;
     380        3578 :     next_.location.end_pos = current_.location.end_pos;
     381             :   }
     382   691898255 :   current_ = next_;
     383   691898255 :   if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
     384   120180694 :     next_ = next_next_;
     385   120180694 :     next_next_.token = Token::UNINITIALIZED;
     386   120180694 :     next_next_.contextual_token = Token::UNINITIALIZED;
     387   120180694 :     has_line_terminator_before_next_ = has_line_terminator_after_next_;
     388   120180694 :     return current_.token;
     389             :   }
     390   571717561 :   has_line_terminator_before_next_ = false;
     391   571717561 :   has_multiline_comment_before_next_ = false;
     392   571717561 :   if (static_cast<unsigned>(c0_) <= 0x7f) {
     393   568414198 :     Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
     394   568414198 :     if (token != Token::ILLEGAL) {
     395             :       int pos = source_pos();
     396   200553604 :       next_.token = token;
     397   200553604 :       next_.contextual_token = Token::UNINITIALIZED;
     398   200553604 :       next_.location.beg_pos = pos;
     399   200553604 :       next_.location.end_pos = pos + 1;
     400   200553604 :       next_.literal_chars = nullptr;
     401   200553604 :       next_.raw_literal_chars = nullptr;
     402   200553604 :       next_.invalid_template_escape_message = MessageTemplate::kNone;
     403   200553604 :       Advance();
     404   200554055 :       return current_.token;
     405             :     }
     406             :   }
     407   371163957 :   Scan();
     408   371169893 :   return current_.token;
     409             : }
     410             : 
     411             : 
     412   120498098 : Token::Value Scanner::PeekAhead() {
     413             :   DCHECK(next_.token != Token::DIV);
     414             :   DCHECK(next_.token != Token::ASSIGN_DIV);
     415             : 
     416   120498098 :   if (next_next_.token != Token::UNINITIALIZED) {
     417             :     return next_next_.token;
     418             :   }
     419   120181089 :   TokenDesc prev = current_;
     420             :   bool has_line_terminator_before_next =
     421   120181089 :       has_line_terminator_before_next_ || has_multiline_comment_before_next_;
     422   120181089 :   Next();
     423             :   has_line_terminator_after_next_ =
     424   120181312 :       has_line_terminator_before_next_ || has_multiline_comment_before_next_;
     425   120181312 :   has_line_terminator_before_next_ = has_line_terminator_before_next;
     426   120181312 :   Token::Value ret = next_.token;
     427   120181312 :   next_next_ = next_;
     428   120181312 :   next_ = current_;
     429   120181312 :   current_ = prev;
     430   120181312 :   return ret;
     431             : }
     432             : 
     433             : 
     434             : // TODO(yangguo): check whether this is actually necessary.
     435             : static inline bool IsLittleEndianByteOrderMark(uc32 c) {
     436             :   // The Unicode value U+FFFE is guaranteed never to be assigned as a
     437             :   // Unicode character; this implies that in a Unicode context the
     438             :   // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
     439             :   // character expressed in little-endian byte order (since it could
     440             :   // not be a U+FFFE character expressed in big-endian byte
     441             :   // order). Nevertheless, we check for it to be compatible with
     442             :   // Spidermonkey.
     443             :   return c == 0xFFFE;
     444             : }
     445             : 
     446     8122418 : bool Scanner::SkipWhiteSpace() {
     447             :   int start_position = source_pos();
     448             : 
     449             :   while (true) {
     450             :     while (true) {
     451             :       // Don't skip behind the end of input.
     452     8141838 :       if (c0_ == kEndOfInput) break;
     453             : 
     454             :       // Advance as long as character is a WhiteSpace or LineTerminator.
     455             :       // Remember if the latter is the case.
     456    16265037 :       if (unicode_cache_->IsLineTerminator(c0_)) {
     457     4022573 :         has_line_terminator_before_next_ = true;
     458    12268467 :       } else if (!unicode_cache_->IsWhiteSpace(c0_) &&
     459     4048573 :                  !IsLittleEndianByteOrderMark(c0_)) {
     460             :         break;
     461             :       }
     462     4083946 :       Advance();
     463             :     }
     464             : 
     465             :     // If there is an HTML comment end '-->' at the beginning of a
     466             :     // line (with only whitespace in front of it), we treat the rest
     467             :     // of the line as a comment. This is in line with the way
     468             :     // SpiderMonkey handles it.
     469     4057895 :     if (c0_ != '-' || !has_line_terminator_before_next_) break;
     470             : 
     471        6792 :     Advance();
     472        6792 :     if (c0_ != '-') {
     473             :       PushBack('-');  // undo Advance()
     474             :       break;
     475             :     }
     476             : 
     477         126 :     Advance();
     478         126 :     if (c0_ != '>') {
     479             :       PushBack2('-', '-');  // undo 2x Advance();
     480             :       break;
     481             :     }
     482             : 
     483             :     // Treat the rest of the line as a comment.
     484          53 :     SkipSingleLineComment();
     485             :   }
     486             : 
     487             :   // Return whether or not we skipped any characters.
     488     8141843 :   return source_pos() != start_position;
     489             : }
     490             : 
     491     6777900 : Token::Value Scanner::SkipSingleLineComment() {
     492     6777900 :   Advance();
     493             : 
     494             :   // The line terminator at the end of the line is not considered
     495             :   // to be part of the single-line comment; it is recognized
     496             :   // separately by the lexical grammar and becomes part of the
     497             :   // stream of input elements for the syntactic grammar (see
     498             :   // ECMA-262, section 7.4).
     499   701804732 :   while (c0_ != kEndOfInput && !unicode_cache_->IsLineTerminator(c0_)) {
     500   340735687 :     Advance();
     501             :   }
     502             : 
     503     6777900 :   return Token::WHITESPACE;
     504             : }
     505             : 
     506             : 
     507        2566 : Token::Value Scanner::SkipSourceURLComment() {
     508        2566 :   TryToParseSourceURLComment();
     509        7044 :   while (c0_ != kEndOfInput && !unicode_cache_->IsLineTerminator(c0_)) {
     510         756 :     Advance();
     511             :   }
     512             : 
     513        2566 :   return Token::WHITESPACE;
     514             : }
     515             : 
     516             : 
     517        2566 : void Scanner::TryToParseSourceURLComment() {
     518             :   // Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
     519             :   // function will just return if it cannot parse a magic comment.
     520        5207 :   if (c0_ == kEndOfInput || !unicode_cache_->IsWhiteSpace(c0_)) return;
     521        2550 :   Advance();
     522             :   LiteralBuffer name;
     523       79725 :   while (c0_ != kEndOfInput &&
     524       53126 :          !unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) && c0_ != '=') {
     525       24025 :     name.AddChar(c0_);
     526       24025 :     Advance();
     527             :   }
     528        2550 :   if (!name.is_one_byte()) return;
     529             :   Vector<const uint8_t> name_literal = name.one_byte_literal();
     530             :   LiteralBuffer* value;
     531        2550 :   if (name_literal == STATIC_CHAR_VECTOR("sourceURL")) {
     532        2342 :     value = &source_url_;
     533         208 :   } else if (name_literal == STATIC_CHAR_VECTOR("sourceMappingURL")) {
     534         169 :     value = &source_mapping_url_;
     535             :   } else {
     536             :     return;
     537             :   }
     538        2511 :   if (c0_ != '=')
     539             :     return;
     540        2499 :   Advance();
     541             :   value->Reset();
     542        5046 :   while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) {
     543          24 :     Advance();
     544             :   }
     545       61211 :   while (c0_ != kEndOfInput && !unicode_cache_->IsLineTerminator(c0_)) {
     546             :     // Disallowed characters.
     547       29235 :     if (c0_ == '"' || c0_ == '\'') {
     548             :       value->Reset();
     549             :       return;
     550             :     }
     551       58422 :     if (unicode_cache_->IsWhiteSpace(c0_)) {
     552             :       break;
     553             :     }
     554       29161 :     value->AddChar(c0_);
     555       29161 :     Advance();
     556             :   }
     557             :   // Allow whitespace at the end.
     558        2951 :   while (c0_ != kEndOfInput && !unicode_cache_->IsLineTerminator(c0_)) {
     559         172 :     if (!unicode_cache_->IsWhiteSpace(c0_)) {
     560             :       value->Reset();
     561             :       break;
     562             :     }
     563          62 :     Advance();
     564             :   }
     565             : }
     566             : 
     567             : 
     568      549650 : Token::Value Scanner::SkipMultiLineComment() {
     569             :   DCHECK(c0_ == '*');
     570      549650 :   Advance();
     571             : 
     572     8322745 :   while (c0_ != kEndOfInput) {
     573             :     uc32 ch = c0_;
     574     7773093 :     Advance();
     575    15546184 :     if (c0_ != kEndOfInput && unicode_cache_->IsLineTerminator(ch)) {
     576             :       // Following ECMA-262, section 7.4, a comment containing
     577             :       // a newline will make the comment count as a line-terminator.
     578      147354 :       has_multiline_comment_before_next_ = true;
     579             :     }
     580             :     // If we have reached the end of the multi-line comment, we
     581             :     // consume the '/' and insert a whitespace. This way all
     582             :     // multi-line comments are treated as whitespace.
     583     7773093 :     if (ch == '*' && c0_ == '/') {
     584      549648 :       c0_ = ' ';
     585      549648 :       return Token::WHITESPACE;
     586             :     }
     587             :   }
     588             : 
     589             :   // Unterminated multi-line comment.
     590             :   return Token::ILLEGAL;
     591             : }
     592             : 
     593         130 : Token::Value Scanner::ScanHtmlComment() {
     594             :   // Check for <!-- comments.
     595             :   DCHECK(c0_ == '!');
     596          84 :   Advance();
     597          84 :   if (c0_ != '-') {
     598             :     PushBack('!');  // undo Advance()
     599          23 :     return Token::LT;
     600             :   }
     601             : 
     602          61 :   Advance();
     603          61 :   if (c0_ != '-') {
     604             :     PushBack2('-', '!');  // undo 2x Advance()
     605             :     return Token::LT;
     606             :   }
     607             : 
     608          38 :   found_html_comment_ = true;
     609          38 :   return SkipSingleLineComment();
     610             : }
     611             : 
     612  1527867417 : void Scanner::Scan() {
     613   375223718 :   next_.literal_chars = NULL;
     614   375223718 :   next_.raw_literal_chars = NULL;
     615   375223718 :   next_.invalid_template_escape_message = MessageTemplate::kNone;
     616             :   Token::Value token;
     617   770641234 :   do {
     618             :     // Remember the position of the next token
     619   770644529 :     next_.location.beg_pos = source_pos();
     620             : 
     621   770644529 :     switch (c0_) {
     622             :       case ' ':
     623             :       case '\t':
     624   310691411 :         Advance();
     625             :         token = Token::WHITESPACE;
     626   310691404 :         break;
     627             : 
     628             :       case '\n':
     629    77392529 :         Advance();
     630    77392523 :         has_line_terminator_before_next_ = true;
     631             :         token = Token::WHITESPACE;
     632    77392523 :         break;
     633             : 
     634             :       case '"':
     635             :       case '\'':
     636    14313735 :         token = ScanString();
     637    14313743 :         break;
     638             : 
     639             :       case '<':
     640             :         // < <= << <<= <!--
     641     1684971 :         Advance();
     642     1684971 :         if (c0_ == '=') {
     643             :           token = Select(Token::LTE);
     644     1548790 :         } else if (c0_ == '<') {
     645             :           token = Select('=', Token::ASSIGN_SHL, Token::SHL);
     646     1195723 :         } else if (c0_ == '!') {
     647          84 :           token = ScanHtmlComment();
     648             :         } else {
     649             :           token = Token::LT;
     650             :         }
     651             :         break;
     652             : 
     653             :       case '>':
     654             :         // > >= >> >>= >>> >>>=
     655     1243583 :         Advance();
     656     1243583 :         if (c0_ == '=') {
     657             :           token = Select(Token::GTE);
     658     1064796 :         } else if (c0_ == '>') {
     659             :           // >> >>= >>> >>>=
     660      718290 :           Advance();
     661      718290 :           if (c0_ == '=') {
     662             :             token = Select(Token::ASSIGN_SAR);
     663      710434 :           } else if (c0_ == '>') {
     664             :             token = Select('=', Token::ASSIGN_SHR, Token::SHR);
     665             :           } else {
     666             :             token = Token::SAR;
     667             :           }
     668             :         } else {
     669             :           token = Token::GT;
     670             :         }
     671             :         break;
     672             : 
     673             :       case '=':
     674             :         // = == === =>
     675    33778745 :         Advance();
     676    33778752 :         if (c0_ == '=') {
     677             :           token = Select('=', Token::EQ_STRICT, Token::EQ);
     678    30376808 :         } else if (c0_ == '>') {
     679             :           token = Select(Token::ARROW);
     680             :         } else {
     681             :           token = Token::ASSIGN;
     682             :         }
     683             :         break;
     684             : 
     685             :       case '!':
     686             :         // ! != !==
     687     3028528 :         Advance();
     688     3028528 :         if (c0_ == '=') {
     689             :           token = Select('=', Token::NE_STRICT, Token::NE);
     690             :         } else {
     691             :           token = Token::NOT;
     692             :         }
     693             :         break;
     694             : 
     695             :       case '+':
     696             :         // + ++ +=
     697     7043129 :         Advance();
     698     7043129 :         if (c0_ == '+') {
     699             :           token = Select(Token::INC);
     700     5254423 :         } else if (c0_ == '=') {
     701             :           token = Select(Token::ASSIGN_ADD);
     702             :         } else {
     703             :           token = Token::ADD;
     704             :         }
     705             :         break;
     706             : 
     707             :       case '-':
     708             :         // - -- --> -=
     709     1379608 :         Advance();
     710     1379608 :         if (c0_ == '-') {
     711       80969 :           Advance();
     712       81185 :           if (c0_ == '>' && HasAnyLineTerminatorBeforeNext()) {
     713             :             // For compatibility with SpiderMonkey, we skip lines that
     714             :             // start with an HTML comment end '-->'.
     715         142 :             token = SkipSingleLineComment();
     716             :           } else {
     717             :             token = Token::DEC;
     718             :           }
     719     1298639 :         } else if (c0_ == '=') {
     720             :           token = Select(Token::ASSIGN_SUB);
     721             :         } else {
     722             :           token = Token::SUB;
     723             :         }
     724             :         break;
     725             : 
     726             :       case '*':
     727             :         // * *=
     728      764768 :         Advance();
     729      764768 :         if (c0_ == '*') {
     730             :           token = Select('=', Token::ASSIGN_EXP, Token::EXP);
     731      755195 :         } else if (c0_ == '=') {
     732             :           token = Select(Token::ASSIGN_MUL);
     733             :         } else {
     734             :           token = Token::MUL;
     735             :         }
     736             :         break;
     737             : 
     738             :       case '%':
     739             :         // % %=
     740             :         token = Select('=', Token::ASSIGN_MOD, Token::MOD);
     741     2287787 :         break;
     742             : 
     743             :       case '/':
     744             :         // /  // /* /=
     745     7810708 :         Advance();
     746     7810708 :         if (c0_ == '/') {
     747     6780233 :           Advance();
     748     6780233 :           if (c0_ == '#' || c0_ == '@') {
     749        2566 :             Advance();
     750        2566 :             token = SkipSourceURLComment();
     751             :           } else {
     752             :             PushBack(c0_);
     753     6777667 :             token = SkipSingleLineComment();
     754             :           }
     755     1030475 :         } else if (c0_ == '*') {
     756      549650 :           token = SkipMultiLineComment();
     757      480825 :         } else if (c0_ == '=') {
     758             :           token = Select(Token::ASSIGN_DIV);
     759             :         } else {
     760             :           token = Token::DIV;
     761             :         }
     762             :         break;
     763             : 
     764             :       case '&':
     765             :         // & && &=
     766     1655498 :         Advance();
     767     1655498 :         if (c0_ == '&') {
     768             :           token = Select(Token::AND);
     769      825361 :         } else if (c0_ == '=') {
     770             :           token = Select(Token::ASSIGN_BIT_AND);
     771             :         } else {
     772             :           token = Token::BIT_AND;
     773             :         }
     774             :         break;
     775             : 
     776             :       case '|':
     777             :         // | || |=
     778     2049474 :         Advance();
     779     2049474 :         if (c0_ == '|') {
     780             :           token = Select(Token::OR);
     781     1119064 :         } else if (c0_ == '=') {
     782             :           token = Select(Token::ASSIGN_BIT_OR);
     783             :         } else {
     784             :           token = Token::BIT_OR;
     785             :         }
     786             :         break;
     787             : 
     788             :       case '^':
     789             :         // ^ ^=
     790             :         token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
     791       45374 :         break;
     792             : 
     793             :       case '.':
     794             :         // . Number
     795    24061766 :         Advance();
     796    48123530 :         if (IsDecimalDigit(c0_)) {
     797        5084 :           token = ScanNumber(true);
     798             :         } else {
     799             :           token = Token::PERIOD;
     800    24056681 :           if (c0_ == '.') {
     801      125537 :             Advance();
     802      125537 :             if (c0_ == '.') {
     803      124673 :               Advance();
     804             :               token = Token::ELLIPSIS;
     805             :             } else {
     806             :               PushBack('.');
     807             :             }
     808             :           }
     809             :         }
     810             :         break;
     811             : 
     812             :       case ':':
     813             :         token = Select(Token::COLON);
     814     2454765 :         break;
     815             : 
     816             :       case ';':
     817             :         token = Select(Token::SEMICOLON);
     818       56632 :         break;
     819             : 
     820             :       case ',':
     821             :         token = Select(Token::COMMA);
     822      493944 :         break;
     823             : 
     824             :       case '(':
     825             :         token = Select(Token::LPAREN);
     826     8830758 :         break;
     827             : 
     828             :       case ')':
     829             :         token = Select(Token::RPAREN);
     830      554242 :         break;
     831             : 
     832             :       case '[':
     833             :         token = Select(Token::LBRACK);
     834      575636 :         break;
     835             : 
     836             :       case ']':
     837             :         token = Select(Token::RBRACK);
     838      178481 :         break;
     839             : 
     840             :       case '{':
     841             :         token = Select(Token::LBRACE);
     842    10265604 :         break;
     843             : 
     844             :       case '}':
     845             :         token = Select(Token::RBRACE);
     846    13798526 :         break;
     847             : 
     848             :       case '?':
     849             :         token = Select(Token::CONDITIONAL);
     850      228741 :         break;
     851             : 
     852             :       case '~':
     853             :         token = Select(Token::BIT_NOT);
     854        5751 :         break;
     855             : 
     856             :       case '`':
     857       88967 :         token = ScanTemplateStart();
     858       88967 :         break;
     859             : 
     860             :       default:
     861   243880872 :         if (c0_ == kEndOfInput) {
     862             :           token = Token::EOS;
     863   480744625 :         } else if (unicode_cache_->IsIdentifierStart(c0_)) {
     864   200166218 :           token = ScanIdentifierOrKeyword();
     865    80412502 :         } else if (IsDecimalDigit(c0_)) {
     866    40198881 :           token = ScanNumber(false);
     867        7370 :         } else if (SkipWhiteSpace()) {
     868             :           token = Token::WHITESPACE;
     869             :         } else {
     870             :           token = Select(Token::ILLEGAL);
     871             :         }
     872             :         break;
     873             :     }
     874             : 
     875             :     // Continue scanning for tokens as long as we're just skipping
     876             :     // whitespace.
     877             :   } while (token == Token::WHITESPACE);
     878             : 
     879   375220423 :   next_.location.end_pos = source_pos();
     880   375220423 :   if (Token::IsContextualKeyword(token)) {
     881     5074816 :     next_.token = Token::IDENTIFIER;
     882     5074816 :     next_.contextual_token = token;
     883             :   } else {
     884   370145607 :     next_.token = token;
     885   370145607 :     next_.contextual_token = Token::UNINITIALIZED;
     886             :   }
     887             : 
     888             : #ifdef DEBUG
     889             :   SanityCheckTokenDesc(current_);
     890             :   SanityCheckTokenDesc(next_);
     891             :   SanityCheckTokenDesc(next_next_);
     892             : #endif
     893   375220423 : }
     894             : 
     895             : #ifdef DEBUG
     896             : void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
     897             :   // Most tokens should not have literal_chars or even raw_literal chars.
     898             :   // The rules are:
     899             :   // - UNINITIALIZED: we don't care.
     900             :   // - TEMPLATE_*: need both literal + raw literal chars.
     901             :   // - IDENTIFIERS, STRINGS, etc.: need a literal, but no raw literal.
     902             :   // - all others: should have neither.
     903             :   // Furthermore, only TEMPLATE_* tokens can have a
     904             :   // invalid_template_escape_message.
     905             : 
     906             :   switch (token.token) {
     907             :     case Token::UNINITIALIZED:
     908             :       // token.literal_chars & other members might be garbage. That's ok.
     909             :       break;
     910             :     case Token::TEMPLATE_SPAN:
     911             :     case Token::TEMPLATE_TAIL:
     912             :       DCHECK_NOT_NULL(token.raw_literal_chars);
     913             :       DCHECK_NOT_NULL(token.literal_chars);
     914             :       break;
     915             :     case Token::ESCAPED_KEYWORD:
     916             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     917             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     918             :     case Token::IDENTIFIER:
     919             :     case Token::NUMBER:
     920             :     case Token::REGEXP_LITERAL:
     921             :     case Token::SMI:
     922             :     case Token::STRING:
     923             :       DCHECK_NOT_NULL(token.literal_chars);
     924             :       DCHECK_NULL(token.raw_literal_chars);
     925             :       DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
     926             :       break;
     927             :     default:
     928             :       DCHECK_NULL(token.literal_chars);
     929             :       DCHECK_NULL(token.raw_literal_chars);
     930             :       DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
     931             :       break;
     932             :   }
     933             : 
     934             :   DCHECK_IMPLIES(token.token != Token::IDENTIFIER,
     935             :                  token.contextual_token == Token::UNINITIALIZED);
     936             :   DCHECK_IMPLIES(token.contextual_token != Token::UNINITIALIZED,
     937             :                  token.token == Token::IDENTIFIER &&
     938             :                      Token::IsContextualKeyword(token.contextual_token));
     939             :   DCHECK(!Token::IsContextualKeyword(token.token));
     940             : }
     941             : #endif  // DEBUG
     942             : 
     943         340 : void Scanner::SeekForward(int pos) {
     944             :   // After this call, we will have the token at the given position as
     945             :   // the "next" token. The "current" token will be invalid.
     946         352 :   if (pos == next_.location.beg_pos) return;
     947             :   int current_pos = source_pos();
     948             :   DCHECK_EQ(next_.location.end_pos, current_pos);
     949             :   // Positions inside the lookahead token aren't supported.
     950             :   DCHECK(pos >= current_pos);
     951         164 :   if (pos != current_pos) {
     952         158 :     source_->Seek(pos);
     953         158 :     Advance();
     954             :     // This function is only called to seek to the location
     955             :     // of the end of a function (at the "}" token). It doesn't matter
     956             :     // whether there was a line terminator in the part we skip.
     957         158 :     has_line_terminator_before_next_ = false;
     958         158 :     has_multiline_comment_before_next_ = false;
     959             :   }
     960         164 :   Scan();
     961             : }
     962             : 
     963             : 
     964             : template <bool capture_raw, bool in_template_literal>
     965     3398535 : bool Scanner::ScanEscape() {
     966     1719605 :   uc32 c = c0_;
     967     1719605 :   Advance<capture_raw>();
     968             : 
     969             :   // Skip escaped newlines.
     970     3375714 :   if (!in_template_literal && c0_ != kEndOfInput &&
     971     1687857 :       unicode_cache_->IsLineTerminator(c)) {
     972             :     // Allow CR+LF newlines in multiline string literals.
     973       15104 :     if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
     974             :     // Allow LF+CR newlines in multiline string literals.
     975       15104 :     if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>();
     976             :     return true;
     977             :   }
     978             : 
     979     1704501 :   switch (c) {
     980             :     case '\'':  // fall through
     981             :     case '"' :  // fall through
     982             :     case '\\': break;
     983          59 :     case 'b' : c = '\b'; break;
     984         134 :     case 'f' : c = '\f'; break;
     985     1142279 :     case 'n' : c = '\n'; break;
     986         850 :     case 'r' : c = '\r'; break;
     987         392 :     case 't' : c = '\t'; break;
     988             :     case 'u' : {
     989       80747 :       c = ScanUnicodeEscape<capture_raw>();
     990       80747 :       if (c < 0) return false;
     991             :       break;
     992             :     }
     993             :     case 'v':
     994             :       c = '\v';
     995          74 :       break;
     996             :     case 'x': {
     997        6795 :       c = ScanHexNumber<capture_raw>(2);
     998        6795 :       if (c < 0) return false;
     999             :       break;
    1000             :     }
    1001             :     case '0':  // Fall through.
    1002             :     case '1':  // fall through
    1003             :     case '2':  // fall through
    1004             :     case '3':  // fall through
    1005             :     case '4':  // fall through
    1006             :     case '5':  // fall through
    1007             :     case '6':  // fall through
    1008             :     case '7':
    1009        5600 :       c = ScanOctalEscape<capture_raw>(c, 2);
    1010        5600 :       break;
    1011             :   }
    1012             : 
    1013             :   // Other escaped characters are interpreted as their non-escaped version.
    1014             :   AddLiteralChar(c);
    1015             :   return true;
    1016             : }
    1017             : 
    1018             : 
    1019             : template <bool capture_raw>
    1020       10735 : uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
    1021        5600 :   uc32 x = c - '0';
    1022             :   int i = 0;
    1023        8891 :   for (; i < length; i++) {
    1024        8332 :     int d = c0_ - '0';
    1025        8332 :     if (d < 0 || d > 7) break;
    1026        3315 :     int nx = x * 8 + d;
    1027        3315 :     if (nx >= 256) break;
    1028             :     x = nx;
    1029        3291 :     Advance<capture_raw>();
    1030             :   }
    1031             :   // Anything except '\0' is an octal escape sequence, illegal in strict mode.
    1032             :   // Remember the position of octal escape sequences so that an error
    1033             :   // can be reported later (in strict mode).
    1034             :   // We don't report the error immediately, because the octal escape can
    1035             :   // occur before the "use strict" directive.
    1036        5600 :   if (c != '0' || i > 0) {
    1037        5135 :     octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
    1038        5135 :     octal_message_ = MessageTemplate::kStrictOctalEscape;
    1039             :   }
    1040        5600 :   return x;
    1041             : }
    1042             : 
    1043             : 
    1044   520361961 : Token::Value Scanner::ScanString() {
    1045    14313735 :   uc32 quote = c0_;
    1046             :   Advance<false, false>();  // consume quote
    1047             : 
    1048             :   LiteralScope literal(this);
    1049             :   while (true) {
    1050   245518844 :     if (c0_ > kMaxAscii) {
    1051       20372 :       HandleLeadSurrogate();
    1052       20376 :       break;
    1053             :     }
    1054   245498472 :     if (c0_ == kEndOfInput || c0_ == '\n' || c0_ == '\r') return Token::ILLEGAL;
    1055   245498331 :     if (c0_ == quote) {
    1056             :       literal.Complete();
    1057             :       Advance<false, false>();
    1058    13876063 :       return Token::STRING;
    1059             :     }
    1060   231622268 :     char c = static_cast<char>(c0_);
    1061   231622268 :     if (c == '\\') break;
    1062             :     Advance<false, false>();
    1063             :     AddLiteralChar(c);
    1064             :   }
    1065             : 
    1066    34707501 :   while (c0_ != quote && c0_ != kEndOfInput &&
    1067    17136013 :          !unicode_cache_->IsLineTerminator(c0_)) {
    1068    17136013 :     uc32 c = c0_;
    1069    17136013 :     Advance();
    1070    17136013 :     if (c == '\\') {
    1071     1687871 :       if (c0_ == kEndOfInput || !ScanEscape<false, false>()) {
    1072             :         return Token::ILLEGAL;
    1073             :       }
    1074             :     } else {
    1075             :       AddLiteralChar(c);
    1076             :     }
    1077             :   }
    1078      435475 :   if (c0_ != quote) return Token::ILLEGAL;
    1079             :   literal.Complete();
    1080             : 
    1081      435475 :   Advance();  // consume quote
    1082      435475 :   return Token::STRING;
    1083             : }
    1084             : 
    1085             : 
    1086     1720446 : Token::Value Scanner::ScanTemplateSpan() {
    1087             :   // When scanning a TemplateSpan, we are looking for the following construct:
    1088             :   // TEMPLATE_SPAN ::
    1089             :   //     ` LiteralChars* ${
    1090             :   //   | } LiteralChars* ${
    1091             :   //
    1092             :   // TEMPLATE_TAIL ::
    1093             :   //     ` LiteralChars* `
    1094             :   //   | } LiteralChar* `
    1095             :   //
    1096             :   // A TEMPLATE_SPAN should always be followed by an Expression, while a
    1097             :   // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
    1098             :   // followed by an Expression.
    1099             : 
    1100             :   // These scoped helpers save and restore the original error state, so that we
    1101             :   // can specially treat invalid escape sequences in templates (which are
    1102             :   // handled by the parser).
    1103      168651 :   ErrorState scanner_error_state(&scanner_error_, &scanner_error_location_);
    1104      168651 :   ErrorState octal_error_state(&octal_message_, &octal_pos_);
    1105             : 
    1106             :   Token::Value result = Token::TEMPLATE_SPAN;
    1107             :   LiteralScope literal(this);
    1108             :   StartRawLiteral();
    1109             :   const bool capture_raw = true;
    1110             :   const bool in_template_literal = true;
    1111             :   while (true) {
    1112     1414132 :     uc32 c = c0_;
    1113     1414132 :     Advance<capture_raw>();
    1114     1414132 :     if (c == '`') {
    1115             :       result = Token::TEMPLATE_TAIL;
    1116             :       ReduceRawLiteralLength(1);
    1117             :       break;
    1118     1341062 :     } else if (c == '$' && c0_ == '{') {
    1119       93762 :       Advance<capture_raw>();  // Consume '{'
    1120             :       ReduceRawLiteralLength(2);
    1121             :       break;
    1122     1247300 :     } else if (c == '\\') {
    1123       63743 :       if (c0_ != kEndOfInput && unicode_cache_->IsLineTerminator(c0_)) {
    1124             :         // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
    1125             :         // code unit sequence.
    1126         131 :         uc32 lastChar = c0_;
    1127         131 :         Advance<capture_raw>();
    1128         131 :         if (lastChar == '\r') {
    1129             :           ReduceRawLiteralLength(1);  // Remove \r
    1130          78 :           if (c0_ == '\n') {
    1131          39 :             Advance<capture_raw>();  // Adds \n
    1132             :           } else {
    1133             :             AddRawLiteralChar('\n');
    1134             :           }
    1135             :         }
    1136             :       } else {
    1137       31748 :         bool success = ScanEscape<capture_raw, in_template_literal>();
    1138             :         USE(success);
    1139             :         DCHECK_EQ(!success, has_error());
    1140             :         // For templates, invalid escape sequence checking is handled in the
    1141             :         // parser.
    1142             :         scanner_error_state.MoveErrorTo(&next_);
    1143             :         octal_error_state.MoveErrorTo(&next_);
    1144             :       }
    1145     1215421 :     } else if (c < 0) {
    1146             :       // Unterminated template literal
    1147             :       PushBack(c);
    1148             :       break;
    1149             :     } else {
    1150             :       // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
    1151             :       // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
    1152             :       // consisting of the CV 0x000A.
    1153     1213602 :       if (c == '\r') {
    1154             :         ReduceRawLiteralLength(1);  // Remove \r
    1155         711 :         if (c0_ == '\n') {
    1156         648 :           Advance<capture_raw>();  // Adds \n
    1157             :         } else {
    1158             :           AddRawLiteralChar('\n');
    1159             :         }
    1160             :         c = '\n';
    1161             :       }
    1162             :       AddLiteralChar(c);
    1163             :     }
    1164             :   }
    1165             :   literal.Complete();
    1166      168651 :   next_.location.end_pos = source_pos();
    1167      168651 :   next_.token = result;
    1168      168651 :   next_.contextual_token = Token::UNINITIALIZED;
    1169             : 
    1170      168651 :   return result;
    1171             : }
    1172             : 
    1173             : 
    1174       88967 : Token::Value Scanner::ScanTemplateStart() {
    1175             :   DCHECK(next_next_.token == Token::UNINITIALIZED);
    1176             :   DCHECK(c0_ == '`');
    1177       88967 :   next_.location.beg_pos = source_pos();
    1178       88967 :   Advance();  // Consume `
    1179       88967 :   return ScanTemplateSpan();
    1180             : }
    1181             : 
    1182             : 
    1183       79684 : Token::Value Scanner::ScanTemplateContinuation() {
    1184             :   DCHECK_EQ(next_.token, Token::RBRACE);
    1185       79684 :   next_.location.beg_pos = source_pos() - 1;  // We already consumed }
    1186       79684 :   return ScanTemplateSpan();
    1187             : }
    1188             : 
    1189     2263498 : Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
    1190             :   Handle<String> tmp;
    1191     4526996 :   if (source_url_.length() > 0) tmp = source_url_.Internalize(isolate);
    1192     2263498 :   return tmp;
    1193             : }
    1194             : 
    1195     2263497 : Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const {
    1196             :   Handle<String> tmp;
    1197     4526994 :   if (source_mapping_url_.length() > 0)
    1198         133 :     tmp = source_mapping_url_.Internalize(isolate);
    1199     2263497 :   return tmp;
    1200             : }
    1201             : 
    1202           0 : void Scanner::ScanDecimalDigits() {
    1203    13915776 :   while (IsDecimalDigit(c0_))
    1204     2812865 :     AddLiteralCharAdvance();
    1205           0 : }
    1206             : 
    1207             : 
    1208   215682097 : Token::Value Scanner::ScanNumber(bool seen_period) {
    1209             :   DCHECK(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
    1210             : 
    1211             :   enum {
    1212             :     DECIMAL,
    1213             :     DECIMAL_WITH_LEADING_ZERO,
    1214             :     HEX,
    1215             :     OCTAL,
    1216             :     IMPLICIT_OCTAL,
    1217             :     BINARY
    1218             :   } kind = DECIMAL;
    1219             : 
    1220             :   LiteralScope literal(this);
    1221    40203956 :   bool at_start = !seen_period;
    1222             :   int start_pos = source_pos();  // For reporting octal positions.
    1223    40203956 :   if (seen_period) {
    1224             :     // we have already seen a decimal point of the float
    1225             :     AddLiteralChar('.');
    1226             :     ScanDecimalDigits();  // we know we have at least one digit
    1227             : 
    1228             :   } else {
    1229             :     // if the first character is '0' we must check for octals and hex
    1230    40198872 :     if (c0_ == '0') {
    1231    16195744 :       AddLiteralCharAdvance();
    1232             : 
    1233             :       // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
    1234             :       // an octal number.
    1235    16195745 :       if (c0_ == 'x' || c0_ == 'X') {
    1236             :         // hex number
    1237             :         kind = HEX;
    1238      213945 :         AddLiteralCharAdvance();
    1239      427890 :         if (!IsHexDigit(c0_)) {
    1240             :           // we must have at least one hex digit after 'x'/'X'
    1241             :           return Token::ILLEGAL;
    1242             :         }
    1243     1658768 :         while (IsHexDigit(c0_)) {
    1244      615442 :           AddLiteralCharAdvance();
    1245             :         }
    1246    15981800 :       } else if (c0_ == 'o' || c0_ == 'O') {
    1247             :         kind = OCTAL;
    1248          86 :         AddLiteralCharAdvance();
    1249         172 :         if (!IsOctalDigit(c0_)) {
    1250             :           // we must have at least one octal digit after 'o'/'O'
    1251             :           return Token::ILLEGAL;
    1252             :         }
    1253         412 :         while (IsOctalDigit(c0_)) {
    1254         120 :           AddLiteralCharAdvance();
    1255             :         }
    1256    15981714 :       } else if (c0_ == 'b' || c0_ == 'B') {
    1257             :         kind = BINARY;
    1258          72 :         AddLiteralCharAdvance();
    1259         144 :         if (!IsBinaryDigit(c0_)) {
    1260             :           // we must have at least one binary digit after 'b'/'B'
    1261             :           return Token::ILLEGAL;
    1262             :         }
    1263         356 :         while (IsBinaryDigit(c0_)) {
    1264         106 :           AddLiteralCharAdvance();
    1265             :         }
    1266    16162894 :       } else if ('0' <= c0_ && c0_ <= '7') {
    1267             :         // (possible) octal number
    1268             :         kind = IMPLICIT_OCTAL;
    1269             :         while (true) {
    1270      361817 :           if (c0_ == '8' || c0_ == '9') {
    1271             :             at_start = false;
    1272             :             kind = DECIMAL_WITH_LEADING_ZERO;
    1273             :             break;
    1274             :           }
    1275      361808 :           if (c0_  < '0' || '7'  < c0_) {
    1276             :             // Octal literal finished.
    1277      180556 :             octal_pos_ = Location(start_pos, source_pos());
    1278      180556 :             octal_message_ = MessageTemplate::kStrictOctalLiteral;
    1279      180556 :             break;
    1280             :           }
    1281      181252 :           AddLiteralCharAdvance();
    1282             :         }
    1283    15801077 :       } else if (c0_ == '8' || c0_ == '9') {
    1284             :         kind = DECIMAL_WITH_LEADING_ZERO;
    1285             :       }
    1286             :     }
    1287             : 
    1288             :     // Parse decimal digits and allow trailing fractional part.
    1289    40198870 :     if (kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO) {
    1290    39804211 :       if (at_start) {
    1291             :         uint64_t value = 0;
    1292   214657054 :         while (IsDecimalDigit(c0_)) {
    1293    67524317 :           value = 10 * value + (c0_ - '0');
    1294             : 
    1295             :           uc32 first_char = c0_;
    1296             :           Advance<false, false>();
    1297             :           AddLiteralChar(first_char);
    1298             :         }
    1299             : 
    1300   119361345 :         if (next_.literal_chars->one_byte_literal().length() <= 10 &&
    1301    79411396 :             value <= Smi::kMaxValue && c0_ != '.' &&
    1302    75072820 :             (c0_ == kEndOfInput || !unicode_cache_->IsIdentifierStart(c0_))) {
    1303    37658039 :           next_.smi_value_ = static_cast<uint32_t>(value);
    1304             :           literal.Complete();
    1305    37658039 :           HandleLeadSurrogate();
    1306             : 
    1307    37658039 :           if (kind == DECIMAL_WITH_LEADING_ZERO) {
    1308       44977 :             octal_pos_ = Location(start_pos, source_pos());
    1309       44977 :             octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
    1310             :           }
    1311             :           return Token::SMI;
    1312             :         }
    1313     2146175 :         HandleLeadSurrogate();
    1314             :       }
    1315             : 
    1316             :       ScanDecimalDigits();  // optional
    1317     2146184 :       if (c0_ == '.') {
    1318     1969887 :         AddLiteralCharAdvance();
    1319             :         ScanDecimalDigits();  // optional
    1320             :       }
    1321             :     }
    1322             :   }
    1323             : 
    1324             :   // scan exponent, if any
    1325     2545927 :   if (c0_ == 'e' || c0_ == 'E') {
    1326             :     DCHECK(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
    1327       23913 :     if (!(kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO))
    1328             :       return Token::ILLEGAL;
    1329             :     // scan exponent
    1330       23913 :     AddLiteralCharAdvance();
    1331       23913 :     if (c0_ == '+' || c0_ == '-')
    1332       13191 :       AddLiteralCharAdvance();
    1333       47816 :     if (!IsDecimalDigit(c0_)) {
    1334             :       // we must have at least one decimal digit after 'e'/'E'
    1335             :       return Token::ILLEGAL;
    1336             :     }
    1337             :     ScanDecimalDigits();
    1338             :   }
    1339             : 
    1340             :   // The source character immediately following a numeric literal must
    1341             :   // not be an identifier start or a decimal digit; see ECMA-262
    1342             :   // section 7.8.3, page 17 (note that we read only one decimal digit
    1343             :   // if the value is 0).
    1344     7637646 :   if (IsDecimalDigit(c0_) ||
    1345     5049756 :       (c0_ != kEndOfInput && unicode_cache_->IsIdentifierStart(c0_)))
    1346             :     return Token::ILLEGAL;
    1347             : 
    1348             :   literal.Complete();
    1349             : 
    1350     2545132 :   if (kind == DECIMAL_WITH_LEADING_ZERO) {
    1351           9 :     octal_pos_ = Location(start_pos, source_pos());
    1352           9 :     octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
    1353             :   }
    1354             :   return Token::NUMBER;
    1355             : }
    1356             : 
    1357             : 
    1358       19299 : uc32 Scanner::ScanIdentifierUnicodeEscape() {
    1359       19299 :   Advance();
    1360       19299 :   if (c0_ != 'u') return -1;
    1361       18900 :   Advance();
    1362       18900 :   return ScanUnicodeEscape<false>();
    1363             : }
    1364             : 
    1365             : 
    1366             : template <bool capture_raw>
    1367      122834 : uc32 Scanner::ScanUnicodeEscape() {
    1368             :   // Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
    1369             :   // hex digits between { } is arbitrary. \ and u have already been read.
    1370       99647 :   if (c0_ == '{') {
    1371       35784 :     int begin = source_pos() - 2;
    1372       35784 :     Advance<capture_raw>();
    1373       35784 :     uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff, begin);
    1374       35784 :     if (cp < 0 || c0_ != '}') {
    1375             :       ReportScannerError(source_pos(),
    1376             :                          MessageTemplate::kInvalidUnicodeEscapeSequence);
    1377             :       return -1;
    1378             :     }
    1379       23400 :     Advance<capture_raw>();
    1380       23400 :     return cp;
    1381             :   }
    1382             :   const bool unicode = true;
    1383       63863 :   return ScanHexNumber<capture_raw, unicode>(4);
    1384             : }
    1385             : 
    1386             : 
    1387             : // ----------------------------------------------------------------------------
    1388             : // Keyword Matcher
    1389             : 
    1390             : #define KEYWORDS(KEYWORD_GROUP, KEYWORD)                    \
    1391             :   KEYWORD_GROUP('a')                                        \
    1392             :   KEYWORD("arguments", Token::ARGUMENTS)                    \
    1393             :   KEYWORD("as", Token::AS)                                  \
    1394             :   KEYWORD("async", Token::ASYNC)                            \
    1395             :   KEYWORD("await", Token::AWAIT)                            \
    1396             :   KEYWORD("anonymous", Token::ANONYMOUS)                    \
    1397             :   KEYWORD_GROUP('b')                                        \
    1398             :   KEYWORD("break", Token::BREAK)                            \
    1399             :   KEYWORD_GROUP('c')                                        \
    1400             :   KEYWORD("case", Token::CASE)                              \
    1401             :   KEYWORD("catch", Token::CATCH)                            \
    1402             :   KEYWORD("class", Token::CLASS)                            \
    1403             :   KEYWORD("const", Token::CONST)                            \
    1404             :   KEYWORD("constructor", Token::CONSTRUCTOR)                \
    1405             :   KEYWORD("continue", Token::CONTINUE)                      \
    1406             :   KEYWORD_GROUP('d')                                        \
    1407             :   KEYWORD("debugger", Token::DEBUGGER)                      \
    1408             :   KEYWORD("default", Token::DEFAULT)                        \
    1409             :   KEYWORD("delete", Token::DELETE)                          \
    1410             :   KEYWORD("do", Token::DO)                                  \
    1411             :   KEYWORD_GROUP('e')                                        \
    1412             :   KEYWORD("else", Token::ELSE)                              \
    1413             :   KEYWORD("enum", Token::ENUM)                              \
    1414             :   KEYWORD("eval", Token::EVAL)                              \
    1415             :   KEYWORD("export", Token::EXPORT)                          \
    1416             :   KEYWORD("extends", Token::EXTENDS)                        \
    1417             :   KEYWORD_GROUP('f')                                        \
    1418             :   KEYWORD("false", Token::FALSE_LITERAL)                    \
    1419             :   KEYWORD("finally", Token::FINALLY)                        \
    1420             :   KEYWORD("for", Token::FOR)                                \
    1421             :   KEYWORD("from", Token::FROM)                              \
    1422             :   KEYWORD("function", Token::FUNCTION)                      \
    1423             :   KEYWORD_GROUP('g')                                        \
    1424             :   KEYWORD("get", Token::GET)                                \
    1425             :   KEYWORD_GROUP('i')                                        \
    1426             :   KEYWORD("if", Token::IF)                                  \
    1427             :   KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
    1428             :   KEYWORD("import", Token::IMPORT)                          \
    1429             :   KEYWORD("in", Token::IN)                                  \
    1430             :   KEYWORD("instanceof", Token::INSTANCEOF)                  \
    1431             :   KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
    1432             :   KEYWORD_GROUP('l')                                        \
    1433             :   KEYWORD("let", Token::LET)                                \
    1434             :   KEYWORD_GROUP('n')                                        \
    1435             :   KEYWORD("name", Token::NAME)                              \
    1436             :   KEYWORD("new", Token::NEW)                                \
    1437             :   KEYWORD("null", Token::NULL_LITERAL)                      \
    1438             :   KEYWORD_GROUP('o')                                        \
    1439             :   KEYWORD("of", Token::OF)                                  \
    1440             :   KEYWORD_GROUP('p')                                        \
    1441             :   KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
    1442             :   KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
    1443             :   KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
    1444             :   KEYWORD("prototype", Token::PROTOTYPE)                    \
    1445             :   KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
    1446             :   KEYWORD_GROUP('r')                                        \
    1447             :   KEYWORD("return", Token::RETURN)                          \
    1448             :   KEYWORD_GROUP('s')                                        \
    1449             :   KEYWORD("sent", Token::SENT)                              \
    1450             :   KEYWORD("set", Token::SET)                                \
    1451             :   KEYWORD("static", Token::STATIC)                          \
    1452             :   KEYWORD("super", Token::SUPER)                            \
    1453             :   KEYWORD("switch", Token::SWITCH)                          \
    1454             :   KEYWORD_GROUP('t')                                        \
    1455             :   KEYWORD("target", Token::TARGET)                          \
    1456             :   KEYWORD("this", Token::THIS)                              \
    1457             :   KEYWORD("throw", Token::THROW)                            \
    1458             :   KEYWORD("true", Token::TRUE_LITERAL)                      \
    1459             :   KEYWORD("try", Token::TRY)                                \
    1460             :   KEYWORD("typeof", Token::TYPEOF)                          \
    1461             :   KEYWORD_GROUP('u')                                        \
    1462             :   KEYWORD("undefined", Token::UNDEFINED)                    \
    1463             :   KEYWORD_GROUP('v')                                        \
    1464             :   KEYWORD("var", Token::VAR)                                \
    1465             :   KEYWORD("void", Token::VOID)                              \
    1466             :   KEYWORD_GROUP('w')                                        \
    1467             :   KEYWORD("while", Token::WHILE)                            \
    1468             :   KEYWORD("with", Token::WITH)                              \
    1469             :   KEYWORD_GROUP('y')                                        \
    1470             :   KEYWORD("yield", Token::YIELD)                            \
    1471             :   KEYWORD_GROUP('_')                                        \
    1472             :   KEYWORD("__proto__", Token::PROTO_UNDERSCORED)
    1473             : 
    1474   145769407 : static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
    1475             :                                              int input_length) {
    1476             :   DCHECK(input_length >= 1);
    1477             :   const int kMinLength = 2;
    1478             :   const int kMaxLength = 11;
    1479   145769407 :   if (input_length < kMinLength || input_length > kMaxLength) {
    1480             :     return Token::IDENTIFIER;
    1481             :   }
    1482   120043692 :   switch (input[0]) {
    1483             :     default:
    1484             : #define KEYWORD_GROUP_CASE(ch)                                \
    1485             :       break;                                                  \
    1486             :     case ch:
    1487             : #define KEYWORD(keyword, token)                                           \
    1488             :   {                                                                       \
    1489             :     /* 'keyword' is a char array, so sizeof(keyword) is */                \
    1490             :     /* strlen(keyword) plus 1 for the NUL char. */                        \
    1491             :     const int keyword_length = sizeof(keyword) - 1;                       \
    1492             :     STATIC_ASSERT(keyword_length >= kMinLength);                          \
    1493             :     STATIC_ASSERT(keyword_length <= kMaxLength);                          \
    1494             :     DCHECK_EQ(input[0], keyword[0]);                                      \
    1495             :     DCHECK(token == Token::FUTURE_STRICT_RESERVED_WORD ||                 \
    1496             :            0 == strncmp(keyword, Token::String(token), sizeof(keyword))); \
    1497             :     if (input_length == keyword_length && input[1] == keyword[1] &&       \
    1498             :         (keyword_length <= 2 || input[2] == keyword[2]) &&                \
    1499             :         (keyword_length <= 3 || input[3] == keyword[3]) &&                \
    1500             :         (keyword_length <= 4 || input[4] == keyword[4]) &&                \
    1501             :         (keyword_length <= 5 || input[5] == keyword[5]) &&                \
    1502             :         (keyword_length <= 6 || input[6] == keyword[6]) &&                \
    1503             :         (keyword_length <= 7 || input[7] == keyword[7]) &&                \
    1504             :         (keyword_length <= 8 || input[8] == keyword[8]) &&                \
    1505             :         (keyword_length <= 9 || input[9] == keyword[9]) &&                \
    1506             :         (keyword_length <= 10 || input[10] == keyword[10])) {             \
    1507             :       return token;                                                       \
    1508             :     }                                                                     \
    1509             :   }
    1510     3532070 :       KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
    1511             :   }
    1512    57724097 :   return Token::IDENTIFIER;
    1513             : }
    1514             : 
    1515             : 
    1516  2644154333 : Token::Value Scanner::ScanIdentifierOrKeyword() {
    1517             :   DCHECK(unicode_cache_->IsIdentifierStart(c0_));
    1518             :   LiteralScope literal(this);
    1519   400333066 :   if (IsInRange(c0_, 'a', 'z') || c0_ == '_') {
    1520   835382431 :     do {
    1521   835382082 :       char first_char = static_cast<char>(c0_);
    1522             :       Advance<false, false>();
    1523             :       AddLiteralChar(first_char);
    1524  1670764862 :     } while (IsInRange(c0_, 'a', 'z') || c0_ == '_');
    1525             : 
    1526   350490144 :     if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' ||
    1527             :         c0_ == '$') {
    1528             :       // Identifier starting with lowercase.
    1529    33957969 :       char first_char = static_cast<char>(c0_);
    1530             :       Advance<false, false>();
    1531             :       AddLiteralChar(first_char);
    1532   396202960 :       while (IsAsciiIdentifier(c0_)) {
    1533   164143506 :         char first_char = static_cast<char>(c0_);
    1534             :         Advance<false, false>();
    1535             :         AddLiteralChar(first_char);
    1536             :       }
    1537    33957974 :       if (c0_ <= kMaxAscii && c0_ != '\\') {
    1538             :         literal.Complete();
    1539    33957977 :         return Token::IDENTIFIER;
    1540             :       }
    1541   145767976 :     } else if (c0_ <= kMaxAscii && c0_ != '\\') {
    1542             :       // Only a-z+ or _: could be a keyword or identifier.
    1543   145752351 :       Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1544             :       Token::Value token =
    1545   145751719 :           KeywordOrIdentifierToken(chars.start(), chars.length());
    1546   291503492 :       if (token == Token::IDENTIFIER ||
    1547   208017312 :           token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1548             :           Token::IsContextualKeyword(token))
    1549             :         literal.Complete();
    1550             :       return token;
    1551             :     }
    1552             : 
    1553       16254 :     HandleLeadSurrogate();
    1554    20440937 :   } else if (IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') {
    1555   188508276 :     do {
    1556   188508269 :       char first_char = static_cast<char>(c0_);
    1557             :       Advance<false, false>();
    1558             :       AddLiteralChar(first_char);
    1559   188508276 :     } while (IsAsciiIdentifier(c0_));
    1560             : 
    1561    20437429 :     if (c0_ <= kMaxAscii && c0_ != '\\') {
    1562             :       literal.Complete();
    1563    20437361 :       return Token::IDENTIFIER;
    1564             :     }
    1565             : 
    1566          68 :     HandleLeadSurrogate();
    1567        3515 :   } else if (c0_ == '\\') {
    1568             :     // Scan identifier start character.
    1569        3363 :     uc32 c = ScanIdentifierUnicodeEscape();
    1570             :     // Only allow legal identifier start characters.
    1571       10089 :     if (c < 0 ||
    1572        9636 :         c == '\\' ||  // No recursive escapes.
    1573        2910 :         !unicode_cache_->IsIdentifierStart(c)) {
    1574             :       return Token::ILLEGAL;
    1575             :     }
    1576             :     AddLiteralChar(c);
    1577        2851 :     return ScanIdentifierSuffix(&literal, true);
    1578             :   } else {
    1579             :     uc32 first_char = c0_;
    1580         152 :     Advance();
    1581             :     AddLiteralChar(first_char);
    1582             :   }
    1583             : 
    1584             :   // Scan the rest of the identifier characters.
    1585       34539 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1586       16710 :     if (c0_ != '\\') {
    1587             :       uc32 next_char = c0_;
    1588         854 :       Advance();
    1589             :       AddLiteralChar(next_char);
    1590             :       continue;
    1591             :     }
    1592             :     // Fallthrough if no longer able to complete keyword.
    1593       15856 :     return ScanIdentifierSuffix(&literal, false);
    1594             :   }
    1595             : 
    1596        1264 :   if (next_.literal_chars->is_one_byte()) {
    1597             :     Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1598             :     Token::Value token =
    1599          51 :         KeywordOrIdentifierToken(chars.start(), chars.length());
    1600         102 :     if (token == Token::IDENTIFIER ||
    1601          51 :         token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1602             :         Token::IsContextualKeyword(token))
    1603             :       literal.Complete();
    1604             :     return token;
    1605             :   }
    1606             :   literal.Complete();
    1607         581 :   return Token::IDENTIFIER;
    1608             : }
    1609             : 
    1610             : 
    1611       18707 : Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal,
    1612       63592 :                                            bool escaped) {
    1613             :   // Scan the rest of the identifier characters.
    1614      182939 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1615       64292 :     if (c0_ == '\\') {
    1616       15936 :       uc32 c = ScanIdentifierUnicodeEscape();
    1617             :       escaped = true;
    1618             :       // Only allow legal identifier part characters.
    1619       47808 :       if (c < 0 ||
    1620       47136 :           c == '\\' ||
    1621       15264 :           !unicode_cache_->IsIdentifierPart(c)) {
    1622             :         return Token::ILLEGAL;
    1623             :       }
    1624             :       AddLiteralChar(c);
    1625             :     } else {
    1626             :       AddLiteralChar(c0_);
    1627       48356 :       Advance();
    1628             :     }
    1629             :   }
    1630             :   literal->Complete();
    1631             : 
    1632       18007 :   if (escaped && next_.literal_chars->is_one_byte()) {
    1633       17592 :     Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1634             :     Token::Value token =
    1635       17592 :         KeywordOrIdentifierToken(chars.start(), chars.length());
    1636             :     /* TODO(adamk): YIELD should be handled specially. */
    1637       34102 :     if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) {
    1638             :       return token;
    1639       32300 :     } else if (token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1640       28204 :                token == Token::LET || token == Token::STATIC) {
    1641             :       return Token::ESCAPED_STRICT_RESERVED_WORD;
    1642             :     } else {
    1643        9510 :       return Token::ESCAPED_KEYWORD;
    1644             :     }
    1645             :   }
    1646             :   return Token::IDENTIFIER;
    1647             : }
    1648             : 
    1649      259362 : bool Scanner::ScanRegExpPattern() {
    1650             :   DCHECK(next_next_.token == Token::UNINITIALIZED);
    1651             :   DCHECK(next_.token == Token::DIV || next_.token == Token::ASSIGN_DIV);
    1652             : 
    1653             :   // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
    1654             :   bool in_character_class = false;
    1655      129681 :   bool seen_equal = (next_.token == Token::ASSIGN_DIV);
    1656             : 
    1657             :   // Previous token is either '/' or '/=', in the second case, the
    1658             :   // pattern starts at =.
    1659      129681 :   next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
    1660      129681 :   next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
    1661             : 
    1662             :   // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
    1663             :   // the scanner should pass uninterpreted bodies to the RegExp
    1664             :   // constructor.
    1665             :   LiteralScope literal(this);
    1666      129681 :   if (seen_equal) {
    1667             :     AddLiteralChar('=');
    1668             :   }
    1669             : 
    1670     1243318 :   while (c0_ != '/' || in_character_class) {
    1671     2227575 :     if (c0_ == kEndOfInput || unicode_cache_->IsLineTerminator(c0_))
    1672             :       return false;
    1673     1113643 :     if (c0_ == '\\') {  // Escape sequence.
    1674      148205 :       AddLiteralCharAdvance();
    1675      296404 :       if (c0_ == kEndOfInput || unicode_cache_->IsLineTerminator(c0_))
    1676             :         return false;
    1677      148199 :       AddLiteralCharAdvance();
    1678             :       // If the escape allows more characters, i.e., \x??, \u????, or \c?,
    1679             :       // only "safe" characters are allowed (letters, digits, underscore),
    1680             :       // otherwise the escape isn't valid and the invalid character has
    1681             :       // its normal meaning. I.e., we can just continue scanning without
    1682             :       // worrying whether the following characters are part of the escape
    1683             :       // or not, since any '/', '\\' or '[' is guaranteed to not be part
    1684             :       // of the escape sequence.
    1685             : 
    1686             :       // TODO(896): At some point, parse RegExps more throughly to capture
    1687             :       // octal esacpes in strict mode.
    1688             :     } else {  // Unescaped character.
    1689      965438 :       if (c0_ == '[') in_character_class = true;
    1690      965438 :       if (c0_ == ']') in_character_class = false;
    1691      965438 :       AddLiteralCharAdvance();
    1692             :     }
    1693             :   }
    1694      129386 :   Advance();  // consume '/'
    1695             : 
    1696             :   literal.Complete();
    1697      129386 :   next_.token = Token::REGEXP_LITERAL;
    1698      129386 :   next_.contextual_token = Token::UNINITIALIZED;
    1699      129386 :   return true;
    1700             : }
    1701             : 
    1702             : 
    1703      257553 : Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
    1704             :   DCHECK(next_.token == Token::REGEXP_LITERAL);
    1705             : 
    1706             :   // Scan regular expression flags.
    1707             :   int flags = 0;
    1708      547139 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1709             :     RegExp::Flags flag = RegExp::kNone;
    1710       81710 :     switch (c0_) {
    1711             :       case 'g':
    1712             :         flag = RegExp::kGlobal;
    1713             :         break;
    1714             :       case 'i':
    1715             :         flag = RegExp::kIgnoreCase;
    1716        5495 :         break;
    1717             :       case 'm':
    1718             :         flag = RegExp::kMultiline;
    1719        8703 :         break;
    1720             :       case 's':
    1721          56 :         if (FLAG_harmony_regexp_dotall) {
    1722             :           flag = RegExp::kDotAll;
    1723             :         } else {
    1724             :           return Nothing<RegExp::Flags>();
    1725             :         }
    1726             :         break;
    1727             :       case 'u':
    1728             :         flag = RegExp::kUnicode;
    1729       23894 :         break;
    1730             :       case 'y':
    1731             :         flag = RegExp::kSticky;
    1732         100 :         break;
    1733             :       default:
    1734             :         return Nothing<RegExp::Flags>();
    1735             :     }
    1736       80964 :     if (flags & flag) {
    1737             :       return Nothing<RegExp::Flags>();
    1738             :     }
    1739       80755 :     Advance();
    1740       80755 :     flags |= flag;
    1741             :   }
    1742             : 
    1743      128299 :   next_.location.end_pos = source_pos();
    1744      128299 :   return Just(RegExp::Flags(flags));
    1745             : }
    1746             : 
    1747   142597687 : const AstRawString* Scanner::CurrentSymbol(
    1748   142597687 :     AstValueFactory* ast_value_factory) const {
    1749   142597687 :   if (is_literal_one_byte()) {
    1750   142534818 :     return ast_value_factory->GetOneByteString(literal_one_byte_string());
    1751             :   }
    1752       63043 :   return ast_value_factory->GetTwoByteString(literal_two_byte_string());
    1753             : }
    1754             : 
    1755       98348 : const AstRawString* Scanner::NextSymbol(
    1756       98348 :     AstValueFactory* ast_value_factory) const {
    1757       98348 :   if (is_next_literal_one_byte()) {
    1758       95229 :     return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
    1759             :   }
    1760        3119 :   return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
    1761             : }
    1762             : 
    1763       70792 : const AstRawString* Scanner::CurrentRawSymbol(
    1764       70792 :     AstValueFactory* ast_value_factory) const {
    1765       70792 :   if (is_raw_literal_one_byte()) {
    1766       70763 :     return ast_value_factory->GetOneByteString(raw_literal_one_byte_string());
    1767             :   }
    1768          29 :   return ast_value_factory->GetTwoByteString(raw_literal_two_byte_string());
    1769             : }
    1770             : 
    1771             : 
    1772     2562778 : double Scanner::DoubleValue() {
    1773             :   DCHECK(is_literal_one_byte());
    1774             :   return StringToDouble(
    1775             :       unicode_cache_,
    1776             :       literal_one_byte_string(),
    1777     2562778 :       ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
    1778             : }
    1779             : 
    1780             : 
    1781     1745359 : bool Scanner::ContainsDot() {
    1782             :   DCHECK(is_literal_one_byte());
    1783             :   Vector<const uint8_t> str = literal_one_byte_string();
    1784     3490718 :   return std::find(str.begin(), str.end(), '.') != str.end();
    1785             : }
    1786             : 
    1787    11242565 : bool Scanner::IsDuplicateSymbol(DuplicateFinder* duplicate_finder,
    1788             :                                 AstValueFactory* ast_value_factory) const {
    1789             :   DCHECK_NOT_NULL(duplicate_finder);
    1790             :   DCHECK_NOT_NULL(ast_value_factory);
    1791    11242565 :   const AstRawString* string = CurrentSymbol(ast_value_factory);
    1792    22485132 :   return !duplicate_finder->known_symbols_.insert(string).second;
    1793             : }
    1794             : 
    1795         178 : void Scanner::SeekNext(size_t position) {
    1796             :   // Use with care: This cleanly resets most, but not all scanner state.
    1797             :   // TODO(vogelheim): Fix this, or at least DCHECK the relevant conditions.
    1798             : 
    1799             :   // To re-scan from a given character position, we need to:
    1800             :   // 1, Reset the current_, next_ and next_next_ tokens
    1801             :   //    (next_ + next_next_ will be overwrittem by Next(),
    1802             :   //     current_ will remain unchanged, so overwrite it fully.)
    1803             :   current_ = {{0, 0},
    1804             :               nullptr,
    1805             :               nullptr,
    1806             :               0,
    1807             :               Token::UNINITIALIZED,
    1808             :               MessageTemplate::kNone,
    1809             :               {0, 0},
    1810         178 :               Token::UNINITIALIZED};
    1811         178 :   next_.token = Token::UNINITIALIZED;
    1812         178 :   next_.contextual_token = Token::UNINITIALIZED;
    1813         178 :   next_next_.token = Token::UNINITIALIZED;
    1814         178 :   next_next_.contextual_token = Token::UNINITIALIZED;
    1815             :   // 2, reset the source to the desired position,
    1816         178 :   source_->Seek(position);
    1817             :   // 3, re-scan, by scanning the look-ahead char + 1 token (next_).
    1818         178 :   c0_ = source_->Advance();
    1819         178 :   Next();
    1820             :   DCHECK_EQ(next_.location.beg_pos, static_cast<int>(position));
    1821         178 : }
    1822             : 
    1823             : }  // namespace internal
    1824             : }  // namespace v8

Generated by: LCOV version 1.10