diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-31 22:17:11 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-08-31 22:17:11 +0000 |
commit | 9ce2b45936896d28939c2d28860a9c9fb424c7d3 (patch) | |
tree | 881aad0deab058309d207b7e999c30820bedc171 /clang/lib/Serialization/ASTWriter.cpp | |
parent | 0518574a735fd41d7aa1a8f3457be9b790b5befd (diff) | |
download | bcm5719-llvm-9ce2b45936896d28939c2d28860a9c9fb424c7d3.tar.gz bcm5719-llvm-9ce2b45936896d28939c2d28860a9c9fb424c7d3.zip |
[modules] Rework serialized DeclContext lookup table management. Instead of
walking the loaded ModuleFiles looking for lookup tables for the context, store
them all in one place, and merge them together if we find we have too many
(currently, more than 4). If we do merge, include the merged form in our
serialized lookup table, so that downstream readers never need to look at our
imports' tables.
This gives a huge performance improvement to builds with very large numbers of
modules (in some cases, more than a 2x speedup was observed).
llvm-svn: 246497
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b5340dc41d2..51839afce1a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -13,6 +13,8 @@ #include "clang/Serialization/ASTWriter.h" #include "ASTCommon.h" +#include "ASTReaderInternals.h" +#include "MultiOnDiskHashTable.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclContextInternals.h" @@ -3338,12 +3340,14 @@ namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { ASTWriter &Writer; + llvm::SmallVector<DeclID, 64> DeclIDs; public: typedef DeclarationNameKey key_type; typedef key_type key_type_ref; - typedef DeclContext::lookup_result data_type; + /// A start and end index into DeclIDs, representing a sequence of decls. + typedef std::pair<unsigned, unsigned> data_type; typedef const data_type& data_type_ref; typedef unsigned hash_value_type; @@ -3351,10 +3355,40 @@ public: explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { } + template<typename Coll> + data_type getData(const Coll &Decls) { + unsigned Start = DeclIDs.size(); + for (NamedDecl *D : Decls) { + DeclIDs.push_back( + Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); + } + return std::make_pair(Start, DeclIDs.size()); + } + + data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { + unsigned Start = DeclIDs.size(); + for (auto ID : FromReader) + DeclIDs.push_back(ID); + return std::make_pair(Start, DeclIDs.size()); + } + + static bool EqualKey(key_type_ref a, key_type_ref b) { + return a == b; + } + hash_value_type ComputeHash(DeclarationNameKey Name) { return Name.getHash(); } + void EmitFileRef(raw_ostream &Out, ModuleFile *F) const { + assert(Writer.hasChain() && + "have reference to loaded module file but no chain?"); + + using namespace llvm::support; + endian::Writer<little>(Out) + .write<uint32_t>(Writer.getChain()->getModuleFileID(F)); + } + std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out, DeclarationNameKey Name, data_type_ref Lookup) { @@ -3381,7 +3415,9 @@ public: LE.write<uint16_t>(KeyLen); // 4 bytes for each DeclID. - unsigned DataLen = 4 * Lookup.size(); + unsigned DataLen = 4 * (Lookup.second - Lookup.first); + assert(uint16_t(DataLen) == DataLen && + "too many decls for serialized lookup result"); LE.write<uint16_t>(DataLen); return std::make_pair(KeyLen, DataLen); @@ -3421,11 +3457,8 @@ public: using namespace llvm::support; endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end(); - I != E; ++I) - LE.write<uint32_t>( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), *I))); - + for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) + LE.write<uint32_t>(DeclIDs[I]); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; @@ -3445,7 +3478,7 @@ bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, return true; } -uint32_t +void ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, llvm::SmallVectorImpl<char> &LookupTable) { assert(!ConstDC->HasLazyLocalLexicalLookups && @@ -3457,8 +3490,8 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); // Create the on-disk hash table representation. - llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> - Generator; + MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait, + ASTDeclContextNameLookupTrait> Generator; ASTDeclContextNameLookupTrait Trait(*this); // The first step is to collect the declaration names which we need to @@ -3593,7 +3626,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, switch (Name.getNameKind()) { default: - Generator.insert(Name, Result, Trait); + Generator.insert(Name, Trait.getData(Result), Trait); break; case DeclarationName::CXXConstructorName: @@ -3611,17 +3644,15 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, // the key, only the kind of name is used. if (!ConstructorDecls.empty()) Generator.insert(ConstructorDecls.front()->getDeclName(), - DeclContext::lookup_result(ConstructorDecls), Trait); + Trait.getData(ConstructorDecls), Trait); if (!ConversionDecls.empty()) Generator.insert(ConversionDecls.front()->getDeclName(), - DeclContext::lookup_result(ConversionDecls), Trait); + Trait.getData(ConversionDecls), Trait); - // Create the on-disk hash table in a buffer. - llvm::raw_svector_ostream Out(LookupTable); - // Make sure that no bucket is at offset 0 - using namespace llvm::support; - endian::Writer<little>(Out).write<uint32_t>(0); - return Generator.Emit(Out, Trait); + // Create the on-disk hash table. Also emit the existing imported and + // merged table if there is one. + auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr; + Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); } /// \brief Write the block containing all of the declaration IDs @@ -3704,12 +3735,11 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable); + GenerateNameLookupTable(DC, LookupTable); // Write the lookup table RecordData Record; Record.push_back(DECL_CONTEXT_VISIBLE); - Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, LookupTable); ++NumVisibleDeclContexts; @@ -3732,7 +3762,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; - uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable); + GenerateNameLookupTable(DC, LookupTable); // If we're updating a namespace, select a key declaration as the key for the // update record; those are the only ones that will be checked on reload. @@ -3743,7 +3773,6 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { RecordData Record; Record.push_back(UPDATE_VISIBLE); Record.push_back(getDeclID(cast<Decl>(DC))); - Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); } @@ -4207,7 +4236,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Abv = new llvm::BitCodeAbbrev(); Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv); WriteDeclContextVisibleUpdate(TU); |