Skip to content

Commit 7ac7d49

Browse files
committed
[Index] Only hash Decl once when generating the hash value for a record
Say we are indexing the header file containing `NSArray`. Almost every declaration in here has a relation to `NSArray` (mostly child-of relations). This means that for every of those declarations we hash `NSArray` again by creating a `DeclHashVisitor` that, among others, adds the string `NSArray` to the hash builder. To avoid this, keep track of all the declarations that we have already incorporated into the hash. If we did already hash the declaration, only incorporate an integer into the hash.
1 parent 9db20e6 commit 7ac7d49

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

clang/lib/Index/IndexRecordHasher.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ struct IndexRecordHasher {
2828
llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
2929
HashBuilder;
3030

31+
/// Maps declarations that have already been hashed in this
32+
/// `IndexRecordHasher` to a unique ID that identifies this declaration.
33+
///
34+
/// The ID assigned to a declaration is consistent across multiple runs of the
35+
/// `IndexRecordHasher` on the same AST structure, even across multiple
36+
/// process runs.
37+
///
38+
/// See `hashDecl` for its use.
39+
llvm::DenseMap<const Decl *, size_t> HashedDecls;
40+
3141
explicit IndexRecordHasher(ASTContext &context) : Ctx(context) {}
3242

3343
void hashDecl(const Decl *D);
@@ -184,6 +194,26 @@ void IndexRecordHasher::hashMacro(const IdentifierInfo *name,
184194
void IndexRecordHasher::hashDecl(const Decl *D) {
185195
assert(D->isCanonicalDecl());
186196

197+
auto emplaceResult = HashedDecls.try_emplace(D, HashedDecls.size() + 1);
198+
bool inserted = emplaceResult.second;
199+
if (!inserted) {
200+
// If we have already serialized this declaration, just add the
201+
// declaration's hash to the hash builder. This is significantly
202+
// cheaper than visiting the declaration again.
203+
HashBuilder.add(emplaceResult.first->second);
204+
return;
205+
}
206+
207+
// If we haven't serialized the declaration yet,`try_emplace` will insert the
208+
// new unique ID into `HashedDecls`. We just need to hash the declaration
209+
// once.
210+
//
211+
// Add a `0` to the hash value to indicate that we are serializing a new
212+
// declaration. The declaration IDs serialized above is always greater than
213+
// zero, so there is no ambiguity between newly serialized decls and the
214+
// serialization of declaration IDs.
215+
HashBuilder.add(0);
216+
187217
if (auto *NS = dyn_cast<NamespaceDecl>(D)) {
188218
if (NS->isAnonymousNamespace()) {
189219
HashBuilder.add("@aN");

0 commit comments

Comments
 (0)