From 9451eecd7614cc6f73d018ad4d6340b4e8c25e26 Mon Sep 17 00:00:00 2001
From: Yuka Takahashi <yukatkh@gmail.com>
Date: Mon, 19 Nov 2018 16:11:32 +0100
Subject: [PATCH] [D54097]Optimize clang::ASTReader by using DenseMap instead
 of vector (#2903)

Optimize clang::ASTReader by using DenseMap instead of vector

This gives ~20 MB memory improvement.
---
 .../include/clang/Serialization/ASTReader.h   | 15 ++--
 .../clang/lib/Serialization/ASTReader.cpp     | 75 ++++++++++---------
 .../clang/lib/Serialization/ASTReaderDecl.cpp |  5 +-
 3 files changed, 52 insertions(+), 43 deletions(-)

diff --git a/interpreter/llvm/src/tools/clang/include/clang/Serialization/ASTReader.h b/interpreter/llvm/src/tools/clang/include/clang/Serialization/ASTReader.h
index ab6f4f00436..da44613aed9 100644
--- a/interpreter/llvm/src/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/interpreter/llvm/src/tools/clang/include/clang/Serialization/ASTReader.h
@@ -446,7 +446,8 @@ private:
   ///
   /// When the pointer at index I is non-NULL, the type with
   /// ID = (I + 1) << FastQual::Width has already been loaded
-  std::vector<QualType> TypesLoaded;
+  llvm::DenseMap<unsigned, QualType> TypesLoaded;
+  unsigned NumTypesLoaded = 0;
 
   typedef ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>
     GlobalTypeMapType;
@@ -460,7 +461,8 @@ private:
   ///
   /// When the pointer at index I is non-NULL, the declaration with ID
   /// = I + 1 has already been loaded.
-  std::vector<Decl *> DeclsLoaded;
+  llvm::DenseMap<unsigned, Decl *> DeclsLoaded;
+  unsigned NumDeclsLoaded = 0;
 
   typedef ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>
     GlobalDeclMapType;
@@ -602,7 +604,8 @@ private:
   /// If the pointer at index I is non-NULL, then it refers to the
   /// MacroInfo for the identifier with ID=I+1 that has already
   /// been loaded.
-  std::vector<MacroInfo *> MacrosLoaded;
+  llvm::DenseMap<unsigned, MacroInfo *> MacrosLoaded;
+  unsigned NumMacrosLoaded = 0;
 
   typedef std::pair<IdentifierInfo *, serialization::SubmoduleID>
       LoadedMacroInfo;
@@ -1668,17 +1671,17 @@ public:
 
   /// \brief Returns the number of macros found in the chain.
   unsigned getTotalNumMacros() const {
-    return static_cast<unsigned>(MacrosLoaded.size());
+    return NumMacrosLoaded;
   }
 
   /// \brief Returns the number of types found in the chain.
   unsigned getTotalNumTypes() const {
-    return static_cast<unsigned>(TypesLoaded.size());
+    return NumTypesLoaded;
   }
 
   /// \brief Returns the number of declarations found in the chain.
   unsigned getTotalNumDecls() const {
-    return static_cast<unsigned>(DeclsLoaded.size());
+    return NumDeclsLoaded;
   }
 
   /// \brief Returns the number of submodules known.
diff --git a/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReader.cpp b/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReader.cpp
index eb85593ae16..e05c3eec007 100644
--- a/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReader.cpp
@@ -2769,7 +2769,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
           std::make_pair(LocalBaseTypeIndex,
                          F.BaseTypeIndex - LocalBaseTypeIndex));
 
-        TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
+        NumTypesLoaded += F.LocalNumTypes;
       }
       break;
     }
@@ -2799,7 +2799,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
         // module.
         F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
 
-        DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
+        NumDeclsLoaded += F.LocalNumDecls;
       }
       break;
     }
@@ -3333,7 +3333,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
           std::make_pair(LocalBaseMacroID,
                          F.BaseMacroID - LocalBaseMacroID));
 
-        MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);
+        NumMacrosLoaded += F.LocalNumMacros;
       }
       break;
     }
@@ -6766,19 +6766,19 @@ QualType ASTReader::GetType(TypeID ID) {
   }
 
   Index -= NUM_PREDEF_TYPE_IDS;
-  assert(Index < TypesLoaded.size() && "Type index out-of-range");
-  if (TypesLoaded[Index].isNull()) {
-    TypesLoaded[Index] = readTypeRecord(Index);
-    if (TypesLoaded[Index].isNull())
+  assert(Index < NumTypesLoaded && "Type index out-of-range");
+  if (TypesLoaded.find(Index) == TypesLoaded.end()) {
+    QualType QualTy = readTypeRecord(Index);
+    TypesLoaded.insert({Index, QualTy});
+    if (TypesLoaded.find(Index) == TypesLoaded.end())
       return QualType();
 
-    TypesLoaded[Index]->setFromAST();
+    QualTy->setFromAST();
     if (DeserializationListener)
-      DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
-                                        TypesLoaded[Index]);
+      DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID), QualTy);
   }
 
-  return TypesLoaded[Index].withFastQualifiers(FastQuals);
+  return TypesLoaded.find(Index)->second.withFastQualifiers(FastQuals);
 }
 
 QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {
@@ -7016,13 +7016,14 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
 
   unsigned Index = ID - NUM_PREDEF_DECL_IDS;
 
-  if (Index > DeclsLoaded.size()) {
+  if (Index > NumDeclsLoaded) {
     Error("declaration ID out-of-range for AST file");
     return SourceLocation();
   }
 
-  if (Decl *D = DeclsLoaded[Index])
-    return D->getLocation();
+  auto FindRes = DeclsLoaded.find(Index);
+  if (FindRes != DeclsLoaded.end())
+    return FindRes->second->getLocation();
 
   SourceLocation Loc;
   DeclCursorForID(ID, Loc);
@@ -7101,13 +7102,17 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) {
 
   unsigned Index = ID - NUM_PREDEF_DECL_IDS;
 
-  if (Index >= DeclsLoaded.size()) {
+  if (Index >= NumDeclsLoaded) {
     assert(0 && "declaration ID out-of-range for AST file");
     Error("declaration ID out-of-range for AST file");
     return nullptr;
   }
 
-  return DeclsLoaded[Index];
+  auto FindRes = DeclsLoaded.find(Index);
+  if (FindRes == DeclsLoaded.end())
+    return nullptr;
+
+  return FindRes->second;
 }
 
 Decl *ASTReader::GetDecl(DeclID ID) {
@@ -7116,19 +7121,19 @@ Decl *ASTReader::GetDecl(DeclID ID) {
 
   unsigned Index = ID - NUM_PREDEF_DECL_IDS;
 
-  if (Index >= DeclsLoaded.size()) {
+  if (Index >= NumDeclsLoaded) {
     assert(0 && "declaration ID out-of-range for AST file");
     Error("declaration ID out-of-range for AST file");
     return nullptr;
   }
 
-  if (!DeclsLoaded[Index]) {
+  if (DeclsLoaded.find(Index) == DeclsLoaded.end()) {
     ReadDeclRecord(ID);
     if (DeserializationListener)
-      DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
+      DeserializationListener->DeclRead(ID, DeclsLoaded.find(Index)->second);
   }
 
-  return DeclsLoaded[Index];
+  return DeclsLoaded.find(Index)->second;
 }
 
 DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
@@ -7386,20 +7391,16 @@ void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
 void ASTReader::PrintStats() {
   std::fprintf(stderr, "*** AST File Statistics:\n");
 
-  unsigned NumTypesLoaded
-    = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
-                                      QualType());
-  unsigned NumDeclsLoaded
-    = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
-                                      (Decl *)nullptr);
+  unsigned NumTypesLoaded = TypesLoaded.size();
+
+  unsigned NumDeclsLoaded = DeclsLoaded.size();
+
   unsigned NumIdentifiersLoaded
     = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
                                             IdentifiersLoaded.end(),
                                             (IdentifierInfo *)nullptr);
   unsigned NumMacrosLoaded
-    = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
-                                       MacrosLoaded.end(),
-                                       (MacroInfo *)nullptr);
+    = MacrosLoaded.size();
   unsigned NumSelectorsLoaded
     = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
                                           SelectorsLoaded.end(),
@@ -8181,26 +8182,30 @@ MacroInfo *ASTReader::getMacro(MacroID ID) {
   if (ID == 0)
     return nullptr;
 
-  if (MacrosLoaded.empty()) {
+  if (!NumMacrosLoaded) {
     Error("no macro table in AST file");
     return nullptr;
   }
 
   ID -= NUM_PREDEF_MACRO_IDS;
-  if (!MacrosLoaded[ID]) {
+  auto FindRes = MacrosLoaded.find(ID);
+  if (FindRes == MacrosLoaded.end()) {
     GlobalMacroMapType::iterator I
       = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);
     assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
     ModuleFile *M = I->second;
     unsigned Index = ID - M->BaseMacroID;
-    MacrosLoaded[ID] = ReadMacroRecord(*M, M->MacroOffsets[Index]);
+    MacroInfo *MI = ReadMacroRecord(*M, M->MacroOffsets[Index]);
+    MacrosLoaded.insert({ID, MI});
 
     if (DeserializationListener)
-      DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS,
-                                         MacrosLoaded[ID]);
+      DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS, MI);
   }
 
-  return MacrosLoaded[ID];
+  FindRes = MacrosLoaded.find(ID);
+  if (FindRes == MacrosLoaded.end())
+    return nullptr;
+  return FindRes->second;
 }
 
 MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {
diff --git a/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index 7c2baaca15d..b105dc01a70 100644
--- a/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/interpreter/llvm/src/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2560,8 +2560,9 @@ void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
 /// so that future GetDecl calls will return this declaration rather
 /// than trying to load a new declaration.
 inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
-  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
-  DeclsLoaded[Index] = D;
+  assert((DeclsLoaded.find(Index) == DeclsLoaded.end()) &&
+         "Decl loaded twice?");
+  DeclsLoaded.insert({Index, D});
 }
 
 
-- 
GitLab