Skip to content

Commit 76a7cee

Browse files
committed
[NFC] Re-Core Fingerprint
Switch from a string core to a 128-bit integral core. This should make Fingerprints much cheaper to copy around and sets us up for a future where we can provide alternative implementations of the ambient hashing algorithm. rdar://72313506
1 parent c9ef005 commit 76a7cee

File tree

7 files changed

+47
-38
lines changed

7 files changed

+47
-38
lines changed

include/swift/Basic/Fingerprint.h

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,53 +60,51 @@ namespace swift {
6060
class Fingerprint final {
6161
public:
6262
/// The size (in bytes) of the raw value of all fingerprints.
63-
///
64-
/// This constant's value is justified by a static assertion in the
65-
/// corresponding cpp file.
6663
constexpr static size_t DIGEST_LENGTH = 32;
6764

65+
using Core = std::pair<uint64_t, uint64_t>;
6866
private:
69-
std::string Core;
67+
Core core;
7068

7169
public:
70+
/// Creates a fingerprint value from a pair of 64-bit integers.
71+
explicit Fingerprint(Fingerprint::Core value) : core(value) {}
72+
7273
/// Creates a fingerprint value from the given input string that is known to
7374
/// be a 32-byte hash value.
7475
///
7576
/// In +asserts builds, strings that violate this invariant will crash. If a
7677
/// fingerprint value is needed to represent an "invalid" state, use a
7778
/// vocabulary type like \c Optional<Fingerprint> instead.
78-
explicit Fingerprint(std::string value) : Core(std::move(value)) {
79-
assert(Core.size() == Fingerprint::DIGEST_LENGTH &&
80-
"Only supports 32-byte hash values!");
81-
}
79+
static Fingerprint fromString(llvm::StringRef value);
8280

8381
/// Creates a fingerprint value from the given input string literal.
8482
template <std::size_t N>
8583
explicit Fingerprint(const char (&literal)[N])
86-
: Core{literal, N-1} {
84+
: Fingerprint{Fingerprint::fromString({literal, N-1}).core} {
8785
static_assert(N == Fingerprint::DIGEST_LENGTH + 1,
8886
"String literal must be 32 bytes in length!");
8987
}
9088

9189
/// Creates a fingerprint value by consuming the given \c MD5Result from LLVM.
9290
explicit Fingerprint(llvm::MD5::MD5Result &&MD5Value)
93-
: Core{MD5Value.digest().str()} {}
91+
: core{MD5Value.words()} {}
9492

9593
public:
9694
/// Retrieve the raw underlying bytes of this fingerprint.
97-
llvm::StringRef getRawValue() const { return Core; }
95+
llvm::SmallString<Fingerprint::DIGEST_LENGTH> getRawValue() const;
9896

9997
public:
10098
friend bool operator==(const Fingerprint &lhs, const Fingerprint &rhs) {
101-
return lhs.Core == rhs.Core;
99+
return lhs.core == rhs.core;
102100
}
103101

104102
friend bool operator!=(const Fingerprint &lhs, const Fingerprint &rhs) {
105-
return lhs.Core != rhs.Core;
103+
return lhs.core != rhs.core;
106104
}
107105

108106
friend llvm::hash_code hash_value(const Fingerprint &fp) {
109-
return llvm::hash_value(fp.Core);
107+
return llvm::hash_value(fp.core);
110108
}
111109

112110
public:
@@ -115,7 +113,7 @@ class Fingerprint final {
115113
/// This fingerprint is a perfectly fine value for an MD5 hash, but it is
116114
/// completely arbitrary.
117115
static Fingerprint ZERO() {
118-
return Fingerprint("00000000000000000000000000000000");
116+
return Fingerprint(Fingerprint::Core{0, 0});
119117
}
120118

121119
private:
@@ -124,7 +122,7 @@ class Fingerprint final {
124122
///
125123
/// Very well, LLVM. A default value you shall have.
126124
friend class llvm::yaml::IO;
127-
Fingerprint() : Core(DIGEST_LENGTH, '0') {}
125+
Fingerprint() : core{Fingerprint::Core{0, 0}} {}
128126
};
129127

130128
void simple_display(llvm::raw_ostream &out, const Fingerprint &fp);

lib/AST/FineGrainedDependencyFormat.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ bool Deserializer::readFineGrainedDependencyGraph(SourceFileDepGraph &g,
232232
if (node == nullptr)
233233
llvm::report_fatal_error("Unexpected FINGERPRINT_NODE record");
234234

235-
node->setFingerprint(Fingerprint{BlobData.str()});
235+
node->setFingerprint(Fingerprint::fromString(BlobData));
236236
break;
237237
}
238238

lib/Basic/Fingerprint.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212

1313
#include "swift/Basic/Fingerprint.h"
1414
#include "swift/Basic/STLExtras.h"
15+
#include "llvm/Support/Format.h"
1516
#include "llvm/Support/raw_ostream.h"
1617

18+
#include <inttypes.h>
19+
#include <sstream>
20+
1721
using namespace swift;
1822

1923
llvm::raw_ostream &llvm::operator<<(llvm::raw_ostream &OS,
@@ -25,19 +29,26 @@ void swift::simple_display(llvm::raw_ostream &out, const Fingerprint &fp) {
2529
out << fp.getRawValue();
2630
}
2731

28-
namespace {
29-
template <class T> struct SmallStringBound;
30-
template <size_t N> struct SmallStringBound<llvm::SmallString<N>> {
31-
static constexpr size_t value = N;
32-
};
33-
};
32+
Fingerprint Fingerprint::fromString(StringRef value) {
33+
assert(value.size() == Fingerprint::DIGEST_LENGTH &&
34+
"Only supports 32-byte hash values!");
35+
auto fp = Fingerprint::ZERO();
36+
{
37+
std::istringstream s(value.drop_back(Fingerprint::DIGEST_LENGTH/2).str());
38+
s >> std::hex >> fp.core.first;
39+
}
40+
{
41+
std::istringstream s(value.drop_front(Fingerprint::DIGEST_LENGTH/2).str());
42+
s >> std::hex >> fp.core.second;
43+
}
44+
return fp;
45+
}
3446

35-
// Assert that the \c DIGEST_LENGTH value we export from the \c Fingerprint
36-
// has the right byte length. It's unlikely this value will change in LLVM,
37-
// but it's always good to have compile-time justification for a
38-
// magic constant - especially one that gets used for serialization.
39-
using MD5Digest_t =
40-
decltype (&llvm::MD5::MD5Result::digest)(llvm::MD5::MD5Result);
41-
static_assert(SmallStringBound<std::result_of<MD5Digest_t>::type>::value ==
42-
Fingerprint::DIGEST_LENGTH,
43-
"MD5 digest size does not match size expected by Fingerprint!");
47+
llvm::SmallString<Fingerprint::DIGEST_LENGTH> Fingerprint::getRawValue() const {
48+
llvm::SmallString<Fingerprint::DIGEST_LENGTH> Str;
49+
llvm::raw_svector_ostream Res(Str);
50+
Res << llvm::format_hex_no_prefix(core.first, 16);
51+
Res << llvm::format_hex_no_prefix(core.second, 16);
52+
assert(*this == Fingerprint::fromString(Str));
53+
return Str;
54+
}

lib/Serialization/ModuleFileCoreTableInfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,9 @@ class ModuleFileSharedCore::DeclFingerprintsTableInfo {
600600
static data_type ReadData(internal_key_type key, const uint8_t *data,
601601
unsigned length) {
602602
using namespace llvm::support;
603-
auto str = std::string{reinterpret_cast<const char *>(data),
604-
Fingerprint::DIGEST_LENGTH};
605-
return Fingerprint{str};
603+
auto str = llvm::StringRef{reinterpret_cast<const char *>(data),
604+
Fingerprint::DIGEST_LENGTH};
605+
return Fingerprint::fromString(str);
606606
}
607607
};
608608

tools/swift-dependency-tool/swift-dependency-tool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ template <> struct ScalarTraits<swift::Fingerprint> {
6969
os << fp.getRawValue();
7070
}
7171
static StringRef input(StringRef s, void *, swift::Fingerprint &fp) {
72-
fp = swift::Fingerprint{s.str()};
72+
fp = swift::Fingerprint::fromString(s);
7373
return StringRef();
7474
}
7575
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }

unittests/Driver/MockingFineGrainedDependencyGraphs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ mocking_fine_grained_dependency_graphs::getChangesForSimulatedLoad(
4545
assert(!swiftDeps.empty());
4646
swiftDeps.resize(Fingerprint::DIGEST_LENGTH, 'X');
4747
auto interfaceHash =
48-
interfaceHashIfNonEmpty.getValueOr(Fingerprint{swiftDeps});
48+
interfaceHashIfNonEmpty.getValueOr(Fingerprint::fromString(swiftDeps));
4949

5050
SourceManager sm;
5151
DiagnosticEngine diags(sm);

unittests/Driver/UnitTestSourceFileDepGraphFactory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void UnitTestSourceFileDepGraphFactory::addADefinedDecl(StringRef s,
5757
fingerprintString.resize(Fingerprint::DIGEST_LENGTH, 'X');
5858
const Optional<Fingerprint> fingerprint = fingerprintString.empty()
5959
? Optional<Fingerprint>()
60-
: Fingerprint{fingerprintString};
60+
: Fingerprint::fromString(fingerprintString);
6161

6262
AbstractSourceFileDepGraphFactory::addADefinedDecl(key.getValue(),
6363
fingerprint);

0 commit comments

Comments
 (0)