From e58aa890e8de55bb3146e6ea9fbbba3a58ce30c6 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Wed, 4 Aug 2010 18:21:41 +0000 Subject: [PATCH] When chaining, only write interesting selectors to the PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110229 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/PCHReader.h | 12 +++++-- include/clang/Frontend/PCHWriter.h | 6 ++++ lib/Frontend/PCHReader.cpp | 5 +++ lib/Frontend/PCHWriter.cpp | 53 +++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index d50979379b..971311e40a 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -675,16 +675,21 @@ public: return static_cast(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(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(DeclsLoaded.size()); } + /// \brief Returns the number of selectors found in the chain. + unsigned getTotalNumSelectors() const { + return static_cast(SelectorsLoaded.size()); + } + /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo @@ -794,6 +799,9 @@ public: virtual std::pair 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 &DeclIDs, diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index e22272e44f..811a506216 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -171,6 +171,12 @@ private: /// table. std::vector 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 SelectorIDs; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index ac817ac050..777931948a 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -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"); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3675186052..7bc479c0e1 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -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 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::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; } -- 2.40.0