COMMIT_MESSAGE

 1String parse
 2
 3Signed-off-by: Zoltan Herczeg <zherczeg@inf.u-szeged.hu>

JavaScriptCore/ChangeLog

 12010-07-05 Zoltan Herczeg <zherczeg@webkit.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Refactored string parsing inside the lexer
 6 https://bugs.webkit.org/show_bug.cgi?id=41606
 7
 8 Does not use goto. Although the last sunspider
 9 parse-only tests yields 1.044x speedup, I think the
 10 patch can have a slight improvement at most.
 11
 12 * parser/Lexer.cpp:
 13 (JSC::singleEscape):
 14 (JSC::Lexer::parseString):
 15 (JSC::Lexer::lex):
 16 * parser/Lexer.h:
 17
1182010-07-04 Mark Rowe <mrowe@apple.com>
219
320 Build fix after r62456.

JavaScriptCore/parser/Lexer.cpp

@@static inline int singleEscape(int c)
357357 return 0x0C;
358358 case 'r':
359359 return 0x0D;
 360 case '\\':
 361 return '\\';
 362 case '\'':
 363 return '\'';
 364 case '"':
 365 return '"';
360366 default:
361  return c;
 367 return 0;
362368 }
363369}
364370

@@inline void Lexer::record16(int c)
381387 record16(UChar(static_cast<unsigned short>(c)));
382388}
383389
 390ALWAYS_INLINE bool Lexer::parseString(void* lvalp)
 391{
 392 int stringQuoteCharacter = m_current;
 393 shift();
 394
 395 const UChar* stringStart = currentCharacter();
 396
 397 while (m_current != stringQuoteCharacter) {
 398 if (UNLIKELY(m_current == '\\')) {
 399 if (stringStart != currentCharacter())
 400 m_buffer16.append(stringStart, currentCharacter() - stringStart);
 401 shift();
 402
 403 int escape = singleEscape(m_current);
 404
 405 // Most common escape sequences first
 406 if (escape) {
 407 record16(escape);
 408 shift();
 409 } else if (UNLIKELY(isLineTerminator(m_current)))
 410 shiftLineTerminator();
 411 else if (m_current == 'x') {
 412 shift();
 413 if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
 414 int prev = m_current;
 415 shift();
 416 record16(convertHex(prev, m_current));
 417 shift();
 418 } else
 419 record16('x');
 420 } else if (m_current == 'u') {
 421 shift();
 422 int character = getUnicodeCharacter();
 423 if (character != -1)
 424 record16(character);
 425 else if (m_current == stringQuoteCharacter)
 426 record16('u');
 427 else // Only stringQuoteCharacter allowed after \u
 428 return false;
 429 } else if (isASCIIOctalDigit(m_current)) {
 430 // Octal character sequences
 431 int character1 = m_current;
 432 shift();
 433 if (isASCIIOctalDigit(m_current)) {
 434 // Two octal characters
 435 int character2 = m_current;
 436 shift();
 437 if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
 438 record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
 439 shift();
 440 } else
 441 record16((character1 - '0') * 8 + character2 - '0');
 442 } else
 443 record16(character1 - '0');
 444 } else if (m_current != -1) {
 445 record16(m_current);
 446 shift();
 447 } else
 448 return false;
 449
 450 stringStart = currentCharacter();
 451 continue;
 452 } else if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
 453 // New-line or end of input is not allowed
 454 if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
 455 return false;
 456 // Anything else is just a normal character
 457 }
 458 shift();
 459 }
 460
 461 if (currentCharacter() != stringStart)
 462 m_buffer16.append(stringStart, currentCharacter() - stringStart);
 463 reinterpret_cast<YYSTYPE*>(lvalp)->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
 464 m_buffer16.resize(0);
 465 return true;
 466}
 467
384468int Lexer::lex(void* p1, void* p2)
385469{
386470 ASSERT(!m_error);

@@start:
401485 if (UNLIKELY(m_current == -1)) {
402486 if (!m_terminator && !m_delimited && !m_isReparsing) {
403487 // automatic semicolon insertion if program incomplete
404  token = ';';
405488 goto doneSemicolon;
406489 }
407490 return 0;
408491 }
409492
410493 m_delimited = false;
411  ASSERT(m_current >= 0);
412494
413  if (m_current < 128) {
414  ASSERT(isASCII(m_current));
 495 if (isASCII(m_current)) {
 496 ASSERT(m_current >= 0 && m_current < 128);
415497
416498 switch (AsciiCharacters[m_current]) {
417499 case CharacterGreater:

@@start:
633715 case CharacterNumber:
634716 goto startNumber;
635717 case CharacterQuote:
636  goto startString;
 718 if (UNLIKELY(!parseString(lvalp)))
 719 goto returnError;
 720 shift();
 721 m_delimited = false;
 722 token = STRING;
 723 break;
637724 case CharacterAlpha:
638725 ASSERT(isIdentStart(m_current));
639726 goto startIdentifierOrKeyword;

@@start:
655742 }
656743 } else {
657744 // Rare characters
658  ASSERT(!isASCII(m_current));
659745
660746 if (isNonASCIIIdentStart(m_current))
661747 goto startIdentifierOrKeyword;

@@start:
663749 shiftLineTerminator();
664750 m_atLineStart = true;
665751 m_terminator = true;
666  if (lastTokenWasRestrKeyword()) {
667  token = ';';
 752 if (lastTokenWasRestrKeyword())
668753 goto doneSemicolon;
669  }
670754 goto start;
671755 }
672756 goto returnError;

@@start:
675759 m_atLineStart = false;
676760 goto returnToken;
677761
678 startString: {
679  int stringQuoteCharacter = m_current;
680  shift();
681 
682  const UChar* stringStart = currentCharacter();
683  while (m_current != stringQuoteCharacter) {
684  // Fast check for characters that require special handling.
685  // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
686  // as possible, and lets through all common ASCII characters.
687  if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
688  m_buffer16.append(stringStart, currentCharacter() - stringStart);
689  goto inString;
690  }
691  shift();
692  }
693  lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
694  shift();
695  m_atLineStart = false;
696  m_delimited = false;
697  token = STRING;
698  goto returnToken;
699 
700 inString:
701  while (m_current != stringQuoteCharacter) {
702  if (m_current == '\\')
703  goto inStringEscapeSequence;
704  if (UNLIKELY(isLineTerminator(m_current)))
705  goto returnError;
706  if (UNLIKELY(m_current == -1))
707  goto returnError;
708  record16(m_current);
709  shift();
710  }
711  goto doneString;
712 
713 inStringEscapeSequence:
714  shift();
715  if (m_current == 'x') {
716  shift();
717  if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
718  int prev = m_current;
719  shift();
720  record16(convertHex(prev, m_current));
721  shift();
722  goto inString;
723  }
724  record16('x');
725  if (m_current == stringQuoteCharacter)
726  goto doneString;
727  goto inString;
728  }
729  if (m_current == 'u') {
730  shift();
731  token = getUnicodeCharacter();
732  if (token != -1) {
733  record16(token);
734  goto inString;
735  }
736  if (m_current == stringQuoteCharacter) {
737  record16('u');
738  goto doneString;
739  }
740  goto returnError;
741  }
742  if (isASCIIOctalDigit(m_current)) {
743  int char1 = m_current;
744  shift();
745  if (char1 >= '0' && char1 <= '3' && isASCIIOctalDigit(m_current) && isASCIIOctalDigit(peek(1))) {
746  int char2 = m_current;
747  shift();
748  record16((char1 - '0') * 64 + (char2 - '0') * 8 + m_current - '0');
749  shift();
750  goto inString;
751  }
752  if (isASCIIOctalDigit(m_current)) {
753  record16((char1 - '0') * 8 + m_current - '0');
754  shift();
755  goto inString;
756  }
757  record16(char1 - '0');
758  goto inString;
759  }
760  if (isLineTerminator(m_current)) {
761  shiftLineTerminator();
762  goto inString;
763  }
764  if (m_current == -1)
765  goto returnError;
766  record16(singleEscape(m_current));
767  shift();
768  goto inString;
769 }
770 
771762startIdentifierWithBackslash: {
772763 shift();
773764 if (UNLIKELY(m_current != 'u'))

@@doneIdentifierOrKeyword: {
1003994 m_buffer16.resize(0);
1004995 const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
1005996 token = entry ? entry->lexerValue() : static_cast<int>(IDENT);
1006  goto returnToken;
1007 }
1008 
1009 doneString:
1010  // Atomize constant strings in case they're later used in property lookup.
1011  shift();
1012  m_atLineStart = false;
1013  m_delimited = false;
1014  lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
1015  m_buffer16.resize(0);
1016  token = STRING;
1017997
1018998 // Fall through into returnToken.
 999}
10191000
10201001returnToken: {
10211002 int lineNumber = m_lineNumber;

JavaScriptCore/parser/Lexer.h

@@namespace JSC {
8686
8787 ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
8888
 89 ALWAYS_INLINE bool parseString(void* lvalp);
 90
8991 static const size_t initialReadBufferCapacity = 32;
90 
 92
9193 int m_lineNumber;
9294 int m_lastLineNumber;
9395