From 6a170eb3ea6d6319277becabef68eb1a26bf8766 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 21 Jan 2009 07:43:11 +0000 Subject: [PATCH] Add a bit to IdentifierInfo that acts as a simple predicate which tells us whether Preprocessor::HandleIdentifier needs to be called. Because this method is only rarely needed, this saves a call and a bunch of random checks. This drops the time in HandleIdentifier from 3.52ms to .98ms on cocoa.h on my machine. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62675 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/IdentifierTable.h | 66 ++++++++++++++++++++++++--- lib/Basic/IdentifierTable.cpp | 1 + lib/Lex/Lexer.cpp | 4 +- lib/Lex/PTHLexer.cpp | 4 +- lib/Lex/Preprocessor.cpp | 5 ++ lib/Lex/TokenLexer.cpp | 5 +- 6 files changed, 74 insertions(+), 11 deletions(-) diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 167e049262..a06e9b1080 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -57,7 +57,8 @@ class IdentifierInfo { bool IsExtension : 1; // True if identifier is a lang extension. bool IsPoisoned : 1; // True if identifier is poisoned. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. - // 9 bits left in 32-bit word. + bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". + // 8 bits left in 32-bit word. void *FETokenInfo; // Managed by the language front-end. llvm::StringMapEntry *Entry; @@ -107,13 +108,28 @@ public: bool hasMacroDefinition() const { return HasMacro; } - void setHasMacroDefinition(bool Val) { HasMacro = Val; } + void setHasMacroDefinition(bool Val) { + if (HasMacro == Val) return; + + HasMacro = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API /// can be used to cause the lexer to map identifiers to source-language /// tokens. tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } - void setTokenID(tok::TokenKind ID) { TokenID = ID; } + void setTokenID(tok::TokenKind ID) { + TokenID = ID; + + if (ID != tok::identifier) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } /// getPPKeywordID - Return the preprocessor keyword ID for this identifier. /// For example, "define" will return tok::pp_define. @@ -149,19 +165,36 @@ public: /// language token is an extension. This controls extension warnings, and is /// only valid if a custom token ID is set. bool isExtensionToken() const { return IsExtension; } - void setIsExtensionToken(bool Val) { IsExtension = Val; } + void setIsExtensionToken(bool Val) { + IsExtension = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the /// Preprocessor will emit an error every time this token is used. - void setIsPoisoned(bool Value = true) { IsPoisoned = Value; } + void setIsPoisoned(bool Value = true) { + IsPoisoned = Value; + if (Value) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } /// isPoisoned - Return true if this token has been poisoned. bool isPoisoned() const { return IsPoisoned; } /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether /// this identifier is a C++ alternate representation of an operator. - void setIsCPlusPlusOperatorKeyword(bool Val = true) - { IsCPPOperatorKeyword = Val; } + void setIsCPlusPlusOperatorKeyword(bool Val = true) { + IsCPPOperatorKeyword = Val; + if (Val) + NeedsHandleIdentifier = 1; + else + RecomputeNeedsHandleIdentifier(); + } bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to @@ -169,12 +202,31 @@ public: template T *getFETokenInfo() const { return static_cast(FETokenInfo); } void setFETokenInfo(void *T) { FETokenInfo = T; } + + /// isHandleIdentifierCase - Return true if the Preprocessor::HandleIdentifier + /// must be called on a token of this identifier. If this returns false, we + /// know that HandleIdentifier will not affect the token. + bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } /// Emit - Serialize this IdentifierInfo to a bitstream. void Emit(llvm::Serializer& S) const; /// Read - Deserialize an IdentifierInfo object from a bitstream. void Read(llvm::Deserializer& D); + +private: + /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does + /// several special (but rare) things to identifiers of various sorts. For + /// example, it changes the "for" keyword token from tok::identifier to + /// tok::for. + /// + /// This method is very tied to the definition of HandleIdentifier. Any + /// change to it should be reflected here. + void RecomputeNeedsHandleIdentifier() { + NeedsHandleIdentifier = + (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() | + isExtensionToken()) || getTokenID() != tok::identifier; + } }; /// IdentifierInfoLookup - An abstract class used by IdentifierTable that diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index d7ef915dab..304c7a9b42 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -32,6 +32,7 @@ IdentifierInfo::IdentifierInfo() { IsExtension = false; IsPoisoned = false; IsCPPOperatorKeyword = false; + NeedsHandleIdentifier = false; FETokenInfo = 0; Entry = 0; } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 19b3121c64..f7937d5d70 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -560,7 +560,9 @@ FinishIdentifier: // Finally, now that we know we have an identifier, pass this off to the // preprocessor, which may macro expand it or something. - return PP->HandleIdentifier(Result); + if (Result.getIdentifierInfo()->isHandleIdentifierCase()) + PP->HandleIdentifier(Result); + return; } // Otherwise, $,\,? in identifier found. Enter slower path. diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index 81349171fe..99bb3f795d 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -143,7 +143,9 @@ LexNextToken: if (TKind == tok::identifier) { MIOpt.ReadToken(); - return PP->HandleIdentifier(Tok); + if (Tok.getIdentifierInfo()->isHandleIdentifierCase()) + PP->HandleIdentifier(Tok); + return; } if (TKind == tok::eof) { diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 5d9fc9567d..e53c392c38 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -718,6 +718,11 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier, /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). +/// +/// Note that callers of this method are guarded by checking the +/// IdentifierInfo's 'isHandleIdentifierCase' bit. If this method changes, the +/// IdentifierInfo methods that compute these properties will need to change to +/// match. void Preprocessor::HandleIdentifier(Token &Identifier) { assert(Identifier.getIdentifierInfo() && "Can't handle identifiers without identifier info!"); diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index 82c4d926ae..c945843459 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -326,8 +326,9 @@ void TokenLexer::Lex(Token &Tok) { } // Handle recursive expansion! - if (Tok.getIdentifierInfo() && !DisableMacroExpansion) - return PP.HandleIdentifier(Tok); + if (Tok.getIdentifierInfo() && !DisableMacroExpansion && + Tok.getIdentifierInfo()->isHandleIdentifierCase()) + PP.HandleIdentifier(Tok); // Otherwise, return a normal token. } -- 2.40.0