]> granicus.if.org Git - clang/commitdiff
When chaining, only write interesting selectors to the PCH.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 4 Aug 2010 18:21:41 +0000 (18:21 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 4 Aug 2010 18:21:41 +0000 (18:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110229 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/PCHReader.h
include/clang/Frontend/PCHWriter.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp

index d50979379b8886c13b4ffd763b983b9766c1ca37..971311e40a9fa96e72c22d2197614ae121d8eb5e 100644 (file)
@@ -675,16 +675,21 @@ public:
     return static_cast<unsigned>(IdentifiersLoaded.size());
   }
 
-  /// \brief Returns the number of types found in this file.
+  /// \brief Returns the number of types found in the chain.
   unsigned getTotalNumTypes() const {
     return static_cast<unsigned>(TypesLoaded.size());
   }
 
-  /// \brief Returns the number of declarations found in this file.
+  /// \brief Returns the number of declarations found in the chain.
   unsigned getTotalNumDecls() const {
     return static_cast<unsigned>(DeclsLoaded.size());
   }
 
+  /// \brief Returns the number of selectors found in the chain.
+  unsigned getTotalNumSelectors() const {
+    return static_cast<unsigned>(SelectorsLoaded.size());
+  }
+
   /// \brief Reads a TemplateArgumentLocInfo appropriate for the
   /// given TemplateArgument kind.
   TemplateArgumentLocInfo
@@ -794,6 +799,9 @@ public:
   virtual std::pair<ObjCMethodList, ObjCMethodList>
     ReadMethodPool(Selector Sel);
 
+  /// \brief Load a selector from disk, registering its ID if it exists.
+  void LoadSelector(Selector Sel);
+
   void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
   void SetGloballyVisibleDecls(IdentifierInfo *II,
                                const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
index e22272e44f7dcbe09f4e2d222486066a9138686e..811a5062167e8a3c29c9478d4f982330ee65902c 100644 (file)
@@ -171,6 +171,12 @@ private:
   /// table.
   std::vector<uint32_t> IdentifierOffsets;
 
+  /// \brief The first ID number we can use for our own selectors.
+  pch::SelectorID FirstSelectorID;
+
+  /// \brief The selector ID that will be assigned to the next new identifier.
+  pch::SelectorID NextSelectorID;
+
   /// \brief Map that provides the ID numbers of each Selector.
   llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
 
index ac817ac050c58664f6e1434e053d2e70558cc763..777931948ac7efa7105d45bc53fb36cb8006e4f2 100644 (file)
@@ -3230,6 +3230,11 @@ PCHReader::ReadMethodPool(Selector Sel) {
   return std::make_pair(Data.Instance, Data.Factory);
 }
 
+void PCHReader::LoadSelector(Selector Sel) {
+  // It would be complicated to avoid reading the methods anyway. So don't.
+  ReadMethodPool(Sel);
+}
+
 void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
   assert(ID && "Non-zero identifier ID required");
   assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
index 3675186052d9fc34c713632553f997dcdbea9e9d..7bc479c0e1cec8e62c7b4aa036c9b2b0c037cb16 100644 (file)
@@ -1655,13 +1655,14 @@ void PCHWriter::WriteSelectors(Sema &SemaRef) {
   // Do we have to do anything at all?
   if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
     return;
+  unsigned NumTableEntries = 0;
   // Create and write out the blob that contains selectors and the method pool.
   {
     OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator;
 
     // Create the on-disk hash table representation. We walk through every
     // selector we've seen and look it up in the method pool.
-    SelectorOffsets.resize(SelectorIDs.size());
+    SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
     for (llvm::DenseMap<Selector, pch::SelectorID>::iterator
              I = SelectorIDs.begin(), E = SelectorIDs.end();
          I != E; ++I) {
@@ -1676,7 +1677,26 @@ void PCHWriter::WriteSelectors(Sema &SemaRef) {
         Data.Instance = F->second.first;
         Data.Factory = F->second.second;
       }
+      // Only write this selector if it's not in an existing PCH or something
+      // changed.
+      if (Chain && I->second < FirstSelectorID) {
+        // Selector already exists. Did it change?
+        bool changed = false;
+        for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method;
+             M = M->Next) {
+          if (M->Method->getPCHLevel() == 0)
+            changed = true;
+        }
+        for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method;
+             M = M->Next) {
+          if (M->Method->getPCHLevel() == 0)
+            changed = true;
+        }
+        if (!changed)
+          continue;
+      }
       Generator.insert(S, Data);
+      ++NumTableEntries;
     }
 
     // Create the on-disk hash table in a buffer.
@@ -1702,7 +1722,7 @@ void PCHWriter::WriteSelectors(Sema &SemaRef) {
     RecordData Record;
     Record.push_back(pch::METHOD_POOL);
     Record.push_back(BucketOffset);
-    Record.push_back(SelectorIDs.size());
+    Record.push_back(NumTableEntries);
     Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
 
     // Create a blob abbreviation for the selector table offsets.
@@ -2115,17 +2135,20 @@ void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
 void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
   unsigned ID = SelectorIDs[Sel];
   assert(ID && "Unknown selector");
-  SelectorOffsets[ID - 1] = Offset;
+  // Don't record offsets for selectors that are also available in a different
+  // file.
+  if (ID < FirstSelectorID)
+    return;
+  SelectorOffsets[ID - FirstSelectorID] = Offset;
 }
 
 PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
-  : Stream(Stream), Chain(0), FirstDeclID(1),
-    FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), FirstIdentID(1),
-    CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
-    NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) {
-  NextDeclID = FirstDeclID;
-  NextTypeID = FirstTypeID;
-  NextIdentID = FirstIdentID;
+  : Stream(Stream), Chain(0), FirstDeclID(1), NextDeclID(FirstDeclID),
+    FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
+    FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1),
+    NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit),
+    NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
+    NumVisibleDeclContexts(0) {
 }
 
 void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
@@ -2321,9 +2344,11 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   FirstDeclID += Chain->getTotalNumDecls();
   FirstTypeID += Chain->getTotalNumTypes();
   FirstIdentID += Chain->getTotalNumIdentifiers();
+  FirstSelectorID += Chain->getTotalNumSelectors();
   NextDeclID = FirstDeclID;
   NextTypeID = FirstTypeID;
   NextIdentID = FirstIdentID;
+  NextSelectorID = FirstSelectorID;
 
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;
@@ -2519,8 +2544,13 @@ pch::SelectorID PCHWriter::getSelectorRef(Selector Sel) {
   }
 
   pch::SelectorID &SID = SelectorIDs[Sel];
+  if (SID == 0 && Chain) {
+    // This might trigger a ReadSelector callback, which will set the ID for
+    // this selector.
+    Chain->LoadSelector(Sel);
+  }
   if (SID == 0) {
-    SID = SelectorIDs.size();
+    SID = NextSelectorID++;
   }
   return SID;
 }
@@ -2875,6 +2905,7 @@ void PCHWriter::SetReader(PCHReader *Reader) {
   assert(FirstDeclID == NextDeclID &&
          FirstTypeID == NextTypeID &&
          FirstIdentID == NextIdentID &&
+         FirstSelectorID == NextSelectorID &&
          "Setting chain after writing has started.");
   Chain = Reader;
 }