Skip to content

Commit 9f79fd5

Browse files
committed
Serialize Fingerprints in Swift Modules
1 parent beeefbc commit 9f79fd5

File tree

12 files changed

+189
-7
lines changed

12 files changed

+189
-7
lines changed

include/swift/AST/LazyResolver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ class alignas(void*) LazyMemberLoader {
8484
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
8585
uint64_t contextData) = 0;
8686

87+
/// Returns the fingerprint associated with the given iterable decl context,
88+
/// or \c None if no such fingerprint is available.
89+
virtual Optional<std::string>
90+
loadFingerprint(const IterableDeclContext *IDC) = 0;
91+
8792
/// Populates the given vector with all conformances for \p D.
8893
///
8994
/// The implementation should \em not call setConformances on \p D.

lib/AST/DeclContext.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,12 +1012,16 @@ IterableDeclContext::castDeclToIterableDeclContext(const Decl *D) {
10121012
}
10131013

10141014
Optional<std::string> IterableDeclContext::getBodyFingerprint() const {
1015-
// Only makes sense for contexts in a source file
1016-
if (!getAsGenericContext()->getParentSourceFile())
1017-
return None;
1015+
auto &ctx = getASTContext();
1016+
// If this decl comes from a serialized module, grab its fingerprint from
1017+
// the file.
1018+
if (!getAsGenericContext()->getParentSourceFile()) {
1019+
auto ci = ctx.getOrCreateLazyIterableContextData(this,
1020+
/*lazyLoader=*/nullptr);
1021+
return ci->loader->loadFingerprint(this);
1022+
}
10181023
auto mutableThis = const_cast<IterableDeclContext *>(this);
1019-
return evaluateOrDefault(getASTContext().evaluator,
1020-
ParseMembersRequest{mutableThis},
1024+
return evaluateOrDefault(ctx.evaluator, ParseMembersRequest{mutableThis},
10211025
FingerprintAndMembers())
10221026
.fingerprint;
10231027
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,6 +3831,12 @@ void ClangImporter::Implementation::lookupAllObjCMembers(
38313831
}
38323832
}
38333833

3834+
Optional<std::string>
3835+
ClangImporter::Implementation::loadFingerprint(const IterableDeclContext *) {
3836+
// Clang decls are not fingerprinted in Swift.
3837+
return None;
3838+
}
3839+
38343840
TinyPtrVector<ValueDecl *>
38353841
ClangImporter::Implementation::loadNamedMembers(
38363842
const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) {

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
12471247
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
12481248
uint64_t contextData) override;
12491249

1250+
virtual Optional<std::string>
1251+
loadFingerprint(const IterableDeclContext *IDC) override;
1252+
12501253
private:
12511254
void
12521255
loadAllMembersOfObjcContainer(Decl *D,

lib/Serialization/ModuleFile.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,24 @@ void ModuleFile::loadDerivativeFunctionConfigurations(
650650
}
651651
}
652652

653+
Optional<std::string>
654+
ModuleFile::loadFingerprint(const IterableDeclContext *IDC) {
655+
PrettyStackTraceDecl trace("loading fingerprints for", IDC->getDecl());
656+
657+
assert(IDC->wasDeserialized());
658+
assert(IDC->getDeclID() != 0);
659+
660+
if (!Core->DeclFingerprints) {
661+
return None;
662+
}
663+
664+
auto it = Core->DeclFingerprints->find(IDC->getDeclID());
665+
if (it == Core->DeclFingerprints->end()) {
666+
return None;
667+
}
668+
return *it;
669+
}
670+
653671
TinyPtrVector<ValueDecl *>
654672
ModuleFile::loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
655673
uint64_t contextData) {

lib/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ class ModuleFile
653653
loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N,
654654
uint64_t contextData) override;
655655

656+
virtual Optional<std::string>
657+
loadFingerprint(const IterableDeclContext *IDC) override;
658+
656659
virtual void
657660
loadAllConformances(const Decl *D, uint64_t contextData,
658661
SmallVectorImpl<ProtocolConformance*> &Conforms) override;

lib/Serialization/ModuleFileCoreTableInfo.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,42 @@ class ModuleFileSharedCore::DeclUSRTableInfo {
566566
}
567567
};
568568

569+
class ModuleFileSharedCore::DeclFingerprintsTableInfo {
570+
public:
571+
using internal_key_type = uint32_t;
572+
using external_key_type = DeclID;
573+
using data_type = std::string;
574+
using hash_value_type = uint32_t;
575+
using offset_type = unsigned;
576+
577+
internal_key_type GetInternalKey(external_key_type ID) { return ID; }
578+
579+
hash_value_type ComputeHash(internal_key_type key) {
580+
return llvm::hash_value(key);
581+
}
582+
583+
static bool EqualKey(internal_key_type lhs, internal_key_type rhs) {
584+
return lhs == rhs;
585+
}
586+
587+
static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&data) {
588+
using namespace llvm::support;
589+
unsigned dataLength = endian::readNext<uint16_t, little, unaligned>(data);
590+
return {sizeof(uint32_t), dataLength};
591+
}
592+
593+
static internal_key_type ReadKey(const uint8_t *data, unsigned length) {
594+
using namespace llvm::support;
595+
return endian::readNext<uint32_t, little, unaligned>(data);
596+
}
597+
598+
static data_type ReadData(internal_key_type key, const uint8_t *data,
599+
unsigned length) {
600+
using namespace llvm::support;
601+
return std::string{reinterpret_cast<const char *>(data), length};
602+
}
603+
};
604+
569605
} // end namespace swift
570606

571607
#endif

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,18 @@ ModuleFileSharedCore::readDeclMembersTable(ArrayRef<uint64_t> fields,
531531
base + sizeof(uint32_t), base));
532532
}
533533

534+
std::unique_ptr<ModuleFileSharedCore::SerializedDeclFingerprintsTable>
535+
ModuleFileSharedCore::readDeclFingerprintsTable(ArrayRef<uint64_t> fields,
536+
StringRef blobData) const {
537+
uint32_t tableOffset;
538+
index_block::DeclFingerprintsLayout::readRecord(fields, tableOffset);
539+
auto base = reinterpret_cast<const uint8_t *>(blobData.data());
540+
541+
using OwnedTable = std::unique_ptr<SerializedDeclFingerprintsTable>;
542+
return OwnedTable(SerializedDeclFingerprintsTable::Create(
543+
base + tableOffset, base + sizeof(uint32_t), base));
544+
}
545+
534546
std::unique_ptr<ModuleFileSharedCore::SerializedObjCMethodTable>
535547
ModuleFileSharedCore::readObjCMethodTable(ArrayRef<uint64_t> fields,
536548
StringRef blobData) const {
@@ -685,6 +697,9 @@ bool ModuleFileSharedCore::readIndexBlock(llvm::BitstreamCursor &cursor) {
685697
case index_block::DECL_MEMBER_NAMES:
686698
DeclMemberNames = readDeclMemberNamesTable(scratch, blobData);
687699
break;
700+
case index_block::DECL_FINGERPRINTS:
701+
DeclFingerprints = readDeclFingerprintsTable(scratch, blobData);
702+
break;
688703
case index_block::LOCAL_DECL_CONTEXT_OFFSETS:
689704
assert(blobData.empty());
690705
allocateBuffer(LocalDeclContexts, scratch);

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ class ModuleFileSharedCore {
240240
using SerializedDeclMembersTable =
241241
llvm::OnDiskIterableChainedHashTable<DeclMembersTableInfo>;
242242

243+
class DeclFingerprintsTableInfo;
244+
using SerializedDeclFingerprintsTable =
245+
llvm::OnDiskIterableChainedHashTable<DeclFingerprintsTableInfo>;
246+
243247
std::unique_ptr<SerializedDeclTable> TopLevelDecls;
244248
std::unique_ptr<SerializedDeclTable> OperatorDecls;
245249
std::unique_ptr<SerializedDeclTable> PrecedenceGroupDecls;
@@ -250,6 +254,7 @@ class ModuleFileSharedCore {
250254
std::unique_ptr<SerializedOpaqueReturnTypeDeclTable> OpaqueReturnTypeDecls;
251255
std::unique_ptr<SerializedNestedTypeDeclsTable> NestedTypeDecls;
252256
std::unique_ptr<SerializedDeclMemberNamesTable> DeclMemberNames;
257+
std::unique_ptr<SerializedDeclFingerprintsTable> DeclFingerprints;
253258

254259
class ObjCMethodTableInfo;
255260
using SerializedObjCMethodTable =
@@ -399,6 +404,12 @@ class ModuleFileSharedCore {
399404
std::unique_ptr<SerializedDeclMembersTable>
400405
readDeclMembersTable(ArrayRef<uint64_t> fields, StringRef blobData) const;
401406

407+
/// Read an on-disk local declid-string hash table stored in
408+
/// index_block::DeclFingerprintsLayout format.
409+
std::unique_ptr<SerializedDeclFingerprintsTable>
410+
readDeclFingerprintsTable(ArrayRef<uint64_t> fields,
411+
StringRef blobData) const;
412+
402413
/// Read an on-disk derivative function configuration table stored in
403414
/// index_block::DerivativeFunctionConfigTableLayout format.
404415
std::unique_ptr<ModuleFileSharedCore::SerializedDerivativeFunctionConfigTable>

lib/Serialization/ModuleFormat.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 586; // allow errors in modules
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 587; // fingerprints in modules
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -2010,14 +2010,15 @@ namespace index_block {
20102010
PRECEDENCE_GROUPS,
20112011
NESTED_TYPE_DECLS,
20122012
DECL_MEMBER_NAMES,
2013+
DECL_FINGERPRINTS,
20132014

20142015
ORDERED_TOP_LEVEL_DECLS,
20152016

20162017
SUBSTITUTION_MAP_OFFSETS,
20172018
CLANG_TYPE_OFFSETS,
20182019
LastRecordKind = CLANG_TYPE_OFFSETS,
20192020
};
2020-
2021+
20212022
constexpr const unsigned RecordIDFieldWidth = 5;
20222023
static_assert(LastRecordKind < (1 << RecordIDFieldWidth),
20232024
"not enough bits for all record kinds");
@@ -2078,6 +2079,12 @@ namespace index_block {
20782079
RecordIDField, // record ID
20792080
BCArray<DeclIDField> // list of decls by ID
20802081
>;
2082+
2083+
using DeclFingerprintsLayout = BCRecordLayout<
2084+
DECL_FINGERPRINTS, // record ID
2085+
BCVBR<16>, // table offset within the blob (see below)
2086+
BCBlob // map from member DeclIDs to strings
2087+
>;
20812088
}
20822089

20832090
/// \sa DECL_MEMBER_TABLES_BLOCK_ID

0 commit comments

Comments
 (0)