]> granicus.if.org Git - clang/commitdiff
Add a bit to IdentifierInfo that acts as a simple predicate which
authorChris Lattner <sabre@nondot.org>
Wed, 21 Jan 2009 07:43:11 +0000 (07:43 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 21 Jan 2009 07:43:11 +0000 (07:43 +0000)
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
lib/Basic/IdentifierTable.cpp
lib/Lex/Lexer.cpp
lib/Lex/PTHLexer.cpp
lib/Lex/Preprocessor.cpp
lib/Lex/TokenLexer.cpp

index 167e0492625f971da5a9997c42f68d5f87999c67..a06e9b10807b331cb5002eb2bcc27992ba0e830a 100644 (file)
@@ -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<IdentifierInfo*> *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<typename T>
   T *getFETokenInfo() const { return static_cast<T*>(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
index d7ef915dab7c4c8fb4157c59b4d1f52a7342cbf2..304c7a9b42f6bf7f287dff423c244536ace77885 100644 (file)
@@ -32,6 +32,7 @@ IdentifierInfo::IdentifierInfo() {
   IsExtension = false;
   IsPoisoned = false;
   IsCPPOperatorKeyword = false;
+  NeedsHandleIdentifier = false;
   FETokenInfo = 0;
   Entry = 0;
 }
index 19b3121c64483b5a1b962866d0e9c356bd892c85..f7937d5d70f4ea048ad2f6fbeca1dba23d4b00a8 100644 (file)
@@ -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.
index 81349171fe8bc1ff15450bea1ab1d8d35c706426..99bb3f795d8a82d84a3ac78c77306d9525351b37 100644 (file)
@@ -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) {
index 5d9fc9567dc990e783ce908af9dccf4998eb344c..e53c392c388b34a42ceb261c95f12e16a91925f8 100644 (file)
@@ -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!");
index 82c4d926aee500ad21f79fdc1f75fa55483d4647..c945843459f400e69b9c660f656ec40cdc171196 100644 (file)
@@ -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.
 }