LCOV - code coverage report
Current view: top level - src/parsing - scanner.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 576 595 96.8 %
Date: 2017-10-20 Functions: 50 55 90.9 %

          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/parsing/duplicate-finder.h"  // For Scanner::FindSymbol
      17             : #include "src/unicode-cache-inl.h"
      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      275542 :         old_location_(*location_stack) {
      30      275542 :     *message_stack_ = MessageTemplate::kNone;
      31      275542 :     *location_stack_ = Location::invalid();
      32             :   }
      33             : 
      34             :   ~ErrorState() {
      35      275542 :     *message_stack_ = old_message_;
      36      275542 :     *location_stack_ = old_location_;
      37             :   }
      38             : 
      39             :   void MoveErrorTo(TokenDesc* dest) {
      40       49982 :     if (*message_stack_ == MessageTemplate::kNone) {
      41             :       return;
      42             :     }
      43       23142 :     if (dest->invalid_template_escape_message == MessageTemplate::kNone) {
      44       23142 :       dest->invalid_template_escape_message = *message_stack_;
      45       23142 :       dest->invalid_template_escape_location = *location_stack_;
      46             :     }
      47       23142 :     *message_stack_ = MessageTemplate::kNone;
      48       23142 :     *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        2780 : Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const {
      62        2780 :   if (is_one_byte()) {
      63        2780 :     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     3331746 :   int capacity = Max(min_capacity, backing_store_.length());
      70     3331758 :   int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
      71           0 :   return new_capacity;
      72             : }
      73             : 
      74     3331746 : void Scanner::LiteralBuffer::ExpandBuffer() {
      75             :   Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
      76     3331750 :   MemCopy(new_store.start(), backing_store_.start(), position_);
      77             :   backing_store_.Dispose();
      78     3331750 :   backing_store_ = new_store;
      79     3331750 : }
      80             : 
      81       51693 : void Scanner::LiteralBuffer::ConvertToTwoByte() {
      82             :   DCHECK(is_one_byte_);
      83             :   Vector<byte> new_store;
      84       51693 :   int new_content_size = position_ * kUC16Size;
      85      206772 :   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       51681 :     new_store = backing_store_;
      91             :   }
      92             :   uint8_t* src = backing_store_.start();
      93             :   uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.start());
      94      104302 :   for (int i = position_ - 1; i >= 0; i--) {
      95       52609 :     dst[i] = src[i];
      96             :   }
      97       51693 :   if (new_store.start() != backing_store_.start()) {
      98             :     backing_store_.Dispose();
      99          12 :     backing_store_ = new_store;
     100             :   }
     101       51693 :   position_ = new_content_size;
     102       51693 :   is_one_byte_ = false;
     103       51693 : }
     104             : 
     105      986841 : void Scanner::LiteralBuffer::AddCharSlow(uc32 code_unit) {
     106     2975447 :   if (position_ >= backing_store_.length()) ExpandBuffer();
     107      986841 :   if (is_one_byte_) {
     108       51693 :     if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
     109           0 :       backing_store_[position_] = static_cast<byte>(code_unit);
     110           0 :       position_ += kOneByteSize;
     111      986841 :       return;
     112             :     }
     113       51693 :     ConvertToTwoByte();
     114             :   }
     115      986841 :   if (code_unit <=
     116             :       static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
     117     1958758 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
     118      979379 :     position_ += kUC16Size;
     119             :   } else {
     120        7462 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
     121       14924 :         unibrow::Utf16::LeadSurrogate(code_unit);
     122        7462 :     position_ += kUC16Size;
     123        7462 :     if (position_ >= backing_store_.length()) ExpandBuffer();
     124        7462 :     *reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
     125        7462 :         unibrow::Utf16::TrailSurrogate(code_unit);
     126        7462 :     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     2245915 : 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     2245915 :   bookmark_ = (scanner_->current_.token == Token::UNINITIALIZED)
     152             :                   ? kBookmarkAtFirstPos
     153     2245915 :                   : scanner_->location().beg_pos;
     154     2245915 : }
     155             : 
     156         157 : void Scanner::BookmarkScope::Apply() {
     157             :   DCHECK(HasBeenSet());  // Caller hasn't called SetBookmark.
     158         157 :   if (bookmark_ == kBookmarkAtFirstPos) {
     159           6 :     scanner_->SeekNext(0);
     160             :   } else {
     161         151 :     scanner_->SeekNext(bookmark_);
     162         151 :     scanner_->Next();
     163             :     DCHECK_EQ(scanner_->location().beg_pos, static_cast<int>(bookmark_));
     164             :   }
     165         157 :   bookmark_ = kBookmarkWasApplied;
     166         157 : }
     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             : // LineTerminator:       'JS_Line_Terminator' in point.properties
     177             : // ES#sec-line-terminators lists exactly 4 code points:
     178             : // LF (U+000A), CR (U+000D), LS(U+2028), PS(U+2029)
     179           0 : bool Scanner::IsLineTerminator(uc32 c) {
     180   343813909 :   if (c == 0x000A || c == 0x000D) {
     181             :     return true;
     182             :   }
     183   337684875 :   if (c == 0x2028 || c == 0x2029) {
     184             :     ++use_counts_[v8::Isolate::UseCounterFeature::
     185         116 :                       kLineOrParagraphSeparatorAsLineTerminator];
     186           0 :     return true;
     187             :   }
     188             :   return false;
     189             : }
     190             : 
     191             : // ----------------------------------------------------------------------------
     192             : // Scanner
     193             : 
     194     2786057 : Scanner::Scanner(UnicodeCache* unicode_cache, int* use_counts)
     195             :     : unicode_cache_(unicode_cache),
     196             :       octal_pos_(Location::invalid()),
     197             :       octal_message_(MessageTemplate::kNone),
     198             :       found_html_comment_(false),
     199             :       allow_harmony_bigint_(false),
     200     8358171 :       use_counts_(use_counts) {}
     201             : 
     202     2786055 : void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
     203             :   DCHECK_NOT_NULL(source);
     204     2786055 :   source_ = source;
     205     2786055 :   is_module_ = is_module;
     206             :   // Need to capture identifiers in order to recognize "get" and "set"
     207             :   // in object literals.
     208     2786055 :   Init();
     209     2786055 :   has_line_terminator_before_next_ = true;
     210     2786055 :   Scan();
     211     2786054 : }
     212             : 
     213             : template <bool capture_raw, bool unicode>
     214    18132107 : uc32 Scanner::ScanHexNumber(int expected_length) {
     215             :   DCHECK_LE(expected_length, 4);  // prevent overflow
     216             : 
     217    18132107 :   int begin = source_pos() - 2;
     218             :   uc32 x = 0;
     219    54464327 :   for (int i = 0; i < expected_length; i++) {
     220    36343656 :     int d = HexValue(c0_);
     221    36343656 :     if (d < 0) {
     222             :       ReportScannerError(Location(begin, begin + expected_length + 2),
     223             :                          unicode
     224             :                              ? MessageTemplate::kInvalidUnicodeEscapeSequence
     225       11436 :                              : MessageTemplate::kInvalidHexEscapeSequence);
     226             :       return -1;
     227             :     }
     228    36332220 :     x = x * 16 + d;
     229    36332220 :     Advance<capture_raw>();
     230             :   }
     231             : 
     232             :   return x;
     233             : }
     234             : 
     235             : template <bool capture_raw>
     236       39536 : uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value, int beg_pos) {
     237             :   uc32 x = 0;
     238       37256 :   int d = HexValue(c0_);
     239       37256 :   if (d < 0) return -1;
     240             : 
     241      150690 :   while (d >= 0) {
     242      121514 :     x = x * 16 + d;
     243      121514 :     if (x > max_value) {
     244             :       ReportScannerError(Location(beg_pos, source_pos() + 1),
     245             :                          MessageTemplate::kUndefinedUnicodeCodePoint);
     246             :       return -1;
     247             :     }
     248      119234 :     Advance<capture_raw>();
     249      119234 :     d = HexValue(c0_);
     250             :   }
     251             : 
     252             :   return x;
     253             : }
     254             : 
     255             : 
     256             : // Ensure that tokens can be stored in a byte.
     257             : STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
     258             : 
     259             : // Table of one-character tokens, by character (0x00..0x7f only).
     260             : static const byte one_char_tokens[] = {
     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::ILLEGAL,
     287             :   Token::ILLEGAL,
     288             :   Token::ILLEGAL,
     289             :   Token::ILLEGAL,
     290             :   Token::ILLEGAL,
     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::LPAREN,       // 0x28
     302             :   Token::RPAREN,       // 0x29
     303             :   Token::ILLEGAL,
     304             :   Token::ILLEGAL,
     305             :   Token::COMMA,        // 0x2c
     306             :   Token::ILLEGAL,
     307             :   Token::ILLEGAL,
     308             :   Token::ILLEGAL,
     309             :   Token::ILLEGAL,
     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::COLON,        // 0x3a
     320             :   Token::SEMICOLON,    // 0x3b
     321             :   Token::ILLEGAL,
     322             :   Token::ILLEGAL,
     323             :   Token::ILLEGAL,
     324             :   Token::CONDITIONAL,  // 0x3f
     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::ILLEGAL,
     338             :   Token::ILLEGAL,
     339             :   Token::ILLEGAL,
     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::LBRACK,     // 0x5b
     353             :   Token::ILLEGAL,
     354             :   Token::RBRACK,     // 0x5d
     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::ILLEGAL,
     370             :   Token::ILLEGAL,
     371             :   Token::ILLEGAL,
     372             :   Token::ILLEGAL,
     373             :   Token::ILLEGAL,
     374             :   Token::ILLEGAL,
     375             :   Token::ILLEGAL,
     376             :   Token::ILLEGAL,
     377             :   Token::ILLEGAL,
     378             :   Token::ILLEGAL,
     379             :   Token::ILLEGAL,
     380             :   Token::ILLEGAL,
     381             :   Token::ILLEGAL,
     382             :   Token::ILLEGAL,
     383             :   Token::ILLEGAL,
     384             :   Token::LBRACE,       // 0x7b
     385             :   Token::ILLEGAL,
     386             :   Token::RBRACE,       // 0x7d
     387             :   Token::BIT_NOT,      // 0x7e
     388             :   Token::ILLEGAL
     389             : };
     390             : 
     391             : 
     392   634541110 : Token::Value Scanner::Next() {
     393   493550321 :   if (next_.token == Token::EOS) {
     394        2865 :     next_.location.beg_pos = current_.location.beg_pos;
     395        2865 :     next_.location.end_pos = current_.location.end_pos;
     396             :   }
     397   493550321 :   current_ = next_;
     398   493550321 :   if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
     399    86271368 :     next_ = next_next_;
     400    86271368 :     next_next_.token = Token::UNINITIALIZED;
     401    86271368 :     next_next_.contextual_token = Token::UNINITIALIZED;
     402    86271368 :     has_line_terminator_before_next_ = has_line_terminator_after_next_;
     403    86271368 :     return current_.token;
     404             :   }
     405   407278953 :   has_line_terminator_before_next_ = false;
     406   407278953 :   has_multiline_comment_before_next_ = false;
     407   407278953 :   if (static_cast<unsigned>(c0_) <= 0x7f) {
     408   405119359 :     Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
     409   405119359 :     if (token != Token::ILLEGAL) {
     410             :       int pos = source_pos();
     411   140990789 :       next_.token = token;
     412   140990789 :       next_.contextual_token = Token::UNINITIALIZED;
     413   140990789 :       next_.location.beg_pos = pos;
     414   140990789 :       next_.location.end_pos = pos + 1;
     415   140990789 :       next_.literal_chars = nullptr;
     416   140990789 :       next_.raw_literal_chars = nullptr;
     417   140990789 :       next_.invalid_template_escape_message = MessageTemplate::kNone;
     418   140990789 :       Advance();
     419   140990824 :       return current_.token;
     420             :     }
     421             :   }
     422   266288164 :   Scan();
     423   266289648 :   return current_.token;
     424             : }
     425             : 
     426             : 
     427    86564020 : Token::Value Scanner::PeekAhead() {
     428             :   DCHECK(next_.token != Token::DIV);
     429             :   DCHECK(next_.token != Token::ASSIGN_DIV);
     430             : 
     431    86564020 :   if (next_next_.token != Token::UNINITIALIZED) {
     432             :     return next_next_.token;
     433             :   }
     434    86272960 :   TokenDesc prev = current_;
     435             :   bool has_line_terminator_before_next =
     436    86272960 :       has_line_terminator_before_next_ || has_multiline_comment_before_next_;
     437    86272960 :   Next();
     438             :   has_line_terminator_after_next_ =
     439    86272989 :       has_line_terminator_before_next_ || has_multiline_comment_before_next_;
     440    86272989 :   has_line_terminator_before_next_ = has_line_terminator_before_next;
     441    86272989 :   Token::Value ret = next_.token;
     442    86272989 :   next_next_ = next_;
     443    86272989 :   next_ = current_;
     444    86272989 :   current_ = prev;
     445    86272989 :   return ret;
     446             : }
     447             : 
     448             : 
     449        7444 : Token::Value Scanner::SkipWhiteSpace() {
     450             :   int start_position = source_pos();
     451             : 
     452             :   while (true) {
     453             :     while (true) {
     454             :       // Don't skip behind the end of input.
     455       17155 :       if (c0_ == kEndOfInput) break;
     456             : 
     457             :       // Advance as long as character is a WhiteSpace or LineTerminator.
     458             :       // Remember if the latter is the case.
     459       16881 :       if (IsLineTerminator(c0_)) {
     460        3088 :         has_line_terminator_before_next_ = true;
     461       27586 :       } else if (!unicode_cache_->IsWhiteSpace(c0_)) {
     462             :         break;
     463             :       }
     464       13433 :       Advance();
     465             :     }
     466             : 
     467             :     // If there is an HTML comment end '-->' at the beginning of a
     468             :     // line (with only whitespace in front of it), we treat the rest
     469             :     // of the line as a comment. This is in line with the way
     470             :     // SpiderMonkey handles it.
     471        3722 :     if (c0_ != '-' || !has_line_terminator_before_next_) break;
     472             : 
     473           0 :     Advance();
     474           0 :     if (c0_ != '-') {
     475             :       PushBack('-');  // undo Advance()
     476             :       break;
     477             :     }
     478             : 
     479           0 :     Advance();
     480           0 :     if (c0_ != '>') {
     481             :       PushBack2('-', '-');  // undo 2x Advance();
     482             :       break;
     483             :     }
     484             : 
     485             :     // Treat the rest of the line as a comment.
     486           0 :     Token::Value token = SkipSingleHTMLComment();
     487           0 :     if (token == Token::ILLEGAL) {
     488             :       return token;
     489             :     }
     490       13433 :   }
     491             : 
     492             :   // Return whether or not we skipped any characters.
     493        3722 :   if (source_pos() == start_position) {
     494             :     return Token::ILLEGAL;
     495             :   }
     496             : 
     497        3502 :   return Token::WHITESPACE;
     498             : }
     499             : 
     500         197 : Token::Value Scanner::SkipSingleHTMLComment() {
     501         192 :   if (is_module_) {
     502             :     ReportScannerError(source_pos(), MessageTemplate::kHtmlCommentInModule);
     503             :     return Token::ILLEGAL;
     504             :   }
     505         187 :   return SkipSingleLineComment();
     506             : }
     507             : 
     508     5328985 : Token::Value Scanner::SkipSingleLineComment() {
     509     5328985 :   Advance();
     510             : 
     511             :   // The line terminator at the end of the line is not considered
     512             :   // to be part of the single-line comment; it is recognized
     513             :   // separately by the lexical grammar and becomes part of the
     514             :   // stream of input elements for the syntactic grammar (see
     515             :   // ECMA-262, section 7.4).
     516   550934367 :   while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
     517   267473937 :     Advance();
     518             :   }
     519             : 
     520     5328985 :   return Token::WHITESPACE;
     521             : }
     522             : 
     523             : 
     524        2881 : Token::Value Scanner::SkipSourceURLComment() {
     525        2881 :   TryToParseSourceURLComment();
     526        7317 :   while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
     527         624 :     Advance();
     528             :   }
     529             : 
     530        2881 :   return Token::WHITESPACE;
     531             : }
     532             : 
     533             : 
     534        2881 : void Scanner::TryToParseSourceURLComment() {
     535             :   // Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
     536             :   // function will just return if it cannot parse a magic comment.
     537        5823 :   if (c0_ == kEndOfInput || !unicode_cache_->IsWhiteSpace(c0_)) return;
     538        2871 :   Advance();
     539             :   LiteralBuffer name;
     540       88590 :   while (c0_ != kEndOfInput &&
     541       59040 :          !unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) && c0_ != '=') {
     542       26659 :     name.AddChar(c0_);
     543       26659 :     Advance();
     544             :   }
     545        2871 :   if (!name.is_one_byte()) return;
     546             :   Vector<const uint8_t> name_literal = name.one_byte_literal();
     547             :   LiteralBuffer* value;
     548        2871 :   if (name_literal == STATIC_CHAR_VECTOR("sourceURL")) {
     549        2710 :     value = &source_url_;
     550         161 :   } else if (name_literal == STATIC_CHAR_VECTOR("sourceMappingURL")) {
     551         130 :     value = &source_mapping_url_;
     552             :   } else {
     553             :     return;
     554             :   }
     555        2840 :   if (c0_ != '=')
     556             :     return;
     557        2830 :   Advance();
     558             :   value->Reset();
     559        5700 :   while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) {
     560          20 :     Advance();
     561             :   }
     562       61931 :   while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
     563             :     // Disallowed characters.
     564       29462 :     if (c0_ == '"' || c0_ == '\'') {
     565             :       value->Reset();
     566             :       return;
     567             :     }
     568       58884 :     if (unicode_cache_->IsWhiteSpace(c0_)) {
     569             :       break;
     570             :     }
     571       29402 :     value->AddChar(c0_);
     572       29402 :     Advance();
     573             :   }
     574             :   // Allow whitespace at the end.
     575        3177 :   while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
     576         140 :     if (!unicode_cache_->IsWhiteSpace(c0_)) {
     577             :       value->Reset();
     578             :       break;
     579             :     }
     580          50 :     Advance();
     581             :   }
     582             : }
     583             : 
     584             : 
     585      428620 : Token::Value Scanner::SkipMultiLineComment() {
     586             :   DCHECK_EQ(c0_, '*');
     587      428620 :   Advance();
     588             : 
     589    28992364 :   while (c0_ != kEndOfInput) {
     590             :     uc32 ch = c0_;
     591    28563742 :     Advance();
     592    57127482 :     if (c0_ != kEndOfInput && IsLineTerminator(ch)) {
     593             :       // Following ECMA-262, section 7.4, a comment containing
     594             :       // a newline will make the comment count as a line-terminator.
     595      785645 :       has_multiline_comment_before_next_ = true;
     596             :     }
     597             :     // If we have reached the end of the multi-line comment, we
     598             :     // consume the '/' and insert a whitespace. This way all
     599             :     // multi-line comments are treated as whitespace.
     600    28563742 :     if (ch == '*' && c0_ == '/') {
     601      428618 :       c0_ = ' ';
     602      428618 :       return Token::WHITESPACE;
     603             :     }
     604             :   }
     605             : 
     606             :   // Unterminated multi-line comment.
     607             :   return Token::ILLEGAL;
     608             : }
     609             : 
     610         111 : Token::Value Scanner::ScanHtmlComment() {
     611             :   // Check for <!-- comments.
     612             :   DCHECK_EQ(c0_, '!');
     613          75 :   Advance();
     614          75 :   if (c0_ != '-') {
     615             :     PushBack('!');  // undo Advance()
     616             :     return Token::LT;
     617             :   }
     618             : 
     619          57 :   Advance();
     620          57 :   if (c0_ != '-') {
     621             :     PushBack2('-', '!');  // undo 2x Advance()
     622          18 :     return Token::LT;
     623             :   }
     624             : 
     625          39 :   found_html_comment_ = true;
     626          39 :   return SkipSingleHTMLComment();
     627             : }
     628             : 
     629  1129083520 : void Scanner::Scan() {
     630   269112928 :   next_.literal_chars = nullptr;
     631   269112928 :   next_.raw_literal_chars = nullptr;
     632   269112928 :   next_.invalid_template_escape_message = MessageTemplate::kNone;
     633             :   Token::Value token;
     634   585527940 :   do {
     635             :     // Remember the position of the next token
     636   585529686 :     next_.location.beg_pos = source_pos();
     637             : 
     638   585529686 :     switch (c0_) {
     639             :       case ' ':
     640             :       case '\t':
     641   250630691 :         Advance();
     642             :         token = Token::WHITESPACE;
     643   250630697 :         break;
     644             : 
     645             :       case '\n':
     646    60022304 :         Advance();
     647    60022302 :         has_line_terminator_before_next_ = true;
     648             :         token = Token::WHITESPACE;
     649    60022302 :         break;
     650             : 
     651             :       case '"':
     652             :       case '\'':
     653    10890649 :         token = ScanString();
     654    10890648 :         break;
     655             : 
     656             :       case '<':
     657             :         // < <= << <<= <!--
     658     1246241 :         Advance();
     659     1246241 :         if (c0_ == '=') {
     660             :           token = Select(Token::LTE);
     661     1149980 :         } else if (c0_ == '<') {
     662             :           token = Select('=', Token::ASSIGN_SHL, Token::SHL);
     663      805257 :         } else if (c0_ == '!') {
     664          75 :           token = ScanHtmlComment();
     665             :         } else {
     666             :           token = Token::LT;
     667             :         }
     668             :         break;
     669             : 
     670             :       case '>':
     671             :         // > >= >> >>= >>> >>>=
     672      690396 :         Advance();
     673      690396 :         if (c0_ == '=') {
     674             :           token = Select(Token::GTE);
     675      573459 :         } else if (c0_ == '>') {
     676             :           // >> >>= >>> >>>=
     677      305764 :           Advance();
     678      305764 :           if (c0_ == '=') {
     679             :             token = Select(Token::ASSIGN_SAR);
     680      300260 :           } else if (c0_ == '>') {
     681             :             token = Select('=', Token::ASSIGN_SHR, Token::SHR);
     682             :           } else {
     683             :             token = Token::SAR;
     684             :           }
     685             :         } else {
     686             :           token = Token::GT;
     687             :         }
     688             :         break;
     689             : 
     690             :       case '=':
     691             :         // = == === =>
     692    23348296 :         Advance();
     693    23348296 :         if (c0_ == '=') {
     694             :           token = Select('=', Token::EQ_STRICT, Token::EQ);
     695    21184024 :         } else if (c0_ == '>') {
     696             :           token = Select(Token::ARROW);
     697             :         } else {
     698             :           token = Token::ASSIGN;
     699             :         }
     700             :         break;
     701             : 
     702             :       case '!':
     703             :         // ! != !==
     704     1966575 :         Advance();
     705     1966575 :         if (c0_ == '=') {
     706             :           token = Select('=', Token::NE_STRICT, Token::NE);
     707             :         } else {
     708             :           token = Token::NOT;
     709             :         }
     710             :         break;
     711             : 
     712             :       case '+':
     713             :         // + ++ +=
     714     5530921 :         Advance();
     715     5530922 :         if (c0_ == '+') {
     716             :           token = Select(Token::INC);
     717     4276305 :         } else if (c0_ == '=') {
     718             :           token = Select(Token::ASSIGN_ADD);
     719             :         } else {
     720             :           token = Token::ADD;
     721             :         }
     722             :         break;
     723             : 
     724             :       case '-':
     725             :         // - -- --> -=
     726     1017807 :         Advance();
     727     1017807 :         if (c0_ == '-') {
     728      102203 :           Advance();
     729      102409 :           if (c0_ == '>' && HasAnyLineTerminatorBeforeNext()) {
     730             :             // For compatibility with SpiderMonkey, we skip lines that
     731             :             // start with an HTML comment end '-->'.
     732         153 :             token = SkipSingleHTMLComment();
     733             :           } else {
     734             :             token = Token::DEC;
     735             :           }
     736      915604 :         } else if (c0_ == '=') {
     737             :           token = Select(Token::ASSIGN_SUB);
     738             :         } else {
     739             :           token = Token::SUB;
     740             :         }
     741             :         break;
     742             : 
     743             :       case '*':
     744             :         // * *=
     745      528397 :         Advance();
     746      528397 :         if (c0_ == '*') {
     747             :           token = Select('=', Token::ASSIGN_EXP, Token::EXP);
     748      520689 :         } else if (c0_ == '=') {
     749             :           token = Select(Token::ASSIGN_MUL);
     750             :         } else {
     751             :           token = Token::MUL;
     752             :         }
     753             :         break;
     754             : 
     755             :       case '%':
     756             :         // % %=
     757             :         token = Select('=', Token::ASSIGN_MOD, Token::MOD);
     758     1224374 :         break;
     759             : 
     760             :       case '/':
     761             :         // /  // /* /=
     762     6087037 :         Advance();
     763     6087037 :         if (c0_ == '/') {
     764     5331679 :           Advance();
     765     5331679 :           if (c0_ == '#' || c0_ == '@') {
     766        2881 :             Advance();
     767        2881 :             token = SkipSourceURLComment();
     768             :           } else {
     769             :             PushBack(c0_);
     770     5328798 :             token = SkipSingleLineComment();
     771             :           }
     772      755358 :         } else if (c0_ == '*') {
     773      428620 :           token = SkipMultiLineComment();
     774      326738 :         } else if (c0_ == '=') {
     775             :           token = Select(Token::ASSIGN_DIV);
     776             :         } else {
     777             :           token = Token::DIV;
     778             :         }
     779             :         break;
     780             : 
     781             :       case '&':
     782             :         // & && &=
     783     1189124 :         Advance();
     784     1189124 :         if (c0_ == '&') {
     785             :           token = Select(Token::AND);
     786      595495 :         } else if (c0_ == '=') {
     787             :           token = Select(Token::ASSIGN_BIT_AND);
     788             :         } else {
     789             :           token = Token::BIT_AND;
     790             :         }
     791             :         break;
     792             : 
     793             :       case '|':
     794             :         // | || |=
     795     1038846 :         Advance();
     796     1038846 :         if (c0_ == '|') {
     797             :           token = Select(Token::OR);
     798      423543 :         } else if (c0_ == '=') {
     799             :           token = Select(Token::ASSIGN_BIT_OR);
     800             :         } else {
     801             :           token = Token::BIT_OR;
     802             :         }
     803             :         break;
     804             : 
     805             :       case '^':
     806             :         // ^ ^=
     807             :         token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
     808       19592 :         break;
     809             : 
     810             :       case '.':
     811             :         // . Number
     812    17338558 :         Advance();
     813    34677114 :         if (IsDecimalDigit(c0_)) {
     814        2993 :           token = ScanNumber(true);
     815             :         } else {
     816             :           token = Token::PERIOD;
     817    17335564 :           if (c0_ == '.') {
     818      116910 :             Advance();
     819      116910 :             if (c0_ == '.') {
     820      116190 :               Advance();
     821             :               token = Token::ELLIPSIS;
     822             :             } else {
     823             :               PushBack('.');
     824             :             }
     825             :           }
     826             :         }
     827             :         break;
     828             : 
     829             :       case ':':
     830             :         token = Select(Token::COLON);
     831     1985691 :         break;
     832             : 
     833             :       case ';':
     834             :         token = Select(Token::SEMICOLON);
     835       47132 :         break;
     836             : 
     837             :       case ',':
     838             :         token = Select(Token::COMMA);
     839      489491 :         break;
     840             : 
     841             :       case '(':
     842             :         token = Select(Token::LPAREN);
     843     6553532 :         break;
     844             : 
     845             :       case ')':
     846             :         token = Select(Token::RPAREN);
     847      396915 :         break;
     848             : 
     849             :       case '[':
     850             :         token = Select(Token::LBRACK);
     851      673629 :         break;
     852             : 
     853             :       case ']':
     854             :         token = Select(Token::RBRACK);
     855      132525 :         break;
     856             : 
     857             :       case '{':
     858             :         token = Select(Token::LBRACE);
     859     8357810 :         break;
     860             : 
     861             :       case '}':
     862             :         token = Select(Token::RBRACE);
     863    10331664 :         break;
     864             : 
     865             :       case '?':
     866             :         token = Select(Token::CONDITIONAL);
     867      225986 :         break;
     868             : 
     869             :       case '~':
     870             :         token = Select(Token::BIT_NOT);
     871        2898 :         break;
     872             : 
     873             :       case '`':
     874       70715 :         token = ScanTemplateStart();
     875       70715 :         break;
     876             : 
     877             :       default:
     878   173491888 :         if (c0_ == kEndOfInput) {
     879             :           token = Token::EOS;
     880   342372018 :         } else if (unicode_cache_->IsIdentifierStart(c0_)) {
     881   141650187 :           token = ScanIdentifierOrKeyword();
     882    59071724 :         } else if (IsDecimalDigit(c0_)) {
     883    29532140 :           token = ScanNumber(false);
     884             :         } else {
     885        3722 :           token = SkipWhiteSpace();
     886        3722 :           if (token == Token::ILLEGAL) {
     887         220 :             Advance();
     888             :           }
     889             :         }
     890             :         break;
     891             :     }
     892             : 
     893             :     // Continue scanning for tokens as long as we're just skipping
     894             :     // whitespace.
     895             :   } while (token == Token::WHITESPACE);
     896             : 
     897   269111182 :   next_.location.end_pos = source_pos();
     898   269111182 :   if (Token::IsContextualKeyword(token)) {
     899     4314433 :     next_.token = Token::IDENTIFIER;
     900     4314433 :     next_.contextual_token = token;
     901             :   } else {
     902   264796749 :     next_.token = token;
     903   264796749 :     next_.contextual_token = Token::UNINITIALIZED;
     904             :   }
     905             : 
     906             : #ifdef DEBUG
     907             :   SanityCheckTokenDesc(current_);
     908             :   SanityCheckTokenDesc(next_);
     909             :   SanityCheckTokenDesc(next_next_);
     910             : #endif
     911   269111182 : }
     912             : 
     913             : #ifdef DEBUG
     914             : void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
     915             :   // Most tokens should not have literal_chars or even raw_literal chars.
     916             :   // The rules are:
     917             :   // - UNINITIALIZED: we don't care.
     918             :   // - TEMPLATE_*: need both literal + raw literal chars.
     919             :   // - IDENTIFIERS, STRINGS, etc.: need a literal, but no raw literal.
     920             :   // - all others: should have neither.
     921             :   // Furthermore, only TEMPLATE_* tokens can have a
     922             :   // invalid_template_escape_message.
     923             : 
     924             :   switch (token.token) {
     925             :     case Token::UNINITIALIZED:
     926             :       // token.literal_chars & other members might be garbage. That's ok.
     927             :       break;
     928             :     case Token::TEMPLATE_SPAN:
     929             :     case Token::TEMPLATE_TAIL:
     930             :       DCHECK_NOT_NULL(token.raw_literal_chars);
     931             :       DCHECK_NOT_NULL(token.literal_chars);
     932             :       break;
     933             :     case Token::ESCAPED_KEYWORD:
     934             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     935             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     936             :     case Token::IDENTIFIER:
     937             :     case Token::NUMBER:
     938             :     case Token::BIGINT:
     939             :     case Token::REGEXP_LITERAL:
     940             :     case Token::SMI:
     941             :     case Token::STRING:
     942             :       DCHECK_NOT_NULL(token.literal_chars);
     943             :       DCHECK_NULL(token.raw_literal_chars);
     944             :       DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
     945             :       break;
     946             :     default:
     947             :       DCHECK_NULL(token.literal_chars);
     948             :       DCHECK_NULL(token.raw_literal_chars);
     949             :       DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
     950             :       break;
     951             :   }
     952             : 
     953             :   DCHECK_IMPLIES(token.token != Token::IDENTIFIER,
     954             :                  token.contextual_token == Token::UNINITIALIZED);
     955             :   DCHECK_IMPLIES(token.contextual_token != Token::UNINITIALIZED,
     956             :                  token.token == Token::IDENTIFIER &&
     957             :                      Token::IsContextualKeyword(token.contextual_token));
     958             :   DCHECK(!Token::IsContextualKeyword(token.token));
     959             : }
     960             : #endif  // DEBUG
     961             : 
     962       70932 : void Scanner::SeekForward(int pos) {
     963             :   // After this call, we will have the token at the given position as
     964             :   // the "next" token. The "current" token will be invalid.
     965       70942 :   if (pos == next_.location.beg_pos) return;
     966             :   int current_pos = source_pos();
     967             :   DCHECK_EQ(next_.location.end_pos, current_pos);
     968             :   // Positions inside the lookahead token aren't supported.
     969             :   DCHECK(pos >= current_pos);
     970       35461 :   if (pos != current_pos) {
     971       35456 :     source_->Seek(pos);
     972       35456 :     Advance();
     973             :     // This function is only called to seek to the location
     974             :     // of the end of a function (at the "}" token). It doesn't matter
     975             :     // whether there was a line terminator in the part we skip.
     976       35456 :     has_line_terminator_before_next_ = false;
     977       35456 :     has_multiline_comment_before_next_ = false;
     978             :   }
     979       35461 :   Scan();
     980             : }
     981             : 
     982             : 
     983             : template <bool capture_raw, bool in_template_literal>
     984    37724623 : bool Scanner::ScanEscape() {
     985    18878359 :   uc32 c = c0_;
     986    18878359 :   Advance<capture_raw>();
     987             : 
     988             :   // Skip escaped newlines.
     989    37706736 :   if (!in_template_literal && c0_ != kEndOfInput && IsLineTerminator(c)) {
     990             :     // Allow escaped CR+LF newlines in multiline string literals.
     991       10999 :     if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
     992             :     return true;
     993             :   }
     994             : 
     995    18867360 :   switch (c) {
     996             :     case '\'':  // fall through
     997             :     case '"' :  // fall through
     998             :     case '\\': break;
     999          47 :     case 'b' : c = '\b'; break;
    1000          91 :     case 'f' : c = '\f'; break;
    1001      585034 :     case 'n' : c = '\n'; break;
    1002         631 :     case 'r' : c = '\r'; break;
    1003         322 :     case 't' : c = '\t'; break;
    1004             :     case 'u' : {
    1005       68270 :       c = ScanUnicodeEscape<capture_raw>();
    1006       68270 :       if (c < 0) return false;
    1007             :       break;
    1008             :     }
    1009             :     case 'v':
    1010             :       c = '\v';
    1011          43 :       break;
    1012             :     case 'x': {
    1013    18085453 :       c = ScanHexNumber<capture_raw>(2);
    1014    18085453 :       if (c < 0) return false;
    1015             :       break;
    1016             :     }
    1017             :     case '0':  // Fall through.
    1018             :     case '1':  // fall through
    1019             :     case '2':  // fall through
    1020             :     case '3':  // fall through
    1021             :     case '4':  // fall through
    1022             :     case '5':  // fall through
    1023             :     case '6':  // fall through
    1024             :     case '7':
    1025        5674 :       c = ScanOctalEscape<capture_raw>(c, 2);
    1026        5674 :       break;
    1027             :   }
    1028             : 
    1029             :   // Other escaped characters are interpreted as their non-escaped version.
    1030             :   AddLiteralChar(c);
    1031             :   return true;
    1032             : }
    1033             : 
    1034             : 
    1035             : template <bool capture_raw>
    1036       11061 : uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
    1037        5674 :   uc32 x = c - '0';
    1038             :   int i = 0;
    1039        8766 :   for (; i < length; i++) {
    1040        8178 :     int d = c0_ - '0';
    1041        8178 :     if (d < 0 || d > 7) break;
    1042        3110 :     int nx = x * 8 + d;
    1043        3110 :     if (nx >= 256) break;
    1044             :     x = nx;
    1045        3092 :     Advance<capture_raw>();
    1046             :   }
    1047             :   // Anything except '\0' is an octal escape sequence, illegal in strict mode.
    1048             :   // Remember the position of octal escape sequences so that an error
    1049             :   // can be reported later (in strict mode).
    1050             :   // We don't report the error immediately, because the octal escape can
    1051             :   // occur before the "use strict" directive.
    1052        5674 :   if (c != '0' || i > 0 || c0_ == '8' || c0_ == '9') {
    1053        5387 :     octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
    1054        5387 :     octal_message_ = MessageTemplate::kStrictOctalEscape;
    1055             :   }
    1056        5674 :   return x;
    1057             : }
    1058             : 
    1059             : 
    1060   336381459 : Token::Value Scanner::ScanString() {
    1061    10890648 :   uc32 quote = c0_;
    1062             :   Advance<false, false>();  // consume quote
    1063             : 
    1064             :   LiteralScope literal(this);
    1065             :   while (true) {
    1066   161235859 :     if (c0_ > kMaxAscii) {
    1067       14021 :       HandleLeadSurrogate();
    1068       14021 :       break;
    1069             :     }
    1070   161221838 :     if (c0_ == kEndOfInput || c0_ == '\n' || c0_ == '\r') return Token::ILLEGAL;
    1071   161221715 :     if (c0_ == quote) {
    1072             :       literal.Complete();
    1073             :       Advance<false, false>();
    1074    10187677 :       return Token::STRING;
    1075             :     }
    1076   151034037 :     char c = static_cast<char>(c0_);
    1077   151034037 :     if (c == '\\') break;
    1078             :     Advance<false, false>();
    1079             :     AddLiteralChar(c);
    1080             :   }
    1081             : 
    1082    45852011 :   while (c0_ != quote && c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
    1083    22575410 :     uc32 c = c0_;
    1084    22575410 :     Advance();
    1085    22575410 :     if (c == '\\') {
    1086    18853377 :       if (c0_ == kEndOfInput || !ScanEscape<false, false>()) {
    1087             :         return Token::ILLEGAL;
    1088             :       }
    1089             :     } else {
    1090             :       AddLiteralChar(c);
    1091             :     }
    1092             :   }
    1093      701181 :   if (c0_ != quote) return Token::ILLEGAL;
    1094             :   literal.Complete();
    1095             : 
    1096      701171 :   Advance();  // consume quote
    1097      701171 :   return Token::STRING;
    1098             : }
    1099             : 
    1100             : 
    1101     1677156 : Token::Value Scanner::ScanTemplateSpan() {
    1102             :   // When scanning a TemplateSpan, we are looking for the following construct:
    1103             :   // TEMPLATE_SPAN ::
    1104             :   //     ` LiteralChars* ${
    1105             :   //   | } LiteralChars* ${
    1106             :   //
    1107             :   // TEMPLATE_TAIL ::
    1108             :   //     ` LiteralChars* `
    1109             :   //   | } LiteralChar* `
    1110             :   //
    1111             :   // A TEMPLATE_SPAN should always be followed by an Expression, while a
    1112             :   // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
    1113             :   // followed by an Expression.
    1114             : 
    1115             :   // These scoped helpers save and restore the original error state, so that we
    1116             :   // can specially treat invalid escape sequences in templates (which are
    1117             :   // handled by the parser).
    1118      137771 :   ErrorState scanner_error_state(&scanner_error_, &scanner_error_location_);
    1119      137771 :   ErrorState octal_error_state(&octal_message_, &octal_pos_);
    1120             : 
    1121             :   Token::Value result = Token::TEMPLATE_SPAN;
    1122             :   LiteralScope literal(this);
    1123             :   StartRawLiteral();
    1124             :   const bool capture_raw = true;
    1125             :   const bool in_template_literal = true;
    1126             :   while (true) {
    1127     1426003 :     uc32 c = c0_;
    1128     1426003 :     Advance<capture_raw>();
    1129     1426003 :     if (c == '`') {
    1130             :       result = Token::TEMPLATE_TAIL;
    1131             :       ReduceRawLiteralLength(1);
    1132             :       break;
    1133     1368525 :     } else if (c == '$' && c0_ == '{') {
    1134       78785 :       Advance<capture_raw>();  // Consume '{'
    1135             :       ReduceRawLiteralLength(2);
    1136             :       break;
    1137     1289740 :     } else if (c == '\\') {
    1138       50160 :       if (c0_ != kEndOfInput && IsLineTerminator(c0_)) {
    1139             :         // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
    1140             :         // code unit sequence.
    1141          94 :         uc32 lastChar = c0_;
    1142          94 :         Advance<capture_raw>();
    1143          94 :         if (lastChar == '\r') {
    1144             :           ReduceRawLiteralLength(1);  // Remove \r
    1145          56 :           if (c0_ == '\n') {
    1146          28 :             Advance<capture_raw>();  // Adds \n
    1147             :           } else {
    1148             :             AddRawLiteralChar('\n');
    1149             :           }
    1150             :         }
    1151             :       } else {
    1152       24991 :         bool success = ScanEscape<capture_raw, in_template_literal>();
    1153             :         USE(success);
    1154             :         DCHECK_EQ(!success, has_error());
    1155             :         // For templates, invalid escape sequence checking is handled in the
    1156             :         // parser.
    1157             :         scanner_error_state.MoveErrorTo(&next_);
    1158             :         octal_error_state.MoveErrorTo(&next_);
    1159             :       }
    1160     1264655 :     } else if (c < 0) {
    1161             :       // Unterminated template literal
    1162             :       PushBack(c);
    1163             :       break;
    1164             :     } else {
    1165             :       // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
    1166             :       // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
    1167             :       // consisting of the CV 0x000A.
    1168     1263147 :       if (c == '\r') {
    1169             :         ReduceRawLiteralLength(1);  // Remove \r
    1170         570 :         if (c0_ == '\n') {
    1171         528 :           Advance<capture_raw>();  // Adds \n
    1172             :         } else {
    1173             :           AddRawLiteralChar('\n');
    1174             :         }
    1175             :         c = '\n';
    1176             :       }
    1177             :       AddLiteralChar(c);
    1178             :     }
    1179             :   }
    1180             :   literal.Complete();
    1181      137771 :   next_.location.end_pos = source_pos();
    1182      137771 :   next_.token = result;
    1183      137771 :   next_.contextual_token = Token::UNINITIALIZED;
    1184             : 
    1185      137771 :   return result;
    1186             : }
    1187             : 
    1188             : 
    1189       70715 : Token::Value Scanner::ScanTemplateStart() {
    1190             :   DCHECK_EQ(next_next_.token, Token::UNINITIALIZED);
    1191             :   DCHECK_EQ(c0_, '`');
    1192       70715 :   next_.location.beg_pos = source_pos();
    1193       70715 :   Advance();  // Consume `
    1194       70715 :   return ScanTemplateSpan();
    1195             : }
    1196             : 
    1197     1678478 : Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
    1198             :   Handle<String> tmp;
    1199     3356956 :   if (source_url_.length() > 0) tmp = source_url_.Internalize(isolate);
    1200     1678478 :   return tmp;
    1201             : }
    1202             : 
    1203     1678476 : Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const {
    1204             :   Handle<String> tmp;
    1205     3356952 :   if (source_mapping_url_.length() > 0)
    1206         100 :     tmp = source_mapping_url_.Internalize(isolate);
    1207     1678476 :   return tmp;
    1208             : }
    1209             : 
    1210           0 : void Scanner::ScanDecimalDigits() {
    1211     8558468 :   while (IsDecimalDigit(c0_))
    1212     1772850 :     AddLiteralCharAdvance();
    1213           0 : }
    1214             : 
    1215             : 
    1216   168234930 : Token::Value Scanner::ScanNumber(bool seen_period) {
    1217             :   DCHECK(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
    1218             : 
    1219             :   enum {
    1220             :     DECIMAL,
    1221             :     DECIMAL_WITH_LEADING_ZERO,
    1222             :     HEX,
    1223             :     OCTAL,
    1224             :     IMPLICIT_OCTAL,
    1225             :     BINARY
    1226             :   } kind = DECIMAL;
    1227             : 
    1228             :   LiteralScope literal(this);
    1229    29535133 :   bool at_start = !seen_period;
    1230             :   int start_pos = source_pos();  // For reporting octal positions.
    1231    29535133 :   if (seen_period) {
    1232             :     // we have already seen a decimal point of the float
    1233             :     AddLiteralChar('.');
    1234             :     ScanDecimalDigits();  // we know we have at least one digit
    1235             : 
    1236             :   } else {
    1237             :     // if the first character is '0' we must check for octals and hex
    1238    29532140 :     if (c0_ == '0') {
    1239    11459899 :       AddLiteralCharAdvance();
    1240             : 
    1241             :       // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
    1242             :       // an octal number.
    1243    11459899 :       if (c0_ == 'x' || c0_ == 'X') {
    1244             :         // hex number
    1245             :         kind = HEX;
    1246      228713 :         AddLiteralCharAdvance();
    1247      457426 :         if (!IsHexDigit(c0_)) {
    1248             :           // we must have at least one hex digit after 'x'/'X'
    1249             :           return Token::ILLEGAL;
    1250             :         }
    1251     1541530 :         while (IsHexDigit(c0_)) {
    1252      542064 :           AddLiteralCharAdvance();
    1253             :         }
    1254    11231186 :       } else if (c0_ == 'o' || c0_ == 'O') {
    1255             :         kind = OCTAL;
    1256          81 :         AddLiteralCharAdvance();
    1257         162 :         if (!IsOctalDigit(c0_)) {
    1258             :           // we must have at least one octal digit after 'o'/'O'
    1259             :           return Token::ILLEGAL;
    1260             :         }
    1261         420 :         while (IsOctalDigit(c0_)) {
    1262         138 :           AddLiteralCharAdvance();
    1263             :         }
    1264    11231105 :       } else if (c0_ == 'b' || c0_ == 'B') {
    1265             :         kind = BINARY;
    1266          71 :         AddLiteralCharAdvance();
    1267         142 :         if (!IsBinaryDigit(c0_)) {
    1268             :           // we must have at least one binary digit after 'b'/'B'
    1269             :           return Token::ILLEGAL;
    1270             :         }
    1271         420 :         while (IsBinaryDigit(c0_)) {
    1272         148 :           AddLiteralCharAdvance();
    1273             :         }
    1274    11373317 :       } else if ('0' <= c0_ && c0_ <= '7') {
    1275             :         // (possible) octal number
    1276             :         kind = IMPLICIT_OCTAL;
    1277             :         while (true) {
    1278      284033 :           if (c0_ == '8' || c0_ == '9') {
    1279             :             at_start = false;
    1280             :             kind = DECIMAL_WITH_LEADING_ZERO;
    1281             :             break;
    1282             :           }
    1283      284027 :           if (c0_  < '0' || '7'  < c0_) {
    1284             :             // Octal literal finished.
    1285      141744 :             octal_pos_ = Location(start_pos, source_pos());
    1286      141744 :             octal_message_ = MessageTemplate::kStrictOctalLiteral;
    1287      141744 :             break;
    1288             :           }
    1289      142283 :           AddLiteralCharAdvance();
    1290             :         }
    1291    11089284 :       } else if (c0_ == '8' || c0_ == '9') {
    1292             :         kind = DECIMAL_WITH_LEADING_ZERO;
    1293             :       }
    1294             :     }
    1295             : 
    1296             :     // Parse decimal digits and allow trailing fractional part.
    1297    29532110 :     if (kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO) {
    1298    29161528 :       if (at_start) {
    1299             :         uint64_t value = 0;
    1300   165629966 :         while (IsDecimalDigit(c0_)) {
    1301    53653458 :           value = 10 * value + (c0_ - '0');
    1302             : 
    1303             :           uc32 first_char = c0_;
    1304             :           Advance<false, false>();
    1305             :           AddLiteralChar(first_char);
    1306             :         }
    1307             : 
    1308    87453759 :         if (next_.literal_chars->one_byte_literal().length() <= 10 &&
    1309    58186451 :             value <= Smi::kMaxValue && c0_ != '.' &&
    1310    55542282 :             (c0_ == kEndOfInput || !unicode_cache_->IsIdentifierStart(c0_))) {
    1311    27854418 :           next_.smi_value_ = static_cast<uint32_t>(value);
    1312             :           literal.Complete();
    1313    27854418 :           HandleLeadSurrogate();
    1314             : 
    1315    27854417 :           if (kind == DECIMAL_WITH_LEADING_ZERO) {
    1316       35308 :             octal_pos_ = Location(start_pos, source_pos());
    1317       35308 :             octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
    1318             :           }
    1319             :           return Token::SMI;
    1320             :         }
    1321     1307107 :         HandleLeadSurrogate();
    1322             :       }
    1323             : 
    1324             :       ScanDecimalDigits();  // optional
    1325     1307113 :       if (c0_ == '.') {
    1326             :         seen_period = true;
    1327     1181088 :         AddLiteralCharAdvance();
    1328             :         ScanDecimalDigits();  // optional
    1329             :       }
    1330             :     }
    1331             :   }
    1332             : 
    1333             :   bool is_bigint = false;
    1334     3361419 :   if (allow_harmony_bigint() && c0_ == 'n' && !seen_period &&
    1335          71 :       (kind == DECIMAL || kind == HEX || kind == OCTAL || kind == BINARY)) {
    1336             :     is_bigint = true;
    1337          25 :     Advance();
    1338     1680663 :   } else if (c0_ == 'e' || c0_ == 'E') {
    1339             :     // scan exponent, if any
    1340             :     DCHECK(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
    1341       15220 :     if (!(kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO))
    1342             :       return Token::ILLEGAL;
    1343             :     // scan exponent
    1344       15220 :     AddLiteralCharAdvance();
    1345       15220 :     if (c0_ == '+' || c0_ == '-')
    1346        9190 :       AddLiteralCharAdvance();
    1347       30436 :     if (!IsDecimalDigit(c0_)) {
    1348             :       // we must have at least one decimal digit after 'e'/'E'
    1349             :       return Token::ILLEGAL;
    1350             :     }
    1351             :     ScanDecimalDigits();
    1352             :   }
    1353             : 
    1354             :   // The source character immediately following a numeric literal must
    1355             :   // not be an identifier start or a decimal digit; see ECMA-262
    1356             :   // section 7.8.3, page 17 (note that we read only one decimal digit
    1357             :   // if the value is 0).
    1358     5041974 :   if (IsDecimalDigit(c0_) ||
    1359     3332774 :       (c0_ != kEndOfInput && unicode_cache_->IsIdentifierStart(c0_)))
    1360             :     return Token::ILLEGAL;
    1361             : 
    1362             :   literal.Complete();
    1363             : 
    1364     1680033 :   if (kind == DECIMAL_WITH_LEADING_ZERO) {
    1365           6 :     octal_pos_ = Location(start_pos, source_pos());
    1366           6 :     octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
    1367             :   }
    1368     1680033 :   return is_bigint ? Token::BIGINT : Token::NUMBER;
    1369             : }
    1370             : 
    1371             : 
    1372       15970 : uc32 Scanner::ScanIdentifierUnicodeEscape() {
    1373       15970 :   Advance();
    1374       15970 :   if (c0_ != 'u') return -1;
    1375       15640 :   Advance();
    1376       15640 :   return ScanUnicodeEscape<false>();
    1377             : }
    1378             : 
    1379             : 
    1380             : template <bool capture_raw>
    1381      103055 : uc32 Scanner::ScanUnicodeEscape() {
    1382             :   // Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
    1383             :   // hex digits between { } is arbitrary. \ and u have already been read.
    1384       83910 :   if (c0_ == '{') {
    1385       37256 :     int begin = source_pos() - 2;
    1386       37256 :     Advance<capture_raw>();
    1387       37256 :     uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff, begin);
    1388       37256 :     if (cp < 0 || c0_ != '}') {
    1389             :       ReportScannerError(source_pos(),
    1390             :                          MessageTemplate::kInvalidUnicodeEscapeSequence);
    1391             :       return -1;
    1392             :     }
    1393       27016 :     Advance<capture_raw>();
    1394       27016 :     return cp;
    1395             :   }
    1396             :   const bool unicode = true;
    1397       46654 :   return ScanHexNumber<capture_raw, unicode>(4);
    1398             : }
    1399             : 
    1400             : 
    1401             : // ----------------------------------------------------------------------------
    1402             : // Keyword Matcher
    1403             : 
    1404             : #define KEYWORDS(KEYWORD_GROUP, KEYWORD)                    \
    1405             :   KEYWORD_GROUP('a')                                        \
    1406             :   KEYWORD("arguments", Token::ARGUMENTS)                    \
    1407             :   KEYWORD("as", Token::AS)                                  \
    1408             :   KEYWORD("async", Token::ASYNC)                            \
    1409             :   KEYWORD("await", Token::AWAIT)                            \
    1410             :   KEYWORD("anonymous", Token::ANONYMOUS)                    \
    1411             :   KEYWORD_GROUP('b')                                        \
    1412             :   KEYWORD("break", Token::BREAK)                            \
    1413             :   KEYWORD_GROUP('c')                                        \
    1414             :   KEYWORD("case", Token::CASE)                              \
    1415             :   KEYWORD("catch", Token::CATCH)                            \
    1416             :   KEYWORD("class", Token::CLASS)                            \
    1417             :   KEYWORD("const", Token::CONST)                            \
    1418             :   KEYWORD("constructor", Token::CONSTRUCTOR)                \
    1419             :   KEYWORD("continue", Token::CONTINUE)                      \
    1420             :   KEYWORD_GROUP('d')                                        \
    1421             :   KEYWORD("debugger", Token::DEBUGGER)                      \
    1422             :   KEYWORD("default", Token::DEFAULT)                        \
    1423             :   KEYWORD("delete", Token::DELETE)                          \
    1424             :   KEYWORD("do", Token::DO)                                  \
    1425             :   KEYWORD_GROUP('e')                                        \
    1426             :   KEYWORD("else", Token::ELSE)                              \
    1427             :   KEYWORD("enum", Token::ENUM)                              \
    1428             :   KEYWORD("eval", Token::EVAL)                              \
    1429             :   KEYWORD("export", Token::EXPORT)                          \
    1430             :   KEYWORD("extends", Token::EXTENDS)                        \
    1431             :   KEYWORD_GROUP('f')                                        \
    1432             :   KEYWORD("false", Token::FALSE_LITERAL)                    \
    1433             :   KEYWORD("finally", Token::FINALLY)                        \
    1434             :   KEYWORD("for", Token::FOR)                                \
    1435             :   KEYWORD("from", Token::FROM)                              \
    1436             :   KEYWORD("function", Token::FUNCTION)                      \
    1437             :   KEYWORD_GROUP('g')                                        \
    1438             :   KEYWORD("get", Token::GET)                                \
    1439             :   KEYWORD_GROUP('i')                                        \
    1440             :   KEYWORD("if", Token::IF)                                  \
    1441             :   KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
    1442             :   KEYWORD("import", Token::IMPORT)                          \
    1443             :   KEYWORD("in", Token::IN)                                  \
    1444             :   KEYWORD("instanceof", Token::INSTANCEOF)                  \
    1445             :   KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD)  \
    1446             :   KEYWORD_GROUP('l')                                        \
    1447             :   KEYWORD("let", Token::LET)                                \
    1448             :   KEYWORD_GROUP('m')                                        \
    1449             :   KEYWORD("meta", Token::META)                              \
    1450             :   KEYWORD_GROUP('n')                                        \
    1451             :   KEYWORD("name", Token::NAME)                              \
    1452             :   KEYWORD("new", Token::NEW)                                \
    1453             :   KEYWORD("null", Token::NULL_LITERAL)                      \
    1454             :   KEYWORD_GROUP('o')                                        \
    1455             :   KEYWORD("of", Token::OF)                                  \
    1456             :   KEYWORD_GROUP('p')                                        \
    1457             :   KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD)    \
    1458             :   KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD)    \
    1459             :   KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD)  \
    1460             :   KEYWORD("prototype", Token::PROTOTYPE)                    \
    1461             :   KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD)     \
    1462             :   KEYWORD_GROUP('r')                                        \
    1463             :   KEYWORD("return", Token::RETURN)                          \
    1464             :   KEYWORD_GROUP('s')                                        \
    1465             :   KEYWORD("sent", Token::SENT)                              \
    1466             :   KEYWORD("set", Token::SET)                                \
    1467             :   KEYWORD("static", Token::STATIC)                          \
    1468             :   KEYWORD("super", Token::SUPER)                            \
    1469             :   KEYWORD("switch", Token::SWITCH)                          \
    1470             :   KEYWORD_GROUP('t')                                        \
    1471             :   KEYWORD("target", Token::TARGET)                          \
    1472             :   KEYWORD("this", Token::THIS)                              \
    1473             :   KEYWORD("throw", Token::THROW)                            \
    1474             :   KEYWORD("true", Token::TRUE_LITERAL)                      \
    1475             :   KEYWORD("try", Token::TRY)                                \
    1476             :   KEYWORD("typeof", Token::TYPEOF)                          \
    1477             :   KEYWORD_GROUP('u')                                        \
    1478             :   KEYWORD("undefined", Token::UNDEFINED)                    \
    1479             :   KEYWORD_GROUP('v')                                        \
    1480             :   KEYWORD("var", Token::VAR)                                \
    1481             :   KEYWORD("void", Token::VOID)                              \
    1482             :   KEYWORD_GROUP('w')                                        \
    1483             :   KEYWORD("while", Token::WHILE)                            \
    1484             :   KEYWORD("with", Token::WITH)                              \
    1485             :   KEYWORD_GROUP('y')                                        \
    1486             :   KEYWORD("yield", Token::YIELD)                            \
    1487             :   KEYWORD_GROUP('_')                                        \
    1488             :   KEYWORD("__proto__", Token::PROTO_UNDERSCORED)
    1489             : 
    1490   103459274 : static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
    1491             :                                              int input_length) {
    1492             :   DCHECK_GE(input_length, 1);
    1493             :   const int kMinLength = 2;
    1494             :   const int kMaxLength = 11;
    1495   103459274 :   if (input_length < kMinLength || input_length > kMaxLength) {
    1496             :     return Token::IDENTIFIER;
    1497             :   }
    1498    86427967 :   switch (input[0]) {
    1499             :     default:
    1500             : #define KEYWORD_GROUP_CASE(ch)                                \
    1501             :       break;                                                  \
    1502             :     case ch:
    1503             : #define KEYWORD(keyword, token)                                           \
    1504             :   {                                                                       \
    1505             :     /* 'keyword' is a char array, so sizeof(keyword) is */                \
    1506             :     /* strlen(keyword) plus 1 for the NUL char. */                        \
    1507             :     const int keyword_length = sizeof(keyword) - 1;                       \
    1508             :     STATIC_ASSERT(keyword_length >= kMinLength);                          \
    1509             :     STATIC_ASSERT(keyword_length <= kMaxLength);                          \
    1510             :     DCHECK_EQ(input[0], keyword[0]);                                      \
    1511             :     DCHECK(token == Token::FUTURE_STRICT_RESERVED_WORD ||                 \
    1512             :            0 == strncmp(keyword, Token::String(token), sizeof(keyword))); \
    1513             :     if (input_length == keyword_length && input[1] == keyword[1] &&       \
    1514             :         (keyword_length <= 2 || input[2] == keyword[2]) &&                \
    1515             :         (keyword_length <= 3 || input[3] == keyword[3]) &&                \
    1516             :         (keyword_length <= 4 || input[4] == keyword[4]) &&                \
    1517             :         (keyword_length <= 5 || input[5] == keyword[5]) &&                \
    1518             :         (keyword_length <= 6 || input[6] == keyword[6]) &&                \
    1519             :         (keyword_length <= 7 || input[7] == keyword[7]) &&                \
    1520             :         (keyword_length <= 8 || input[8] == keyword[8]) &&                \
    1521             :         (keyword_length <= 9 || input[9] == keyword[9]) &&                \
    1522             :         (keyword_length <= 10 || input[10] == keyword[10])) {             \
    1523             :       return token;                                                       \
    1524             :     }                                                                     \
    1525             :   }
    1526     2575394 :       KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
    1527             :   }
    1528    41862043 :   return Token::IDENTIFIER;
    1529             : }
    1530             : 
    1531             : 
    1532  1897250098 : Token::Value Scanner::ScanIdentifierOrKeyword() {
    1533             :   DCHECK(unicode_cache_->IsIdentifierStart(c0_));
    1534             :   LiteralScope literal(this);
    1535   283300734 :   if (IsInRange(c0_, 'a', 'z') || c0_ == '_') {
    1536   602307269 :     do {
    1537   602307098 :       char first_char = static_cast<char>(c0_);
    1538             :       Advance<false, false>();
    1539             :       AddLiteralChar(first_char);
    1540  1204614538 :     } while (IsInRange(c0_, 'a', 'z') || c0_ == '_');
    1541             : 
    1542   249358170 :     if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' ||
    1543             :         c0_ == '$') {
    1544             :       // Identifier starting with lowercase.
    1545    24445634 :       char first_char = static_cast<char>(c0_);
    1546             :       Advance<false, false>();
    1547             :       AddLiteralChar(first_char);
    1548   294804102 :       while (IsAsciiIdentifier(c0_)) {
    1549   122956417 :         char first_char = static_cast<char>(c0_);
    1550             :         Advance<false, false>();
    1551             :         AddLiteralChar(first_char);
    1552             :       }
    1553    24445634 :       if (c0_ <= kMaxAscii && c0_ != '\\') {
    1554             :         literal.Complete();
    1555    24445636 :         return Token::IDENTIFIER;
    1556             :       }
    1557   103458040 :     } else if (c0_ <= kMaxAscii && c0_ != '\\') {
    1558             :       // Only a-z+ or _: could be a keyword or identifier.
    1559   103445080 :       Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1560             :       Token::Value token =
    1561   103444535 :           KeywordOrIdentifierToken(chars.start(), chars.length());
    1562   206889086 :       if (token == Token::IDENTIFIER ||
    1563   147965980 :           token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1564             :           Token::IsContextualKeyword(token))
    1565             :         literal.Complete();
    1566             :       return token;
    1567             :     }
    1568             : 
    1569       13503 :     HandleLeadSurrogate();
    1570    13746864 :   } else if (IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') {
    1571   128089118 :     do {
    1572   128089116 :       char first_char = static_cast<char>(c0_);
    1573             :       Advance<false, false>();
    1574             :       AddLiteralChar(first_char);
    1575   128089118 :     } while (IsAsciiIdentifier(c0_));
    1576             : 
    1577    13743962 :     if (c0_ <= kMaxAscii && c0_ != '\\') {
    1578             :       literal.Complete();
    1579    13743915 :       return Token::IDENTIFIER;
    1580             :     }
    1581             : 
    1582          47 :     HandleLeadSurrogate();
    1583        2904 :   } else if (c0_ == '\\') {
    1584             :     // Scan identifier start character.
    1585        2712 :     uc32 c = ScanIdentifierUnicodeEscape();
    1586             :     // Only allow legal identifier start characters.
    1587        8136 :     if (c < 0 ||
    1588        7786 :         c == '\\' ||  // No recursive escapes.
    1589        2362 :         !unicode_cache_->IsIdentifierStart(c)) {
    1590             :       return Token::ILLEGAL;
    1591             :     }
    1592             :     AddLiteralChar(c);
    1593        2323 :     return ScanIdentifierSuffix(&literal, true);
    1594             :   } else {
    1595             :     uc32 first_char = c0_;
    1596         192 :     Advance();
    1597             :     AddLiteralChar(first_char);
    1598             :   }
    1599             : 
    1600             :   // Scan the rest of the identifier characters.
    1601       28610 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1602       13814 :     if (c0_ != '\\') {
    1603             :       uc32 next_char = c0_;
    1604         616 :       Advance();
    1605             :       AddLiteralChar(next_char);
    1606             :       continue;
    1607             :     }
    1608             :     // Fallthrough if no longer able to complete keyword.
    1609       13198 :     return ScanIdentifierSuffix(&literal, false);
    1610             :   }
    1611             : 
    1612        1090 :   if (next_.literal_chars->is_one_byte()) {
    1613             :     Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1614             :     Token::Value token =
    1615         124 :         KeywordOrIdentifierToken(chars.start(), chars.length());
    1616         248 :     if (token == Token::IDENTIFIER ||
    1617         124 :         token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1618             :         Token::IsContextualKeyword(token))
    1619             :       literal.Complete();
    1620             :     return token;
    1621             :   }
    1622             :   literal.Complete();
    1623         421 :   return Token::IDENTIFIER;
    1624             : }
    1625             : 
    1626             : 
    1627       15521 : Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal,
    1628       52937 :                                            bool escaped) {
    1629             :   // Scan the rest of the identifier characters.
    1630      152177 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1631       53515 :     if (c0_ == '\\') {
    1632       13258 :       uc32 c = ScanIdentifierUnicodeEscape();
    1633             :       escaped = true;
    1634             :       // Only allow legal identifier part characters.
    1635       39774 :       if (c < 0 ||
    1636       39214 :           c == '\\' ||
    1637       12698 :           !unicode_cache_->IsIdentifierPart(c)) {
    1638             :         return Token::ILLEGAL;
    1639             :       }
    1640             :       AddLiteralChar(c);
    1641             :     } else {
    1642             :       AddLiteralChar(c0_);
    1643       40257 :       Advance();
    1644             :     }
    1645             :   }
    1646             :   literal->Complete();
    1647             : 
    1648       14943 :   if (escaped && next_.literal_chars->is_one_byte()) {
    1649       14608 :     Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
    1650             :     Token::Value token =
    1651       14608 :         KeywordOrIdentifierToken(chars.start(), chars.length());
    1652             :     /* TODO(adamk): YIELD should be handled specially. */
    1653       28365 :     if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) {
    1654             :       return token;
    1655       26914 :     } else if (token == Token::FUTURE_STRICT_RESERVED_WORD ||
    1656       23502 :                token == Token::LET || token == Token::STATIC) {
    1657             :       return Token::ESCAPED_STRICT_RESERVED_WORD;
    1658             :     } else {
    1659        7925 :       return Token::ESCAPED_KEYWORD;
    1660             :     }
    1661             :   }
    1662             :   return Token::IDENTIFIER;
    1663             : }
    1664             : 
    1665      188122 : bool Scanner::ScanRegExpPattern() {
    1666             :   DCHECK(next_next_.token == Token::UNINITIALIZED);
    1667             :   DCHECK(next_.token == Token::DIV || next_.token == Token::ASSIGN_DIV);
    1668             : 
    1669             :   // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
    1670             :   bool in_character_class = false;
    1671       94061 :   bool seen_equal = (next_.token == Token::ASSIGN_DIV);
    1672             : 
    1673             :   // Previous token is either '/' or '/=', in the second case, the
    1674             :   // pattern starts at =.
    1675       94061 :   next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
    1676       94061 :   next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
    1677             : 
    1678             :   // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
    1679             :   // the scanner should pass uninterpreted bodies to the RegExp
    1680             :   // constructor.
    1681             :   LiteralScope literal(this);
    1682       94061 :   if (seen_equal) {
    1683             :     AddLiteralChar('=');
    1684             :   }
    1685             : 
    1686      937913 :   while (c0_ != '/' || in_character_class) {
    1687     1687948 :     if (c0_ == kEndOfInput || IsLineTerminator(c0_)) {
    1688             :       return false;
    1689             :     }
    1690      843857 :     if (c0_ == '\\') {  // Escape sequence.
    1691      102166 :       AddLiteralCharAdvance();
    1692      204327 :       if (c0_ == kEndOfInput || IsLineTerminator(c0_)) {
    1693             :         return false;
    1694             :       }
    1695      102161 :       AddLiteralCharAdvance();
    1696             :       // If the escape allows more characters, i.e., \x??, \u????, or \c?,
    1697             :       // only "safe" characters are allowed (letters, digits, underscore),
    1698             :       // otherwise the escape isn't valid and the invalid character has
    1699             :       // its normal meaning. I.e., we can just continue scanning without
    1700             :       // worrying whether the following characters are part of the escape
    1701             :       // or not, since any '/', '\\' or '[' is guaranteed to not be part
    1702             :       // of the escape sequence.
    1703             : 
    1704             :       // TODO(896): At some point, parse RegExps more thoroughly to capture
    1705             :       // octal esacpes in strict mode.
    1706             :     } else {  // Unescaped character.
    1707      741691 :       if (c0_ == '[') in_character_class = true;
    1708      741691 :       if (c0_ == ']') in_character_class = false;
    1709      741691 :       AddLiteralCharAdvance();
    1710             :     }
    1711             :   }
    1712       93822 :   Advance();  // consume '/'
    1713             : 
    1714             :   literal.Complete();
    1715       93822 :   next_.token = Token::REGEXP_LITERAL;
    1716       93822 :   next_.contextual_token = Token::UNINITIALIZED;
    1717       93822 :   return true;
    1718             : }
    1719             : 
    1720             : 
    1721      186765 : Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
    1722             :   DCHECK(next_.token == Token::REGEXP_LITERAL);
    1723             : 
    1724             :   // Scan regular expression flags.
    1725             :   int flags = 0;
    1726      392441 :   while (c0_ != kEndOfInput && unicode_cache_->IsIdentifierPart(c0_)) {
    1727             :     RegExp::Flags flag = RegExp::kNone;
    1728       57049 :     switch (c0_) {
    1729             :       case 'g':
    1730             :         flag = RegExp::kGlobal;
    1731             :         break;
    1732             :       case 'i':
    1733             :         flag = RegExp::kIgnoreCase;
    1734        3937 :         break;
    1735             :       case 'm':
    1736             :         flag = RegExp::kMultiline;
    1737        6028 :         break;
    1738             :       case 's':
    1739          30 :         if (FLAG_harmony_regexp_dotall) {
    1740             :           flag = RegExp::kDotAll;
    1741             :         } else {
    1742             :           return Nothing<RegExp::Flags>();
    1743             :         }
    1744             :         break;
    1745             :       case 'u':
    1746             :         flag = RegExp::kUnicode;
    1747       16999 :         break;
    1748             :       case 'y':
    1749             :         flag = RegExp::kSticky;
    1750          91 :         break;
    1751             :       default:
    1752             :         return Nothing<RegExp::Flags>();
    1753             :     }
    1754       56529 :     if (flags & flag) {
    1755             :       return Nothing<RegExp::Flags>();
    1756             :     }
    1757       56390 :     Advance();
    1758       56390 :     flags |= flag;
    1759             :   }
    1760             : 
    1761       93053 :   next_.location.end_pos = source_pos();
    1762       93053 :   return Just(RegExp::Flags(flags));
    1763             : }
    1764             : 
    1765   113320097 : const AstRawString* Scanner::CurrentSymbol(
    1766   113320097 :     AstValueFactory* ast_value_factory) const {
    1767   113320097 :   if (is_literal_one_byte()) {
    1768   113280003 :     return ast_value_factory->GetOneByteString(literal_one_byte_string());
    1769             :   }
    1770       40270 :   return ast_value_factory->GetTwoByteString(literal_two_byte_string());
    1771             : }
    1772             : 
    1773       62607 : const AstRawString* Scanner::NextSymbol(
    1774       62607 :     AstValueFactory* ast_value_factory) const {
    1775       62607 :   if (is_next_literal_one_byte()) {
    1776       60473 :     return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
    1777             :   }
    1778        2134 :   return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
    1779             : }
    1780             : 
    1781       62557 : const AstRawString* Scanner::CurrentRawSymbol(
    1782       62557 :     AstValueFactory* ast_value_factory) const {
    1783       62557 :   if (is_raw_literal_one_byte()) {
    1784       62536 :     return ast_value_factory->GetOneByteString(raw_literal_one_byte_string());
    1785             :   }
    1786          21 :   return ast_value_factory->GetTwoByteString(raw_literal_two_byte_string());
    1787             : }
    1788             : 
    1789             : 
    1790     2633604 : double Scanner::DoubleValue() {
    1791             :   DCHECK(is_literal_one_byte());
    1792             :   return StringToDouble(
    1793             :       unicode_cache_,
    1794             :       literal_one_byte_string(),
    1795     2633604 :       ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
    1796             : }
    1797             : 
    1798          25 : const char* Scanner::CurrentLiteralAsCString(Zone* zone) const {
    1799             :   DCHECK(is_literal_one_byte());
    1800             :   Vector<const uint8_t> vector = literal_one_byte_string();
    1801             :   int length = vector.length();
    1802          25 :   char* buffer = zone->NewArray<char>(length + 1);
    1803          25 :   memcpy(buffer, vector.start(), length);
    1804          25 :   buffer[length] = '\0';
    1805          25 :   return buffer;
    1806             : }
    1807             : 
    1808     8375565 : bool Scanner::IsDuplicateSymbol(DuplicateFinder* duplicate_finder,
    1809             :                                 AstValueFactory* ast_value_factory) const {
    1810             :   DCHECK_NOT_NULL(duplicate_finder);
    1811             :   DCHECK_NOT_NULL(ast_value_factory);
    1812     8375565 :   const AstRawString* string = CurrentSymbol(ast_value_factory);
    1813    16751129 :   return !duplicate_finder->known_symbols_.insert(string).second;
    1814             : }
    1815             : 
    1816         157 : void Scanner::SeekNext(size_t position) {
    1817             :   // Use with care: This cleanly resets most, but not all scanner state.
    1818             :   // TODO(vogelheim): Fix this, or at least DCHECK the relevant conditions.
    1819             : 
    1820             :   // To re-scan from a given character position, we need to:
    1821             :   // 1, Reset the current_, next_ and next_next_ tokens
    1822             :   //    (next_ + next_next_ will be overwrittem by Next(),
    1823             :   //     current_ will remain unchanged, so overwrite it fully.)
    1824             :   current_ = {{0, 0},
    1825             :               nullptr,
    1826             :               nullptr,
    1827             :               0,
    1828             :               Token::UNINITIALIZED,
    1829             :               MessageTemplate::kNone,
    1830             :               {0, 0},
    1831         157 :               Token::UNINITIALIZED};
    1832         157 :   next_.token = Token::UNINITIALIZED;
    1833         157 :   next_.contextual_token = Token::UNINITIALIZED;
    1834         157 :   next_next_.token = Token::UNINITIALIZED;
    1835         157 :   next_next_.contextual_token = Token::UNINITIALIZED;
    1836             :   // 2, reset the source to the desired position,
    1837         157 :   source_->Seek(position);
    1838             :   // 3, re-scan, by scanning the look-ahead char + 1 token (next_).
    1839         157 :   c0_ = source_->Advance();
    1840         157 :   Next();
    1841             :   DCHECK_EQ(next_.location.beg_pos, static_cast<int>(position));
    1842         157 : }
    1843             : 
    1844             : }  // namespace internal
    1845             : }  // namespace v8

Generated by: LCOV version 1.10