v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
scanner.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 // Features shared by parsing and pre-parsing scanners.
29 
30 #include <cmath>
31 
32 #include "scanner.h"
33 
34 #include "../include/v8stdint.h"
35 #include "char-predicates-inl.h"
36 #include "conversions-inl.h"
37 #include "list-inl.h"
38 #include "v8.h"
39 #include "parser.h"
40 
41 namespace v8 {
42 namespace internal {
43 
44 // ----------------------------------------------------------------------------
45 // Scanner
46 
48  : unicode_cache_(unicode_cache),
49  octal_pos_(Location::invalid()),
50  harmony_scoping_(false),
51  harmony_modules_(false),
52  harmony_numeric_literals_(false) { }
53 
54 
56  source_ = source;
57  // Need to capture identifiers in order to recognize "get" and "set"
58  // in object literals.
59  Init();
60  // Skip initial whitespace allowing HTML comment ends just like
61  // after a newline and scan first token.
62  has_line_terminator_before_next_ = true;
63  SkipWhiteSpace();
64  Scan();
65 }
66 
67 
68 uc32 Scanner::ScanHexNumber(int expected_length) {
69  ASSERT(expected_length <= 4); // prevent overflow
70 
71  uc32 digits[4] = { 0, 0, 0, 0 };
72  uc32 x = 0;
73  for (int i = 0; i < expected_length; i++) {
74  digits[i] = c0_;
75  int d = HexValue(c0_);
76  if (d < 0) {
77  // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
78  // should be illegal, but other JS VMs just return the
79  // non-escaped version of the original character.
80 
81  // Push back digits that we have advanced past.
82  for (int j = i-1; j >= 0; j--) {
83  PushBack(digits[j]);
84  }
85  return -1;
86  }
87  x = x * 16 + d;
88  Advance();
89  }
90 
91  return x;
92 }
93 
94 
95 // Ensure that tokens can be stored in a byte.
97 
98 // Table of one-character tokens, by character (0x00..0x7f only).
99 static const byte one_char_tokens[] = {
100  Token::ILLEGAL,
101  Token::ILLEGAL,
102  Token::ILLEGAL,
103  Token::ILLEGAL,
104  Token::ILLEGAL,
105  Token::ILLEGAL,
106  Token::ILLEGAL,
107  Token::ILLEGAL,
108  Token::ILLEGAL,
109  Token::ILLEGAL,
110  Token::ILLEGAL,
111  Token::ILLEGAL,
112  Token::ILLEGAL,
113  Token::ILLEGAL,
114  Token::ILLEGAL,
115  Token::ILLEGAL,
116  Token::ILLEGAL,
117  Token::ILLEGAL,
118  Token::ILLEGAL,
119  Token::ILLEGAL,
120  Token::ILLEGAL,
121  Token::ILLEGAL,
122  Token::ILLEGAL,
123  Token::ILLEGAL,
124  Token::ILLEGAL,
125  Token::ILLEGAL,
126  Token::ILLEGAL,
127  Token::ILLEGAL,
128  Token::ILLEGAL,
129  Token::ILLEGAL,
130  Token::ILLEGAL,
131  Token::ILLEGAL,
132  Token::ILLEGAL,
133  Token::ILLEGAL,
134  Token::ILLEGAL,
135  Token::ILLEGAL,
136  Token::ILLEGAL,
137  Token::ILLEGAL,
138  Token::ILLEGAL,
139  Token::ILLEGAL,
140  Token::LPAREN, // 0x28
141  Token::RPAREN, // 0x29
142  Token::ILLEGAL,
143  Token::ILLEGAL,
144  Token::COMMA, // 0x2c
145  Token::ILLEGAL,
146  Token::ILLEGAL,
147  Token::ILLEGAL,
148  Token::ILLEGAL,
149  Token::ILLEGAL,
150  Token::ILLEGAL,
151  Token::ILLEGAL,
152  Token::ILLEGAL,
153  Token::ILLEGAL,
154  Token::ILLEGAL,
155  Token::ILLEGAL,
156  Token::ILLEGAL,
157  Token::ILLEGAL,
158  Token::COLON, // 0x3a
159  Token::SEMICOLON, // 0x3b
160  Token::ILLEGAL,
161  Token::ILLEGAL,
162  Token::ILLEGAL,
163  Token::CONDITIONAL, // 0x3f
164  Token::ILLEGAL,
165  Token::ILLEGAL,
166  Token::ILLEGAL,
167  Token::ILLEGAL,
168  Token::ILLEGAL,
169  Token::ILLEGAL,
170  Token::ILLEGAL,
171  Token::ILLEGAL,
172  Token::ILLEGAL,
173  Token::ILLEGAL,
174  Token::ILLEGAL,
175  Token::ILLEGAL,
176  Token::ILLEGAL,
177  Token::ILLEGAL,
178  Token::ILLEGAL,
179  Token::ILLEGAL,
180  Token::ILLEGAL,
181  Token::ILLEGAL,
182  Token::ILLEGAL,
183  Token::ILLEGAL,
184  Token::ILLEGAL,
185  Token::ILLEGAL,
186  Token::ILLEGAL,
187  Token::ILLEGAL,
188  Token::ILLEGAL,
189  Token::ILLEGAL,
190  Token::ILLEGAL,
191  Token::LBRACK, // 0x5b
192  Token::ILLEGAL,
193  Token::RBRACK, // 0x5d
194  Token::ILLEGAL,
195  Token::ILLEGAL,
196  Token::ILLEGAL,
197  Token::ILLEGAL,
198  Token::ILLEGAL,
199  Token::ILLEGAL,
200  Token::ILLEGAL,
201  Token::ILLEGAL,
202  Token::ILLEGAL,
203  Token::ILLEGAL,
204  Token::ILLEGAL,
205  Token::ILLEGAL,
206  Token::ILLEGAL,
207  Token::ILLEGAL,
208  Token::ILLEGAL,
209  Token::ILLEGAL,
210  Token::ILLEGAL,
211  Token::ILLEGAL,
212  Token::ILLEGAL,
213  Token::ILLEGAL,
214  Token::ILLEGAL,
215  Token::ILLEGAL,
216  Token::ILLEGAL,
217  Token::ILLEGAL,
218  Token::ILLEGAL,
219  Token::ILLEGAL,
220  Token::ILLEGAL,
221  Token::ILLEGAL,
222  Token::ILLEGAL,
223  Token::LBRACE, // 0x7b
224  Token::ILLEGAL,
225  Token::RBRACE, // 0x7d
226  Token::BIT_NOT, // 0x7e
227  Token::ILLEGAL
228 };
229 
230 
232  current_ = next_;
233  has_line_terminator_before_next_ = false;
234  has_multiline_comment_before_next_ = false;
235  if (static_cast<unsigned>(c0_) <= 0x7f) {
236  Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
237  if (token != Token::ILLEGAL) {
238  int pos = source_pos();
239  next_.token = token;
240  next_.location.beg_pos = pos;
241  next_.location.end_pos = pos + 1;
242  Advance();
243  return current_.token;
244  }
245  }
246  Scan();
247  return current_.token;
248 }
249 
250 
251 // TODO(yangguo): check whether this is actually necessary.
252 static inline bool IsLittleEndianByteOrderMark(uc32 c) {
253  // The Unicode value U+FFFE is guaranteed never to be assigned as a
254  // Unicode character; this implies that in a Unicode context the
255  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
256  // character expressed in little-endian byte order (since it could
257  // not be a U+FFFE character expressed in big-endian byte
258  // order). Nevertheless, we check for it to be compatible with
259  // Spidermonkey.
260  return c == 0xFFFE;
261 }
262 
263 
264 bool Scanner::SkipWhiteSpace() {
265  int start_position = source_pos();
266 
267  while (true) {
268  while (true) {
269  // Advance as long as character is a WhiteSpace or LineTerminator.
270  // Remember if the latter is the case.
271  if (unicode_cache_->IsLineTerminator(c0_)) {
272  has_line_terminator_before_next_ = true;
273  } else if (!unicode_cache_->IsWhiteSpace(c0_) &&
274  !IsLittleEndianByteOrderMark(c0_)) {
275  break;
276  }
277  Advance();
278  }
279 
280  // If there is an HTML comment end '-->' at the beginning of a
281  // line (with only whitespace in front of it), we treat the rest
282  // of the line as a comment. This is in line with the way
283  // SpiderMonkey handles it.
284  if (c0_ == '-' && has_line_terminator_before_next_) {
285  Advance();
286  if (c0_ == '-') {
287  Advance();
288  if (c0_ == '>') {
289  // Treat the rest of the line as a comment.
290  SkipSingleLineComment();
291  // Continue skipping white space after the comment.
292  continue;
293  }
294  PushBack('-'); // undo Advance()
295  }
296  PushBack('-'); // undo Advance()
297  }
298  // Return whether or not we skipped any characters.
299  return source_pos() != start_position;
300  }
301 }
302 
303 
304 Token::Value Scanner::SkipSingleLineComment() {
305  Advance();
306 
307  // The line terminator at the end of the line is not considered
308  // to be part of the single-line comment; it is recognized
309  // separately by the lexical grammar and becomes part of the
310  // stream of input elements for the syntactic grammar (see
311  // ECMA-262, section 7.4).
312  while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
313  Advance();
314  }
315 
316  return Token::WHITESPACE;
317 }
318 
319 
320 Token::Value Scanner::SkipMultiLineComment() {
321  ASSERT(c0_ == '*');
322  Advance();
323 
324  while (c0_ >= 0) {
325  uc32 ch = c0_;
326  Advance();
327  if (unicode_cache_->IsLineTerminator(ch)) {
328  // Following ECMA-262, section 7.4, a comment containing
329  // a newline will make the comment count as a line-terminator.
330  has_multiline_comment_before_next_ = true;
331  }
332  // If we have reached the end of the multi-line comment, we
333  // consume the '/' and insert a whitespace. This way all
334  // multi-line comments are treated as whitespace.
335  if (ch == '*' && c0_ == '/') {
336  c0_ = ' ';
337  return Token::WHITESPACE;
338  }
339  }
340 
341  // Unterminated multi-line comment.
342  return Token::ILLEGAL;
343 }
344 
345 
346 Token::Value Scanner::ScanHtmlComment() {
347  // Check for <!-- comments.
348  ASSERT(c0_ == '!');
349  Advance();
350  if (c0_ == '-') {
351  Advance();
352  if (c0_ == '-') return SkipSingleLineComment();
353  PushBack('-'); // undo Advance()
354  }
355  PushBack('!'); // undo Advance()
356  ASSERT(c0_ == '!');
357  return Token::LT;
358 }
359 
360 
361 void Scanner::Scan() {
362  next_.literal_chars = NULL;
363  Token::Value token;
364  do {
365  // Remember the position of the next token
366  next_.location.beg_pos = source_pos();
367 
368  switch (c0_) {
369  case ' ':
370  case '\t':
371  Advance();
372  token = Token::WHITESPACE;
373  break;
374 
375  case '\n':
376  Advance();
377  has_line_terminator_before_next_ = true;
378  token = Token::WHITESPACE;
379  break;
380 
381  case '"': case '\'':
382  token = ScanString();
383  break;
384 
385  case '<':
386  // < <= << <<= <!--
387  Advance();
388  if (c0_ == '=') {
389  token = Select(Token::LTE);
390  } else if (c0_ == '<') {
391  token = Select('=', Token::ASSIGN_SHL, Token::SHL);
392  } else if (c0_ == '!') {
393  token = ScanHtmlComment();
394  } else {
395  token = Token::LT;
396  }
397  break;
398 
399  case '>':
400  // > >= >> >>= >>> >>>=
401  Advance();
402  if (c0_ == '=') {
403  token = Select(Token::GTE);
404  } else if (c0_ == '>') {
405  // >> >>= >>> >>>=
406  Advance();
407  if (c0_ == '=') {
408  token = Select(Token::ASSIGN_SAR);
409  } else if (c0_ == '>') {
410  token = Select('=', Token::ASSIGN_SHR, Token::SHR);
411  } else {
412  token = Token::SAR;
413  }
414  } else {
415  token = Token::GT;
416  }
417  break;
418 
419  case '=':
420  // = == ===
421  Advance();
422  if (c0_ == '=') {
423  token = Select('=', Token::EQ_STRICT, Token::EQ);
424  } else {
425  token = Token::ASSIGN;
426  }
427  break;
428 
429  case '!':
430  // ! != !==
431  Advance();
432  if (c0_ == '=') {
433  token = Select('=', Token::NE_STRICT, Token::NE);
434  } else {
435  token = Token::NOT;
436  }
437  break;
438 
439  case '+':
440  // + ++ +=
441  Advance();
442  if (c0_ == '+') {
443  token = Select(Token::INC);
444  } else if (c0_ == '=') {
445  token = Select(Token::ASSIGN_ADD);
446  } else {
447  token = Token::ADD;
448  }
449  break;
450 
451  case '-':
452  // - -- --> -=
453  Advance();
454  if (c0_ == '-') {
455  Advance();
456  if (c0_ == '>' && has_line_terminator_before_next_) {
457  // For compatibility with SpiderMonkey, we skip lines that
458  // start with an HTML comment end '-->'.
459  token = SkipSingleLineComment();
460  } else {
461  token = Token::DEC;
462  }
463  } else if (c0_ == '=') {
464  token = Select(Token::ASSIGN_SUB);
465  } else {
466  token = Token::SUB;
467  }
468  break;
469 
470  case '*':
471  // * *=
472  token = Select('=', Token::ASSIGN_MUL, Token::MUL);
473  break;
474 
475  case '%':
476  // % %=
477  token = Select('=', Token::ASSIGN_MOD, Token::MOD);
478  break;
479 
480  case '/':
481  // / // /* /=
482  Advance();
483  if (c0_ == '/') {
484  token = SkipSingleLineComment();
485  } else if (c0_ == '*') {
486  token = SkipMultiLineComment();
487  } else if (c0_ == '=') {
488  token = Select(Token::ASSIGN_DIV);
489  } else {
490  token = Token::DIV;
491  }
492  break;
493 
494  case '&':
495  // & && &=
496  Advance();
497  if (c0_ == '&') {
498  token = Select(Token::AND);
499  } else if (c0_ == '=') {
500  token = Select(Token::ASSIGN_BIT_AND);
501  } else {
502  token = Token::BIT_AND;
503  }
504  break;
505 
506  case '|':
507  // | || |=
508  Advance();
509  if (c0_ == '|') {
510  token = Select(Token::OR);
511  } else if (c0_ == '=') {
512  token = Select(Token::ASSIGN_BIT_OR);
513  } else {
514  token = Token::BIT_OR;
515  }
516  break;
517 
518  case '^':
519  // ^ ^=
520  token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
521  break;
522 
523  case '.':
524  // . Number
525  Advance();
526  if (IsDecimalDigit(c0_)) {
527  token = ScanNumber(true);
528  } else {
529  token = Token::PERIOD;
530  }
531  break;
532 
533  case ':':
534  token = Select(Token::COLON);
535  break;
536 
537  case ';':
538  token = Select(Token::SEMICOLON);
539  break;
540 
541  case ',':
542  token = Select(Token::COMMA);
543  break;
544 
545  case '(':
546  token = Select(Token::LPAREN);
547  break;
548 
549  case ')':
550  token = Select(Token::RPAREN);
551  break;
552 
553  case '[':
554  token = Select(Token::LBRACK);
555  break;
556 
557  case ']':
558  token = Select(Token::RBRACK);
559  break;
560 
561  case '{':
562  token = Select(Token::LBRACE);
563  break;
564 
565  case '}':
566  token = Select(Token::RBRACE);
567  break;
568 
569  case '?':
570  token = Select(Token::CONDITIONAL);
571  break;
572 
573  case '~':
574  token = Select(Token::BIT_NOT);
575  break;
576 
577  default:
578  if (unicode_cache_->IsIdentifierStart(c0_)) {
579  token = ScanIdentifierOrKeyword();
580  } else if (IsDecimalDigit(c0_)) {
581  token = ScanNumber(false);
582  } else if (SkipWhiteSpace()) {
583  token = Token::WHITESPACE;
584  } else if (c0_ < 0) {
585  token = Token::EOS;
586  } else {
587  token = Select(Token::ILLEGAL);
588  }
589  break;
590  }
591 
592  // Continue scanning for tokens as long as we're just skipping
593  // whitespace.
594  } while (token == Token::WHITESPACE);
595 
596  next_.location.end_pos = source_pos();
597  next_.token = token;
598 }
599 
600 
601 void Scanner::SeekForward(int pos) {
602  // After this call, we will have the token at the given position as
603  // the "next" token. The "current" token will be invalid.
604  if (pos == next_.location.beg_pos) return;
605  int current_pos = source_pos();
606  ASSERT_EQ(next_.location.end_pos, current_pos);
607  // Positions inside the lookahead token aren't supported.
608  ASSERT(pos >= current_pos);
609  if (pos != current_pos) {
610  source_->SeekForward(pos - source_->pos());
611  Advance();
612  // This function is only called to seek to the location
613  // of the end of a function (at the "}" token). It doesn't matter
614  // whether there was a line terminator in the part we skip.
615  has_line_terminator_before_next_ = false;
616  has_multiline_comment_before_next_ = false;
617  }
618  Scan();
619 }
620 
621 
622 bool Scanner::ScanEscape() {
623  uc32 c = c0_;
624  Advance();
625 
626  // Skip escaped newlines.
627  if (unicode_cache_->IsLineTerminator(c)) {
628  // Allow CR+LF newlines in multiline string literals.
629  if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
630  // Allow LF+CR newlines in multiline string literals.
631  if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
632  return true;
633  }
634 
635  switch (c) {
636  case '\'': // fall through
637  case '"' : // fall through
638  case '\\': break;
639  case 'b' : c = '\b'; break;
640  case 'f' : c = '\f'; break;
641  case 'n' : c = '\n'; break;
642  case 'r' : c = '\r'; break;
643  case 't' : c = '\t'; break;
644  case 'u' : {
645  c = ScanHexNumber(4);
646  if (c < 0) return false;
647  break;
648  }
649  case 'v' : c = '\v'; break;
650  case 'x' : {
651  c = ScanHexNumber(2);
652  if (c < 0) return false;
653  break;
654  }
655  case '0' : // fall through
656  case '1' : // fall through
657  case '2' : // fall through
658  case '3' : // fall through
659  case '4' : // fall through
660  case '5' : // fall through
661  case '6' : // fall through
662  case '7' : c = ScanOctalEscape(c, 2); break;
663  }
664 
665  // According to ECMA-262, section 7.8.4, characters not covered by the
666  // above cases should be illegal, but they are commonly handled as
667  // non-escaped characters by JS VMs.
668  AddLiteralChar(c);
669  return true;
670 }
671 
672 
673 // Octal escapes of the forms '\0xx' and '\xxx' are not a part of
674 // ECMA-262. Other JS VMs support them.
675 uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
676  uc32 x = c - '0';
677  int i = 0;
678  for (; i < length; i++) {
679  int d = c0_ - '0';
680  if (d < 0 || d > 7) break;
681  int nx = x * 8 + d;
682  if (nx >= 256) break;
683  x = nx;
684  Advance();
685  }
686  // Anything except '\0' is an octal escape sequence, illegal in strict mode.
687  // Remember the position of octal escape sequences so that an error
688  // can be reported later (in strict mode).
689  // We don't report the error immediately, because the octal escape can
690  // occur before the "use strict" directive.
691  if (c != '0' || i > 0) {
692  octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
693  }
694  return x;
695 }
696 
697 
698 Token::Value Scanner::ScanString() {
699  uc32 quote = c0_;
700  Advance(); // consume quote
701 
702  LiteralScope literal(this);
703  while (c0_ != quote && c0_ >= 0
704  && !unicode_cache_->IsLineTerminator(c0_)) {
705  uc32 c = c0_;
706  Advance();
707  if (c == '\\') {
708  if (c0_ < 0 || !ScanEscape()) return Token::ILLEGAL;
709  } else {
710  AddLiteralChar(c);
711  }
712  }
713  if (c0_ != quote) return Token::ILLEGAL;
714  literal.Complete();
715 
716  Advance(); // consume quote
717  return Token::STRING;
718 }
719 
720 
721 void Scanner::ScanDecimalDigits() {
722  while (IsDecimalDigit(c0_))
723  AddLiteralCharAdvance();
724 }
725 
726 
727 Token::Value Scanner::ScanNumber(bool seen_period) {
728  ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction
729 
730  enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
731 
732  LiteralScope literal(this);
733  if (seen_period) {
734  // we have already seen a decimal point of the float
735  AddLiteralChar('.');
736  ScanDecimalDigits(); // we know we have at least one digit
737 
738  } else {
739  // if the first character is '0' we must check for octals and hex
740  if (c0_ == '0') {
741  int start_pos = source_pos(); // For reporting octal positions.
742  AddLiteralCharAdvance();
743 
744  // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
745  // an octal number.
746  if (c0_ == 'x' || c0_ == 'X') {
747  // hex number
748  kind = HEX;
749  AddLiteralCharAdvance();
750  if (!IsHexDigit(c0_)) {
751  // we must have at least one hex digit after 'x'/'X'
752  return Token::ILLEGAL;
753  }
754  while (IsHexDigit(c0_)) {
755  AddLiteralCharAdvance();
756  }
757  } else if (harmony_numeric_literals_ && (c0_ == 'o' || c0_ == 'O')) {
758  kind = OCTAL;
759  AddLiteralCharAdvance();
760  if (!IsOctalDigit(c0_)) {
761  // we must have at least one octal digit after 'o'/'O'
762  return Token::ILLEGAL;
763  }
764  while (IsOctalDigit(c0_)) {
765  AddLiteralCharAdvance();
766  }
767  } else if (harmony_numeric_literals_ && (c0_ == 'b' || c0_ == 'B')) {
768  kind = BINARY;
769  AddLiteralCharAdvance();
770  if (!IsBinaryDigit(c0_)) {
771  // we must have at least one binary digit after 'b'/'B'
772  return Token::ILLEGAL;
773  }
774  while (IsBinaryDigit(c0_)) {
775  AddLiteralCharAdvance();
776  }
777  } else if ('0' <= c0_ && c0_ <= '7') {
778  // (possible) octal number
779  kind = IMPLICIT_OCTAL;
780  while (true) {
781  if (c0_ == '8' || c0_ == '9') {
782  kind = DECIMAL;
783  break;
784  }
785  if (c0_ < '0' || '7' < c0_) {
786  // Octal literal finished.
787  octal_pos_ = Location(start_pos, source_pos());
788  break;
789  }
790  AddLiteralCharAdvance();
791  }
792  }
793  }
794 
795  // Parse decimal digits and allow trailing fractional part.
796  if (kind == DECIMAL) {
797  ScanDecimalDigits(); // optional
798  if (c0_ == '.') {
799  AddLiteralCharAdvance();
800  ScanDecimalDigits(); // optional
801  }
802  }
803  }
804 
805  // scan exponent, if any
806  if (c0_ == 'e' || c0_ == 'E') {
807  ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number
808  if (kind != DECIMAL) return Token::ILLEGAL;
809  // scan exponent
810  AddLiteralCharAdvance();
811  if (c0_ == '+' || c0_ == '-')
812  AddLiteralCharAdvance();
813  if (!IsDecimalDigit(c0_)) {
814  // we must have at least one decimal digit after 'e'/'E'
815  return Token::ILLEGAL;
816  }
817  ScanDecimalDigits();
818  }
819 
820  // The source character immediately following a numeric literal must
821  // not be an identifier start or a decimal digit; see ECMA-262
822  // section 7.8.3, page 17 (note that we read only one decimal digit
823  // if the value is 0).
824  if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_))
825  return Token::ILLEGAL;
826 
827  literal.Complete();
828 
829  return Token::NUMBER;
830 }
831 
832 
833 uc32 Scanner::ScanIdentifierUnicodeEscape() {
834  Advance();
835  if (c0_ != 'u') return -1;
836  Advance();
837  uc32 result = ScanHexNumber(4);
838  if (result < 0) PushBack('u');
839  return result;
840 }
841 
842 
843 // ----------------------------------------------------------------------------
844 // Keyword Matcher
845 
846 #define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
847  KEYWORD_GROUP('b') \
848  KEYWORD("break", Token::BREAK) \
849  KEYWORD_GROUP('c') \
850  KEYWORD("case", Token::CASE) \
851  KEYWORD("catch", Token::CATCH) \
852  KEYWORD("class", Token::FUTURE_RESERVED_WORD) \
853  KEYWORD("const", Token::CONST) \
854  KEYWORD("continue", Token::CONTINUE) \
855  KEYWORD_GROUP('d') \
856  KEYWORD("debugger", Token::DEBUGGER) \
857  KEYWORD("default", Token::DEFAULT) \
858  KEYWORD("delete", Token::DELETE) \
859  KEYWORD("do", Token::DO) \
860  KEYWORD_GROUP('e') \
861  KEYWORD("else", Token::ELSE) \
862  KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \
863  KEYWORD("export", harmony_modules \
864  ? Token::EXPORT : Token::FUTURE_RESERVED_WORD) \
865  KEYWORD("extends", Token::FUTURE_RESERVED_WORD) \
866  KEYWORD_GROUP('f') \
867  KEYWORD("false", Token::FALSE_LITERAL) \
868  KEYWORD("finally", Token::FINALLY) \
869  KEYWORD("for", Token::FOR) \
870  KEYWORD("function", Token::FUNCTION) \
871  KEYWORD_GROUP('i') \
872  KEYWORD("if", Token::IF) \
873  KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
874  KEYWORD("import", harmony_modules \
875  ? Token::IMPORT : Token::FUTURE_RESERVED_WORD) \
876  KEYWORD("in", Token::IN) \
877  KEYWORD("instanceof", Token::INSTANCEOF) \
878  KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \
879  KEYWORD_GROUP('l') \
880  KEYWORD("let", harmony_scoping \
881  ? Token::LET : Token::FUTURE_STRICT_RESERVED_WORD) \
882  KEYWORD_GROUP('n') \
883  KEYWORD("new", Token::NEW) \
884  KEYWORD("null", Token::NULL_LITERAL) \
885  KEYWORD_GROUP('p') \
886  KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
887  KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \
888  KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
889  KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \
890  KEYWORD_GROUP('r') \
891  KEYWORD("return", Token::RETURN) \
892  KEYWORD_GROUP('s') \
893  KEYWORD("static", Token::FUTURE_STRICT_RESERVED_WORD) \
894  KEYWORD("super", Token::FUTURE_RESERVED_WORD) \
895  KEYWORD("switch", Token::SWITCH) \
896  KEYWORD_GROUP('t') \
897  KEYWORD("this", Token::THIS) \
898  KEYWORD("throw", Token::THROW) \
899  KEYWORD("true", Token::TRUE_LITERAL) \
900  KEYWORD("try", Token::TRY) \
901  KEYWORD("typeof", Token::TYPEOF) \
902  KEYWORD_GROUP('v') \
903  KEYWORD("var", Token::VAR) \
904  KEYWORD("void", Token::VOID) \
905  KEYWORD_GROUP('w') \
906  KEYWORD("while", Token::WHILE) \
907  KEYWORD("with", Token::WITH) \
908  KEYWORD_GROUP('y') \
909  KEYWORD("yield", Token::YIELD)
910 
911 
912 static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
913  int input_length,
914  bool harmony_scoping,
915  bool harmony_modules) {
916  ASSERT(input_length >= 1);
917  const int kMinLength = 2;
918  const int kMaxLength = 10;
919  if (input_length < kMinLength || input_length > kMaxLength) {
920  return Token::IDENTIFIER;
921  }
922  switch (input[0]) {
923  default:
924 #define KEYWORD_GROUP_CASE(ch) \
925  break; \
926  case ch:
927 #define KEYWORD(keyword, token) \
928  { \
929  /* 'keyword' is a char array, so sizeof(keyword) is */ \
930  /* strlen(keyword) plus 1 for the NUL char. */ \
931  const int keyword_length = sizeof(keyword) - 1; \
932  STATIC_ASSERT(keyword_length >= kMinLength); \
933  STATIC_ASSERT(keyword_length <= kMaxLength); \
934  if (input_length == keyword_length && \
935  input[1] == keyword[1] && \
936  (keyword_length <= 2 || input[2] == keyword[2]) && \
937  (keyword_length <= 3 || input[3] == keyword[3]) && \
938  (keyword_length <= 4 || input[4] == keyword[4]) && \
939  (keyword_length <= 5 || input[5] == keyword[5]) && \
940  (keyword_length <= 6 || input[6] == keyword[6]) && \
941  (keyword_length <= 7 || input[7] == keyword[7]) && \
942  (keyword_length <= 8 || input[8] == keyword[8]) && \
943  (keyword_length <= 9 || input[9] == keyword[9])) { \
944  return token; \
945  } \
946  }
948  }
949  return Token::IDENTIFIER;
950 }
951 
952 
953 Token::Value Scanner::ScanIdentifierOrKeyword() {
954  ASSERT(unicode_cache_->IsIdentifierStart(c0_));
955  LiteralScope literal(this);
956  // Scan identifier start character.
957  if (c0_ == '\\') {
958  uc32 c = ScanIdentifierUnicodeEscape();
959  // Only allow legal identifier start characters.
960  if (c < 0 ||
961  c == '\\' || // No recursive escapes.
962  !unicode_cache_->IsIdentifierStart(c)) {
963  return Token::ILLEGAL;
964  }
965  AddLiteralChar(c);
966  return ScanIdentifierSuffix(&literal);
967  }
968 
969  uc32 first_char = c0_;
970  Advance();
971  AddLiteralChar(first_char);
972 
973  // Scan the rest of the identifier characters.
974  while (unicode_cache_->IsIdentifierPart(c0_)) {
975  if (c0_ != '\\') {
976  uc32 next_char = c0_;
977  Advance();
978  AddLiteralChar(next_char);
979  continue;
980  }
981  // Fallthrough if no longer able to complete keyword.
982  return ScanIdentifierSuffix(&literal);
983  }
984 
985  literal.Complete();
986 
987  if (next_.literal_chars->is_one_byte()) {
988  Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
989  return KeywordOrIdentifierToken(chars.start(),
990  chars.length(),
991  harmony_scoping_,
992  harmony_modules_);
993  }
994 
995  return Token::IDENTIFIER;
996 }
997 
998 
999 Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal) {
1000  // Scan the rest of the identifier characters.
1001  while (unicode_cache_->IsIdentifierPart(c0_)) {
1002  if (c0_ == '\\') {
1003  uc32 c = ScanIdentifierUnicodeEscape();
1004  // Only allow legal identifier part characters.
1005  if (c < 0 ||
1006  c == '\\' ||
1007  !unicode_cache_->IsIdentifierPart(c)) {
1008  return Token::ILLEGAL;
1009  }
1010  AddLiteralChar(c);
1011  } else {
1012  AddLiteralChar(c0_);
1013  Advance();
1014  }
1015  }
1016  literal->Complete();
1017 
1018  return Token::IDENTIFIER;
1019 }
1020 
1021 
1022 bool Scanner::ScanRegExpPattern(bool seen_equal) {
1023  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
1024  bool in_character_class = false;
1025 
1026  // Previous token is either '/' or '/=', in the second case, the
1027  // pattern starts at =.
1028  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
1029  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
1030 
1031  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
1032  // the scanner should pass uninterpreted bodies to the RegExp
1033  // constructor.
1034  LiteralScope literal(this);
1035  if (seen_equal) {
1036  AddLiteralChar('=');
1037  }
1038 
1039  while (c0_ != '/' || in_character_class) {
1040  if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
1041  if (c0_ == '\\') { // Escape sequence.
1042  AddLiteralCharAdvance();
1043  if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
1044  AddLiteralCharAdvance();
1045  // If the escape allows more characters, i.e., \x??, \u????, or \c?,
1046  // only "safe" characters are allowed (letters, digits, underscore),
1047  // otherwise the escape isn't valid and the invalid character has
1048  // its normal meaning. I.e., we can just continue scanning without
1049  // worrying whether the following characters are part of the escape
1050  // or not, since any '/', '\\' or '[' is guaranteed to not be part
1051  // of the escape sequence.
1052 
1053  // TODO(896): At some point, parse RegExps more throughly to capture
1054  // octal esacpes in strict mode.
1055  } else { // Unescaped character.
1056  if (c0_ == '[') in_character_class = true;
1057  if (c0_ == ']') in_character_class = false;
1058  AddLiteralCharAdvance();
1059  }
1060  }
1061  Advance(); // consume '/'
1062 
1063  literal.Complete();
1064 
1065  return true;
1066 }
1067 
1068 
1069 bool Scanner::ScanLiteralUnicodeEscape() {
1070  ASSERT(c0_ == '\\');
1071  uc32 chars_read[6] = {'\\', 'u', 0, 0, 0, 0};
1072  Advance();
1073  int i = 1;
1074  if (c0_ == 'u') {
1075  i++;
1076  while (i < 6) {
1077  Advance();
1078  if (!IsHexDigit(c0_)) break;
1079  chars_read[i] = c0_;
1080  i++;
1081  }
1082  }
1083  if (i < 6) {
1084  // Incomplete escape. Undo all advances and return false.
1085  while (i > 0) {
1086  i--;
1087  PushBack(chars_read[i]);
1088  }
1089  return false;
1090  }
1091  // Complete escape. Add all chars to current literal buffer.
1092  for (int i = 0; i < 6; i++) {
1093  AddLiteralChar(chars_read[i]);
1094  }
1095  return true;
1096 }
1097 
1098 
1100  // Scan regular expression flags.
1101  LiteralScope literal(this);
1102  while (unicode_cache_->IsIdentifierPart(c0_)) {
1103  if (c0_ != '\\') {
1104  AddLiteralCharAdvance();
1105  } else {
1106  if (!ScanLiteralUnicodeEscape()) {
1107  break;
1108  }
1109  Advance();
1110  }
1111  }
1112  literal.Complete();
1113 
1114  next_.location.end_pos = source_pos() - 1;
1115  return true;
1116 }
1117 
1118 
1120  PretenureFlag tenured) {
1121  if (is_next_literal_one_byte()) {
1122  return isolate->factory()->NewStringFromOneByte(
1123  Vector<const uint8_t>::cast(next_literal_one_byte_string()), tenured);
1124  } else {
1125  return isolate->factory()->NewStringFromTwoByte(
1126  next_literal_two_byte_string(), tenured);
1127  }
1128 }
1129 
1130 
1132  if (is_literal_one_byte()) {
1133  return isolate->factory()->InternalizeOneByteString(
1134  literal_one_byte_string());
1135  } else {
1136  return isolate->factory()->InternalizeTwoByteString(
1137  literal_two_byte_string());
1138  }
1139 }
1140 
1141 
1143  ASSERT(is_literal_one_byte());
1144  return StringToDouble(
1145  unicode_cache_, Vector<const char>::cast(literal_one_byte_string()),
1147 }
1148 
1149 
1150 int Scanner::FindNumber(DuplicateFinder* finder, int value) {
1151  return finder->AddNumber(literal_one_byte_string(), value);
1152 }
1153 
1154 
1155 int Scanner::FindSymbol(DuplicateFinder* finder, int value) {
1156  if (is_literal_one_byte()) {
1157  return finder->AddOneByteSymbol(literal_one_byte_string(), value);
1158  }
1159  return finder->AddTwoByteSymbol(literal_two_byte_string(), value);
1160 }
1161 
1162 
1163 void Scanner::LogSymbol(ParserRecorder* log, int position) {
1164  if (is_literal_one_byte()) {
1165  log->LogOneByteSymbol(position, literal_one_byte_string());
1166  } else {
1167  log->LogTwoByteSymbol(position, literal_two_byte_string());
1168  }
1169 }
1170 
1171 
1173  return AddSymbol(key, true, value);
1174 }
1175 
1176 
1178  return AddSymbol(Vector<const uint8_t>::cast(key), false, value);
1179 }
1180 
1181 
1182 int DuplicateFinder::AddSymbol(Vector<const uint8_t> key,
1183  bool is_one_byte,
1184  int value) {
1185  uint32_t hash = Hash(key, is_one_byte);
1186  byte* encoding = BackupKey(key, is_one_byte);
1187  HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1188  int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1189  entry->value =
1190  reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1191  return old_value;
1192 }
1193 
1194 
1196  ASSERT(key.length() > 0);
1197  // Quick check for already being in canonical form.
1198  if (IsNumberCanonical(key)) {
1199  return AddOneByteSymbol(key, value);
1200  }
1201 
1203  double double_value = StringToDouble(
1204  unicode_constants_, Vector<const char>::cast(key), flags, 0.0);
1205  int length;
1206  const char* string;
1207  if (!std::isfinite(double_value)) {
1208  string = "Infinity";
1209  length = 8; // strlen("Infinity");
1210  } else {
1211  string = DoubleToCString(double_value,
1212  Vector<char>(number_buffer_, kBufferSize));
1213  length = StrLength(string);
1214  }
1215  return AddSymbol(Vector<const byte>(reinterpret_cast<const byte*>(string),
1216  length), true, value);
1217 }
1218 
1219 
1220 bool DuplicateFinder::IsNumberCanonical(Vector<const uint8_t> number) {
1221  // Test for a safe approximation of number literals that are already
1222  // in canonical form: max 15 digits, no leading zeroes, except an
1223  // integer part that is a single zero, and no trailing zeros below
1224  // the decimal point.
1225  int pos = 0;
1226  int length = number.length();
1227  if (number.length() > 15) return false;
1228  if (number[pos] == '0') {
1229  pos++;
1230  } else {
1231  while (pos < length &&
1232  static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1233  }
1234  if (length == pos) return true;
1235  if (number[pos] != '.') return false;
1236  pos++;
1237  bool invalid_last_digit = true;
1238  while (pos < length) {
1239  uint8_t digit = number[pos] - '0';
1240  if (digit > '9' - '0') return false;
1241  invalid_last_digit = (digit == 0);
1242  pos++;
1243  }
1244  return !invalid_last_digit;
1245 }
1246 
1247 
1248 uint32_t DuplicateFinder::Hash(Vector<const uint8_t> key, bool is_one_byte) {
1249  // Primitive hash function, almost identical to the one used
1250  // for strings (except that it's seeded by the length and ASCII-ness).
1251  int length = key.length();
1252  uint32_t hash = (length << 1) | (is_one_byte ? 1 : 0) ;
1253  for (int i = 0; i < length; i++) {
1254  uint32_t c = key[i];
1255  hash = (hash + c) * 1025;
1256  hash ^= (hash >> 6);
1257  }
1258  return hash;
1259 }
1260 
1261 
1262 bool DuplicateFinder::Match(void* first, void* second) {
1263  // Decode lengths.
1264  // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1265  // with a 8th bit being non-zero while there are more heptets.
1266  // The value encodes the number of bytes following, and whether the original
1267  // was ASCII.
1268  byte* s1 = reinterpret_cast<byte*>(first);
1269  byte* s2 = reinterpret_cast<byte*>(second);
1270  uint32_t length_one_byte_field = 0;
1271  byte c1;
1272  do {
1273  c1 = *s1;
1274  if (c1 != *s2) return false;
1275  length_one_byte_field = (length_one_byte_field << 7) | (c1 & 0x7f);
1276  s1++;
1277  s2++;
1278  } while ((c1 & 0x80) != 0);
1279  int length = static_cast<int>(length_one_byte_field >> 1);
1280  return memcmp(s1, s2, length) == 0;
1281 }
1282 
1283 
1284 byte* DuplicateFinder::BackupKey(Vector<const uint8_t> bytes,
1285  bool is_one_byte) {
1286  uint32_t one_byte_length = (bytes.length() << 1) | (is_one_byte ? 1 : 0);
1287  backing_store_.StartSequence();
1288  // Emit one_byte_length as base-128 encoded number, with the 7th bit set
1289  // on the byte of every heptet except the last, least significant, one.
1290  if (one_byte_length >= (1 << 7)) {
1291  if (one_byte_length >= (1 << 14)) {
1292  if (one_byte_length >= (1 << 21)) {
1293  if (one_byte_length >= (1 << 28)) {
1294  backing_store_.Add(
1295  static_cast<uint8_t>((one_byte_length >> 28) | 0x80));
1296  }
1297  backing_store_.Add(
1298  static_cast<uint8_t>((one_byte_length >> 21) | 0x80u));
1299  }
1300  backing_store_.Add(
1301  static_cast<uint8_t>((one_byte_length >> 14) | 0x80u));
1302  }
1303  backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u));
1304  }
1305  backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f));
1306 
1307  backing_store_.AddBlock(bytes);
1308  return backing_store_.EndSequence().start();
1309 }
1310 
1311 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
const SwVfpRegister s2
bool IsIdentifierPart(unibrow::uchar c)
Definition: scanner.h:142
Handle< String > NewStringFromOneByte(Vector< const uint8_t > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:265
int FindSymbol(DuplicateFinder *finder, int value)
Definition: scanner.cc:1155
int32_t uc32
Definition: globals.h:310
int AddOneByteSymbol(Vector< const uint8_t > key, int value)
Definition: scanner.cc:1172
bool IsWhiteSpace(unibrow::uchar c)
Definition: scanner.h:144
Scanner(UnicodeCache *scanner_contants)
Definition: scanner.cc:47
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 log
Definition: flags.cc:806
void Add(T value)
Definition: utils.h:622
#define ASSERT(condition)
Definition: checks.h:329
int isfinite(double x)
Factory * factory()
Definition: isolate.h:995
virtual void LogTwoByteSymbol(int start, Vector< const uint16_t > literal)
Definition: preparse-data.h:67
#define KEYWORD(keyword, token)
uint8_t byte
Definition: globals.h:185
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:47
Vector< T > AddBlock(int size, T initial_value)
Definition: utils.h:635
T * start() const
Definition: utils.h:426
int AddTwoByteSymbol(Vector< const uint16_t > key, int value)
Definition: scanner.cc:1177
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
Definition: flags.cc:665
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:81
void SeekForward(int pos)
Definition: scanner.cc:601
#define KEYWORD_GROUP_CASE(ch)
int AddNumber(Vector< const uint8_t > key, int value)
Definition: scanner.cc:1195
#define KEYWORDS(KEYWORD_GROUP, KEYWORD)
Definition: scanner.cc:846
bool IsBinaryDigit(uc32 c)
int HexValue(uc32 c)
Definition: scanner.h:52
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:131
Handle< String > NewStringFromTwoByte(Vector< const uc16 > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:282
int length() const
Definition: utils.h:420
#define COMMA
Definition: flags.h:101
void Initialize(Utf16CharacterStream *source)
Definition: scanner.cc:55
bool IsLineTerminator(unibrow::uchar c)
Definition: scanner.h:143
int StrLength(const char *string)
Definition: utils.h:253
int FindNumber(DuplicateFinder *finder, int value)
Definition: scanner.cc:1150
const SwVfpRegister s1
bool IsCarriageReturn(uc32 c)
Handle< String > InternalizeTwoByteString(Vector< const uc16 > str)
Definition: factory.cc:245
Vector< T > EndSequence()
Definition: utils.h:771
Handle< String > InternalizeOneByteString(Vector< const uint8_t > str)
Definition: factory.cc:232
void LogSymbol(ParserRecorder *log, int position)
Definition: scanner.cc:1163
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
bool IsOctalDigit(uc32 c)
Handle< String > AllocateNextLiteralString(Isolate *isolate, PretenureFlag tenured)
Definition: scanner.cc:1119
virtual void LogOneByteSymbol(int start, Vector< const uint8_t > literal)
Definition: preparse-data.h:64
Token::Value Next()
Definition: scanner.cc:231
bool IsHexDigit(uc32 c)
bool IsIdentifierStart(unibrow::uchar c)
Definition: scanner.h:141
unsigned SeekForward(unsigned code_unit_count)
Definition: scanner.h:96
bool ScanRegExpPattern(bool seen_equal)
Definition: scanner.cc:1022
Handle< String > AllocateInternalizedString(Isolate *isolate)
Definition: scanner.cc:1131
bool IsDecimalDigit(uc32 c)
bool IsLineFeed(uc32 c)