diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2016-04-19 17:28:44 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2016-04-20 12:58:39 +0000 |
commit | 474b8ec5c088555fc2d85bd577db98e1a936b7cc (patch) | |
tree | bf57835a45779a1cd3f63ccbd40b35eefd974ba6 /src/libs/3rdparty | |
parent | 5dc690f234ec7bb5dcdb11a610a4ecbee6dc4d64 (diff) | |
download | qt-creator-474b8ec5c088555fc2d85bd577db98e1a936b7cc.tar.gz |
C++: Fix expensive parsing of declarations
...which can occurr for e.g. files with a high difference of opening and
closing curly braces and many structs.
Make use of the ASTCache for parseSimpleDeclaration() and
parseMemberSpecification(). Those two were the most recurring calls for
the code provided in the bug report.
Task-number: QTCREATORBUG-16049
Change-Id: I13cc7fba2fb6c3be863690a222c8bbfeacbddc05
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'src/libs/3rdparty')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 901f5ac2c1..b55ac6f18a 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -162,13 +162,25 @@ class Parser::ASTCache public: enum ASTKind { + Declaration, Expression, ExpressionList, + MemberSpecification, ParameterDeclarationClause, TemplateId, TypeId }; + struct CacheKey { + CacheKey(unsigned initialCursor, ASTKind astKind) + : initialCursor(initialCursor) + , astKind(astKind) + {} + + const unsigned initialCursor; + const ASTKind astKind; + }; + public: ASTCache() {} @@ -255,6 +267,17 @@ inline void debugPrintCheckCache(bool) {} } \ } while (0) +#define CACHE_AND_RETURN(cacheKey, expression) \ + do { \ + const bool result = expression; \ + _astCache->insert(cacheKey.astKind, \ + cacheKey.initialCursor, \ + result ? node : 0, \ + cursor(), \ + result); \ + return result; \ + } while (0) + #define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \ if (LA() == T_THROW) { \ if (!parseThrowExpression(node)) \ @@ -2480,6 +2503,9 @@ bool Parser::parseQtInterfaces(DeclarationAST *&node) bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *declaringClass) { DEBUG_THIS_RULE(); + const ASTCache::CacheKey cacheKey(cursor(), ASTCache::MemberSpecification); + CHECK_CACHE(cacheKey.astKind, DeclarationAST); + switch (LA()) { case T_Q_OBJECT: case T_Q_GADGET: @@ -2487,7 +2513,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST * QtObjectTagAST *ast = new (_pool) QtObjectTagAST; ast->q_object_token = consumeToken(); node = ast; - return true; + CACHE_AND_RETURN(cacheKey, true); } case T_Q_PRIVATE_SLOT: @@ -2505,44 +2531,44 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST * parseDeclarator(ast->declarator, ast->type_specifier_list); match(T_RPAREN, &ast->rparen_token); node = ast; - } return true; + } CACHE_AND_RETURN(cacheKey, true); case T_SEMICOLON: - return parseEmptyDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseEmptyDeclaration(node)); case T_USING: - return parseUsing(node); + CACHE_AND_RETURN(cacheKey, parseUsing(node)); case T_TEMPLATE: - return parseTemplateDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseTemplateDeclaration(node)); case T_Q_SIGNALS: case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: case T_Q_SLOTS: - return parseAccessDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseAccessDeclaration(node)); case T_Q_PROPERTY: case T_Q_PRIVATE_PROPERTY: - return parseQtPropertyDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseQtPropertyDeclaration(node)); case T_Q_ENUMS: - return parseQtEnumDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseQtEnumDeclaration(node)); case T_Q_FLAGS: - return parseQtFlags(node); + CACHE_AND_RETURN(cacheKey, parseQtFlags(node)); case T_Q_INTERFACES: - return parseQtInterfaces(node); + CACHE_AND_RETURN(cacheKey, parseQtInterfaces(node)); case T_STATIC_ASSERT: if (_languageFeatures.cxx11Enabled) - return parseStaticAssertDeclaration(node); + CACHE_AND_RETURN(cacheKey, parseStaticAssertDeclaration(node)); // fall-through default: - return parseSimpleDeclaration(node, declaringClass); + CACHE_AND_RETURN(cacheKey, parseSimpleDeclaration(node, declaringClass)); } // switch } @@ -4074,6 +4100,9 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node) bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass) { DEBUG_THIS_RULE(); + const ASTCache::CacheKey cacheKey(cursor(), ASTCache::Declaration); + CHECK_CACHE(cacheKey.astKind, DeclarationAST); + unsigned qt_invokable_token = 0; if (declaringClass && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT || LA() == T_Q_INVOKABLE)) qt_invokable_token = consumeToken(); @@ -4188,7 +4217,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de } } if (! parseInitDeclarator(declarator, decl_specifier_seq, declaringClass)) - return false; + CACHE_AND_RETURN(cacheKey, false); } } @@ -4196,7 +4225,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de // and it doesn't look like a fwd or a class declaration // then it's not a declarations if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq)) - return false; + CACHE_AND_RETURN(cacheKey, false); DeclaratorAST *firstDeclarator = declarator; @@ -4223,7 +4252,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de ast->declarator_list = declarator_list; match(T_SEMICOLON, &ast->semicolon_token); node = ast; - return true; + CACHE_AND_RETURN(cacheKey, true); } else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) { if (LA() == T_TRY) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; @@ -4232,7 +4261,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de ast->declarator = firstDeclarator; parseTryBlockStatement(ast->function_body, &ast->ctor_initializer); node = ast; - return true; // recognized a function definition. + CACHE_AND_RETURN(cacheKey, true); // recognized a function definition. } else { CtorInitializerAST *ctor_initializer = 0; bool hasCtorInitializer = false; @@ -4263,13 +4292,13 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de ast->ctor_initializer = ctor_initializer; parseFunctionBody(ast->function_body); node = ast; - return true; // recognized a function definition. + CACHE_AND_RETURN(cacheKey, true); // recognized a function definition. } } } error(cursor(), "unexpected token `%s'", tok().spell()); - return false; + CACHE_AND_RETURN(cacheKey, false); } bool Parser::maybeForwardOrClassDeclaration(SpecifierListAST *decl_specifier_seq) const |