Changeset 87177 in webkit
- Timestamp:
- May 24, 2011 11:49:18 AM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r87157 r87177 1 2011-05-24 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Geoffrey Garen. 4 5 Avoid creating unnecessary identifiers and strings in the syntax checker 6 https://bugs.webkit.org/show_bug.cgi?id=61378 7 8 Selectively tell the lexer that there are some places it does not need to 9 do the real work of creating Identifiers for IDENT and STRING tokens. 10 11 Make parseString and parseIdentifier templatized on whether they should 12 do real work, or merely validate the tokens. 13 14 SunSpider --parse-only reports ~5-8% win depending on hardware. 15 16 * parser/ASTBuilder.h: 17 (JSC::ASTBuilder::createDotAccess): 18 * parser/JSParser.cpp: 19 (JSC::JSParser::next): 20 (JSC::JSParser::consume): 21 (JSC::JSParser::parseVarDeclarationList): 22 (JSC::JSParser::parseConstDeclarationList): 23 (JSC::JSParser::parseExpression): 24 (JSC::JSParser::parseAssignmentExpression): 25 (JSC::JSParser::parseConditionalExpression): 26 (JSC::JSParser::parseBinaryExpression): 27 (JSC::JSParser::parseProperty): 28 (JSC::JSParser::parseObjectLiteral): 29 (JSC::JSParser::parseArrayLiteral): 30 (JSC::JSParser::parseArguments): 31 (JSC::JSParser::parseMemberExpression): 32 * parser/Lexer.cpp: 33 (JSC::Lexer::parseIdentifier): 34 (JSC::Lexer::parseString): 35 (JSC::Lexer::lex): 36 * parser/Lexer.h: 37 * parser/SyntaxChecker.h: 38 (JSC::SyntaxChecker::createDotAccess): 39 (JSC::SyntaxChecker::createProperty): 40 1 41 2011-05-23 Michael Saboff <msaboff@apple.com> 2 42 -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r78727 r87177 110 110 static const bool NeedsFreeVariableInfo = true; 111 111 static const bool CanUseFunctionCache = true; 112 static const int DontBuildKeywords = 0; 113 static const int DontBuildStrings = 0; 112 114 113 115 ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); … … 210 212 } 211 213 212 ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier &property, int start, int divot, int end)213 { 214 DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, property);214 ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier* property, int start, int divot, int end) 215 { 216 DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, *property); 215 217 setExceptionLocation(node, start, divot, end); 216 218 return node; -
trunk/Source/JavaScriptCore/parser/JSParser.cpp
r85456 r87177 50 50 #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0) 51 51 #define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0) 52 #define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) fail(); } while (0) 52 53 #define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0) 53 54 #define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0) … … 99 100 }; 100 101 101 void next( Lexer::LexType lexType = Lexer::IdentifyReservedWords)102 void next(unsigned lexType = 0) 102 103 { 103 104 m_lastLine = m_token.m_info.line; … … 112 113 } 113 114 114 bool consume(JSTokenType expected )115 bool consume(JSTokenType expected, unsigned flags = 0) 115 116 { 116 117 bool result = m_token.m_type == expected; 117 118 failIfFalse(result); 118 next( );119 next(flags); 119 120 return result; 120 121 } … … 797 798 int varDivot = tokenStart() + 1; 798 799 initStart = tokenStart(); 799 next( ); // consume '='800 next(TreeBuilder::DontBuildStrings); // consume '=' 800 801 int initialAssignments = m_assignmentCount; 801 802 TreeExpression initializer = parseAssignmentExpression(context); … … 829 830 TreeExpression initializer = 0; 830 831 if (hasInitializer) { 831 next( ); // consume '='832 next(TreeBuilder::DontBuildStrings); // consume '=' 832 833 initializer = parseAssignmentExpression(context); 833 834 } … … 1553 1554 typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right); 1554 1555 while (match(COMMA)) { 1555 next( );1556 next(TreeBuilder::DontBuildStrings); 1556 1557 right = parseAssignmentExpression(context); 1557 1558 failIfFalse(right); … … 1598 1599 start = tokenStart(); 1599 1600 m_assignmentCount++; 1600 next( );1601 next(TreeBuilder::DontBuildStrings); 1601 1602 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { 1602 1603 failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier); … … 1631 1632 m_nonTrivialExpressionCount++; 1632 1633 m_nonLHSCount++; 1633 next( );1634 next(TreeBuilder::DontBuildStrings); 1634 1635 TreeExpression lhs = parseAssignmentExpression(context); 1635 consumeOrFail (COLON);1636 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings); 1636 1637 1637 1638 TreeExpression rhs = parseAssignmentExpression(context); … … 1671 1672 m_nonLHSCount++; 1672 1673 int operatorToken = m_token.m_type; 1673 next( );1674 next(TreeBuilder::DontBuildStrings); 1674 1675 1675 1676 while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) { … … 1706 1707 case STRING: { 1707 1708 const Identifier* ident = m_token.m_data.ident; 1708 next(Lexer::IgnoreReservedWords); 1709 if (complete || (wasIdent && (*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set))) 1710 next(Lexer::IgnoreReservedWords); 1711 else 1712 next(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords); 1713 1709 1714 if (match(COLON)) { 1710 1715 next(); … … 1748 1753 { 1749 1754 int startOffset = m_token.m_data.intValue; 1750 consumeOrFail (OPENBRACE);1755 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings); 1751 1756 1752 1757 if (match(CLOSEBRACE)) { … … 1765 1770 TreePropertyList tail = propertyList; 1766 1771 while (match(COMMA)) { 1767 next( );1772 next(TreeBuilder::DontBuildStrings); 1768 1773 // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 1769 1774 if (match(CLOSEBRACE)) … … 1830 1835 template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context) 1831 1836 { 1832 consumeOrFail (OPENBRACKET);1837 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings); 1833 1838 1834 1839 int elisions = 0; 1835 1840 while (match(COMMA)) { 1836 next( );1841 next(TreeBuilder::DontBuildStrings); 1837 1842 elisions++; 1838 1843 } 1839 1844 if (match(CLOSEBRACKET)) { 1840 next( );1845 next(TreeBuilder::DontBuildStrings); 1841 1846 return context.createArray(elisions); 1842 1847 } … … 1848 1853 elisions = 0; 1849 1854 while (match(COMMA)) { 1850 next( );1855 next(TreeBuilder::DontBuildStrings); 1851 1856 elisions = 0; 1852 1857 … … 1857 1862 1858 1863 if (match(CLOSEBRACKET)) { 1859 next( );1864 next(TreeBuilder::DontBuildStrings); 1860 1865 return context.createArray(elisions, elementList); 1861 1866 } … … 1949 1954 template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context) 1950 1955 { 1951 consumeOrFail (OPENPAREN);1956 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings); 1952 1957 if (match(CLOSEPAREN)) { 1953 next( );1958 next(TreeBuilder::DontBuildStrings); 1954 1959 return context.createArguments(); 1955 1960 } … … 1960 1965 TreeArgumentsList tail = argList; 1961 1966 while (match(COMMA)) { 1962 next( );1967 next(TreeBuilder::DontBuildStrings); 1963 1968 TreeExpression arg = parseAssignmentExpression(context); 1964 1969 failIfFalse(arg); … … 2034 2039 m_nonTrivialExpressionCount++; 2035 2040 int expressionEnd = lastTokenEnd(); 2036 next(Lexer::IgnoreReservedWords );2041 next(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords); 2037 2042 matchOrFail(IDENT); 2038 base = context.createDotAccess(base, *m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());2043 base = context.createDotAccess(base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd()); 2039 2044 next(); 2040 2045 break; -
trunk/Source/JavaScriptCore/parser/Lexer.cpp
r75852 r87177 400 400 } 401 401 402 ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* lvalp, LexTypelexType)402 template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* lvalp, unsigned lexType) 403 403 { 404 404 bool bufferRequired = false; … … 427 427 if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character))) 428 428 return ERRORTOK; 429 record16(character); 429 if (shouldCreateIdentifier) 430 record16(character); 430 431 identifierStart = currentCharacter(); 431 432 } 432 433 433 if (!bufferRequired) 434 identifierLength = currentCharacter() - identifierStart; 435 else { 436 if (identifierStart != currentCharacter()) 437 m_buffer16.append(identifierStart, currentCharacter() - identifierStart); 438 identifierStart = m_buffer16.data(); 439 identifierLength = m_buffer16.size(); 440 } 441 442 const Identifier* ident = makeIdentifier(identifierStart, identifierLength); 443 lvalp->ident = ident; 434 const Identifier* ident = 0; 435 if (shouldCreateIdentifier) { 436 if (!bufferRequired) 437 identifierLength = currentCharacter() - identifierStart; 438 else { 439 if (identifierStart != currentCharacter()) 440 m_buffer16.append(identifierStart, currentCharacter() - identifierStart); 441 identifierStart = m_buffer16.data(); 442 identifierLength = m_buffer16.size(); 443 } 444 445 ident = makeIdentifier(identifierStart, identifierLength); 446 lvalp->ident = ident; 447 } else 448 lvalp->ident = 0; 449 444 450 m_delimited = false; 445 451 446 if (LIKELY(!bufferRequired && lexType == IdentifyReservedWords)) { 452 if (LIKELY(!bufferRequired && !(lexType & IgnoreReservedWords))) { 453 ASSERT(shouldCreateIdentifier); 447 454 // Keywords must not be recognized if there was an \uXXXX in the identifier. 448 455 const HashEntry* entry = m_keywordTable.entry(m_globalData, *ident); … … 454 461 } 455 462 456 ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp, bool strictMode)463 template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp, bool strictMode) 457 464 { 458 465 int stringQuoteCharacter = m_current; … … 463 470 while (m_current != stringQuoteCharacter) { 464 471 if (UNLIKELY(m_current == '\\')) { 465 if (stringStart != currentCharacter() )472 if (stringStart != currentCharacter() && shouldBuildStrings) 466 473 m_buffer16.append(stringStart, currentCharacter() - stringStart); 467 474 shift(); … … 471 478 // Most common escape sequences first 472 479 if (escape) { 473 record16(escape); 480 if (shouldBuildStrings) 481 record16(escape); 474 482 shift(); 475 483 } else if (UNLIKELY(isLineTerminator(m_current))) … … 480 488 int prev = m_current; 481 489 shift(); 482 record16(convertHex(prev, m_current)); 490 if (shouldBuildStrings) 491 record16(convertHex(prev, m_current)); 483 492 shift(); 484 } else 493 } else if (shouldBuildStrings) 485 494 record16('x'); 486 495 } else if (m_current == 'u') { 487 496 shift(); 488 497 int character = getUnicodeCharacter(); 489 if (character != -1) 490 record16(character); 491 else if (m_current == stringQuoteCharacter) 492 record16('u'); 493 else // Only stringQuoteCharacter allowed after \u 498 if (character != -1) { 499 if (shouldBuildStrings) 500 record16(character); 501 } else if (m_current == stringQuoteCharacter) { 502 if (shouldBuildStrings) 503 record16('u'); 504 } else // Only stringQuoteCharacter allowed after \u 494 505 return false; 495 506 } else if (strictMode && isASCIIDigit(m_current)) { … … 499 510 if (character1 != '0' || isASCIIDigit(m_current)) 500 511 return false; 501 record16(0); 512 if (shouldBuildStrings) 513 record16(0); 502 514 } else if (!strictMode && isASCIIOctalDigit(m_current)) { 503 515 // Octal character sequences … … 509 521 shift(); 510 522 if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) { 511 record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0'); 523 if (shouldBuildStrings) 524 record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0'); 512 525 shift(); 513 } else 514 record16((character1 - '0') * 8 + character2 - '0'); 515 } else 516 record16(character1 - '0'); 526 } else { 527 if (shouldBuildStrings) 528 record16((character1 - '0') * 8 + character2 - '0'); 529 } 530 } else { 531 if (shouldBuildStrings) 532 record16(character1 - '0'); 533 } 517 534 } else if (m_current != -1) { 518 record16(m_current); 535 if (shouldBuildStrings) 536 record16(m_current); 519 537 shift(); 520 538 } else … … 536 554 } 537 555 538 if (currentCharacter() != stringStart )556 if (currentCharacter() != stringStart && shouldBuildStrings) 539 557 m_buffer16.append(stringStart, currentCharacter() - stringStart); 540 lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); 558 if (shouldBuildStrings) 559 lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); 560 else 561 lvalp->ident = 0; 562 541 563 m_buffer16.resize(0); 542 564 return true; … … 713 735 } 714 736 715 JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexTypelexType, bool strictMode)737 JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, unsigned lexType, bool strictMode) 716 738 { 717 739 ASSERT(!m_error); … … 1026 1048 break; 1027 1049 case CharacterQuote: 1028 if (UNLIKELY(!parseString(lvalp, strictMode))) 1029 goto returnError; 1050 if (lexType & DontBuildStrings) { 1051 if (UNLIKELY(!parseString<false>(lvalp, strictMode))) 1052 goto returnError; 1053 } else { 1054 if (UNLIKELY(!parseString<true>(lvalp, strictMode))) 1055 goto returnError; 1056 } 1030 1057 shift(); 1031 1058 m_delimited = false; … … 1036 1063 // Fall through into CharacterBackSlash. 1037 1064 case CharacterBackSlash: 1038 token = parseIdentifier(lvalp, lexType); 1065 if (lexType & DontBuildKeywords) 1066 token = parseIdentifier<false>(lvalp, lexType); 1067 else 1068 token = parseIdentifier<true>(lvalp, lexType); 1039 1069 break; 1040 1070 case CharacterLineTerminator: -
trunk/Source/JavaScriptCore/parser/Lexer.h
r82696 r87177 53 53 54 54 // Functions for the parser itself. 55 enum LexType { IdentifyReservedWords, IgnoreReservedWords }; 56 JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType, bool strictMode); 55 enum LexType { 56 IgnoreReservedWords = 1, 57 DontBuildStrings = 2, 58 DontBuildKeywords = 4 59 }; 60 JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, unsigned, bool strictMode); 57 61 bool nextTokenIsColon(); 58 62 int lineNumber() const { return m_lineNumber; } … … 110 114 ALWAYS_INLINE bool lastTokenWasRestrKeyword() const; 111 115 112 ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, LexType);113 ALWAYS_INLINE bool parseString(JSTokenData* lvalp, bool strictMode);116 template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned); 117 template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData* lvalp, bool strictMode); 114 118 ALWAYS_INLINE void parseHex(double& returnValue); 115 119 ALWAYS_INLINE bool parseOctal(double& returnValue); -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r76177 r87177 27 27 #define SyntaxChecker_h 28 28 29 #include "Lexer.h" 29 30 #include <yarr/YarrSyntaxChecker.h> 30 31 … … 114 115 static const bool NeedsFreeVariableInfo = false; 115 116 static const bool CanUseFunctionCache = true; 117 static const unsigned DontBuildKeywords = Lexer::DontBuildKeywords; 118 static const unsigned DontBuildStrings = Lexer::DontBuildStrings; 116 119 117 120 int createSourceElements() { return 1; } … … 140 143 ExpressionType createNull() { return NullExpr; } 141 144 ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } 142 ExpressionType createDotAccess(ExpressionType, const Identifier &, int, int, int) { return DotExpr; }145 ExpressionType createDotAccess(ExpressionType, const Identifier*, int, int, int) { return DotExpr; } 143 146 ExpressionType createRegExp(const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; } 144 147 ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; } … … 154 157 template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type) 155 158 { 156 ASSERT(name);157 159 if (!complete) 158 160 return Property(type); 161 ASSERT(name); 159 162 return Property(name, type); 160 163 }
Note: See TracChangeset
for help on using the changeset viewer.