Allow deserialization of just the fields of a record, when we want to iterate over them,
instead of deserializing the complete declaration context of the record.
Iterating over the fields of a record is very common (e.g to determine the layout), unfortunately we needlessly deserialize every declaration
that the declaration context of the record contains; this can be bad for large C++ classes that contain a lot of methods.
Fix this by allow deserialization of just the fields when we want to iterate over them.
Progress for rdar://7260160.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116507 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index ece9945..d60a067 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -599,6 +599,24 @@
}
}
+std::pair<Decl *, Decl *>
+DeclContext::BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls) {
+ // Build up a chain of declarations via the Decl::NextDeclInContext field.
+ Decl *FirstNewDecl = 0;
+ Decl *PrevDecl = 0;
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ Decl *D = Decls[I];
+ if (PrevDecl)
+ PrevDecl->NextDeclInContext = D;
+ else
+ FirstNewDecl = D;
+
+ PrevDecl = D;
+ }
+
+ return std::make_pair(FirstNewDecl, PrevDecl);
+}
+
/// \brief Load the declarations within this lexical storage from an
/// external source.
void
@@ -619,26 +637,22 @@
if (Decls.empty())
return;
- // Resolve all of the declaration IDs into declarations, building up
- // a chain of declarations via the Decl::NextDeclInContext field.
- Decl *FirstNewDecl = 0;
- Decl *PrevDecl = 0;
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- Decl *D = Decls[I];
- if (PrevDecl)
- PrevDecl->NextDeclInContext = D;
- else
- FirstNewDecl = D;
-
- PrevDecl = D;
- }
+ // We may have already loaded just the fields of this record, in which case
+ // don't add the decls, just replace the FirstDecl/LastDecl chain.
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
+ if (RD->LoadedFieldsFromExternalStorage) {
+ llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
+ return;
+ }
// Splice the newly-read declarations into the beginning of the list
// of declarations.
- PrevDecl->NextDeclInContext = FirstDecl;
- FirstDecl = FirstNewDecl;
+ Decl *ExternalFirst, *ExternalLast;
+ llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls);
+ ExternalLast->NextDeclInContext = FirstDecl;
+ FirstDecl = ExternalFirst;
if (!LastDecl)
- LastDecl = PrevDecl;
+ LastDecl = ExternalLast;
}
DeclContext::lookup_result