diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-08-20 16:04:35 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-08-20 16:04:35 +0000 |
commit | 074dcc8ef8c5df7a155c85648e8eae786bee6cab (patch) | |
tree | 5c863db01bce5193d1e028a91032e95f2b30e9fa /lib/Serialization | |
parent | 5d26768e2661faa7ce0b55ffff4be8b3969fbbf5 (diff) |
Use the AST on-disk hash table for name lookup inside a DeclContext.
*Huge* improvement over the amount of deserializing that we do for C++ lookup.
e.g, if he have the Carbon header precompiled and include it on a file containing this:
int x;
these are the before/after stats:
BEFORE:
*** AST File Statistics:
578 stat cache hits
4 stat cache misses
548/30654 source location entries read (1.787695%)
15907/16501 types read (96.400223%)
53525/59955 declarations read (89.275291%)
33993/43525 identifiers read (78.099945%)
41516/51891 statements read (80.006165%)
77/5317 macros read (1.448185%)
0/6335 lexical declcontexts read (0.000000%)
1/5424 visible declcontexts read (0.018437%)
AFTER using the on-disk table:
*** AST File Statistics:
578 stat cache hits
4 stat cache misses
548/30654 source location entries read (1.787695%)
10/16501 types read (0.060602%)
9/59955 declarations read (0.015011%)
161/43525 identifiers read (0.369902%)
20/51891 statements read (0.038542%)
6/5317 macros read (0.112846%)
0/6335 lexical declcontexts read (0.000000%)
2/5424 visible declcontexts read (0.036873%)
There's only one issue affecting mostly the precompiled preambles which I will address soon.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111636 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 97 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 32 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 121 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 |
4 files changed, 136 insertions, 120 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 05fa7cd115..b24b35309a 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -846,6 +846,54 @@ public: typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait> ASTDeclContextNameLookupTable; +bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, + const std::pair<uint64_t, uint64_t> &Offsets, + DeclContextInfo &Info) { + SavedStreamPosition SavedPosition(Cursor); + // First the lexical decls. + if (Offsets.first != 0) { + Cursor.JumpToBit(Offsets.first); + + RecordData Record; + const char *Blob; + unsigned BlobLen; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); + if (RecCode != DECL_CONTEXT_LEXICAL) { + Error("Expected lexical block"); + return true; + } + + Info.LexicalDecls = reinterpret_cast<const DeclID*>(Blob); + Info.NumLexicalDecls = BlobLen / sizeof(DeclID); + } else { + Info.LexicalDecls = 0; + Info.NumLexicalDecls = 0; + } + + // Now the lookup table. + if (Offsets.second != 0) { + Cursor.JumpToBit(Offsets.second); + + RecordData Record; + const char *Blob; + unsigned BlobLen; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); + if (RecCode != DECL_CONTEXT_VISIBLE) { + Error("Expected visible lookup table block"); + return true; + } + Info.NameLookupTableData + = ASTDeclContextNameLookupTable::Create( + (const unsigned char *)Blob + Record[0], + (const unsigned char *)Blob, + ASTDeclContextNameLookupTrait(*this)); + } + + return false; +} + void ASTReader::Error(const char *Msg) { Diag(diag::err_fe_pch_malformed) << Msg; } @@ -1674,7 +1722,7 @@ ASTReader::ReadASTBlock(PerFileData &F) { case TU_UPDATE_LEXICAL: { DeclContextInfo Info = { - /* No visible information */ 0, 0, + /* No visible information */ 0, reinterpret_cast<const DeclID *>(BlobStart), BlobLen / sizeof(DeclID) }; @@ -3119,54 +3167,33 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); + if (!Name) + return DeclContext::lookup_result(DeclContext::lookup_iterator(0), + DeclContext::lookup_iterator(0)); - llvm::SmallVector<VisibleDeclaration, 64> Decls; + llvm::SmallVector<NamedDecl *, 64> Decls; // There might be lexical decls in multiple parts of the chain, for the TU // and namespaces. DeclContextInfos &Infos = DeclContextOffsets[DC]; for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end(); I != E; ++I) { - uint64_t Offset = I->OffsetToVisibleDecls; - if (Offset == 0) + if (!I->NameLookupTableData) continue; - llvm::BitstreamCursor &DeclsCursor = *I->Stream; - - // Keep track of where we are in the stream, then jump back there - // after reading this context. - SavedStreamPosition SavedPosition(DeclsCursor); - - // Load the record containing all of the declarations visible in - // this context. - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - if (RecCode != DECL_CONTEXT_VISIBLE) { - Error("Expected visible block"); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - if (Record.empty()) + ASTDeclContextNameLookupTable *LookupTable = + (ASTDeclContextNameLookupTable*)I->NameLookupTableData; + ASTDeclContextNameLookupTable::iterator Pos = LookupTable->find(Name); + if (Pos == LookupTable->end()) continue; - unsigned Idx = 0; - while (Idx < Record.size()) { - Decls.push_back(VisibleDeclaration()); - Decls.back().Name = ReadDeclarationName(Record, Idx); - - unsigned Size = Record[Idx++]; - llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations; - LoadedDecls.reserve(Size); - for (unsigned J = 0; J < Size; ++J) - LoadedDecls.push_back(Record[Idx++]); - } + ASTDeclContextNameLookupTrait::data_type Data = *Pos; + for (; Data.first != Data.second; ++Data.first) + Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first))); } ++NumVisibleDeclContextsRead; - SetExternalVisibleDecls(DC, Decls); + SetExternalVisibleDeclsForName(DC, Name, Decls); return const_cast<DeclContext*>(DC)->lookup(Name); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 9094281cd4..bc68e91e3e 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1413,35 +1413,3 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { return D; } - -bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, - const std::pair<uint64_t, uint64_t> &Offsets, - DeclContextInfo &Info) { - SavedStreamPosition SavedPosition(Cursor); - // First the lexical decls. - if (Offsets.first != 0) { - Cursor.JumpToBit(Offsets.first); - - RecordData Record; - const char *Blob; - unsigned BlobLen; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); - if (RecCode != DECL_CONTEXT_LEXICAL) { - Error("Expected lexical block"); - return true; - } - - Info.LexicalDecls = reinterpret_cast<const DeclID*>(Blob); - Info.NumLexicalDecls = BlobLen / sizeof(DeclID); - } else { - Info.LexicalDecls = 0; - Info.NumLexicalDecls = 0; - } - - // Now the visible decls. - Info.Stream = &Cursor; - Info.OffsetToVisibleDecls = Offsets.second; - - return false; -} diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 94be24ad2c..5deaf3d475 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1466,59 +1466,6 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, return Offset; } -/// \brief Write the block containing all of the declaration IDs -/// visible from the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the -/// bistream, or 0 if no block was written. -uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->getPrimaryContext() != DC) - return 0; - - // Since there is no name lookup into functions or methods, don't bother to - // build a visible-declarations table for these entities. - if (DC->isFunctionOrMethod()) - return 0; - - // If not in C++, we perform name lookup for the translation unit via the - // IdentifierInfo chains, don't bother to build a visible-declarations table. - // FIXME: In C++ we need the visible declarations in order to "see" the - // friend declarations, is there a way to do this without writing the table ? - if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) - return 0; - - // Force the DeclContext to build a its name-lookup table. - DC->lookup(DeclarationName()); - - // Serialize the contents of the mapping used for lookup. Note that, - // although we have two very different code paths, the serialized - // representation is the same for both cases: a declaration name, - // followed by a size, followed by references to the visible - // declarations that have that name. - uint64_t Offset = Stream.GetCurrentBitNo(); - RecordData Record; - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); - if (!Map) - return 0; - - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - AddDeclarationName(D->first, Record); - DeclContext::lookup_result Result = D->second.getLookupResult(Context); - Record.push_back(Result.second - Result.first); - for (; Result.first != Result.second; ++Result.first) - AddDeclRef(*Result.first, Record); - } - - if (Record.size() == 0) - return 0; - - Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record); - ++NumVisibleDeclContexts; - return Offset; -} - void ASTWriter::WriteTypeDeclOffsets() { using namespace llvm; RecordData Record; @@ -2062,6 +2009,74 @@ public: }; } // end anonymous namespace +/// \brief Write the block containing all of the declaration IDs +/// visible from the given DeclContext. +/// +/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the +/// bistream, or 0 if no block was written. +uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, + DeclContext *DC) { + if (DC->getPrimaryContext() != DC) + return 0; + + // Since there is no name lookup into functions or methods, don't bother to + // build a visible-declarations table for these entities. + if (DC->isFunctionOrMethod()) + return 0; + + // If not in C++, we perform name lookup for the translation unit via the + // IdentifierInfo chains, don't bother to build a visible-declarations table. + // FIXME: In C++ we need the visible declarations in order to "see" the + // friend declarations, is there a way to do this without writing the table ? + if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) + return 0; + + // Force the DeclContext to build a its name-lookup table. + DC->lookup(DeclarationName()); + + // Serialize the contents of the mapping used for lookup. Note that, + // although we have two very different code paths, the serialized + // representation is the same for both cases: a declaration name, + // followed by a size, followed by references to the visible + // declarations that have that name. + uint64_t Offset = Stream.GetCurrentBitNo(); + StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); + if (!Map || Map->empty()) + return 0; + + OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator; + ASTDeclContextNameLookupTrait Trait(*this); + + // Create the on-disk hash table representation. + for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); + D != DEnd; ++D) { + DeclarationName Name = D->first; + DeclContext::lookup_result Result = D->second.getLookupResult(); + Generator.insert(Name, Result, Trait); + } + + // Create the on-disk hash table in a buffer. + llvm::SmallString<4096> LookupTable; + uint32_t BucketOffset; + { + llvm::raw_svector_ostream Out(LookupTable); + // Make sure that no bucket is at offset 0 + clang::io::Emit32(Out, 0); + BucketOffset = Generator.Emit(Out, Trait); + } + + // Write the lookup table + RecordData Record; + Record.push_back(DECL_CONTEXT_VISIBLE); + Record.push_back(BucketOffset); + Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, + LookupTable.str()); + + Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record); + ++NumVisibleDeclContexts; + return Offset; +} + //===----------------------------------------------------------------------===// // General Serialization Routines //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 016f4d3c73..a5d2ce21c2 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1086,6 +1086,12 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv); + + Abv = new BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(Abv); } /// isRequiredDecl - Check if this is a "required" Decl, which must be seen by |