Skip to content

Commit ac3cbe5

Browse files
committed
GSB: Add a counter and clean up getConformanceAccessPath() a bit
1 parent 08d1c33 commit ac3cbe5

File tree

2 files changed

+37
-30
lines changed

2 files changed

+37
-30
lines changed

include/swift/Basic/Statistics.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ FRONTEND_STATISTIC(Sema, NumAccessorBodiesSynthesized)
224224
/// amount of work the GSB does analyzing type signatures.
225225
FRONTEND_STATISTIC(Sema, NumGenericSignatureBuilders)
226226

227+
/// Number of conformance access paths we had to compute.
228+
FRONTEND_STATISTIC(Sema, NumConformanceAccessPathsRecorded)
229+
227230
/// Number of lazy requirement signatures registered.
228231
FRONTEND_STATISTIC(Sema, NumLazyRequirementSignatures)
229232

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4145,7 +4145,25 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41454145
return found->second;
41464146
}
41474147

4148-
FrontendStatsTracer(Context.Stats, "get-conformance-access-path");
4148+
auto *Stats = Context.Stats;
4149+
4150+
FrontendStatsTracer(Stats, "get-conformance-access-path");
4151+
4152+
auto recordPath = [&](CanType type, ProtocolDecl *proto,
4153+
ConformanceAccessPath path) {
4154+
// Add the path to the buffer.
4155+
Impl->CurrentConformanceAccessPaths.emplace_back(type, path);
4156+
4157+
// Add the path to the map.
4158+
auto key = std::make_pair(type, proto);
4159+
auto inserted = Impl->ConformanceAccessPaths.insert(
4160+
std::make_pair(key, path));
4161+
assert(inserted.second);
4162+
(void) inserted;
4163+
4164+
if (Stats)
4165+
++Stats->getFrontendCounters().NumConformanceAccessPathsRecorded;
4166+
};
41494167

41504168
// If this is the first time we're asked to look up a conformance access path,
41514169
// visit all of the root conformance requirements in our generic signature and
@@ -4163,19 +4181,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41634181
ArrayRef<ConformanceAccessPath::Entry> path(root);
41644182
ConformanceAccessPath result(Context.AllocateCopy(path));
41654183

4166-
// Add the path to the buffer.
4167-
Impl->CurrentConformanceAccessPaths.emplace_back(rootType, result);
4168-
4169-
// Add the path to the map.
4170-
auto key = std::make_pair(rootType, rootProto);
4171-
auto inserted = Impl->ConformanceAccessPaths.insert(
4172-
std::make_pair(key, result));
4173-
assert(inserted.second);
4174-
(void) inserted;
4184+
recordPath(rootType, rootProto, result);
41754185
}
41764186
}
41774187

4178-
// We keep going until we find the path we are looking for.
4188+
// We enumerate conformance access paths in lexshort order until we find the
4189+
// path whose corresponding type canonicalizes to the one we are looking for.
41794190
while (true) {
41804191
auto found = Impl->ConformanceAccessPaths.find(
41814192
std::make_pair(canType, protocol));
@@ -4185,11 +4196,13 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41854196

41864197
assert(Impl->CurrentConformanceAccessPaths.size() > 0);
41874198

4188-
// Refill the buffer.
4189-
std::vector<std::pair<CanType, ConformanceAccessPath>> morePaths;
4199+
// The buffer consists of all conformance access paths of length N.
4200+
// Swap it out with an empty buffer, and fill it with all paths of
4201+
// length N+1.
4202+
std::vector<std::pair<CanType, ConformanceAccessPath>> oldPaths;
4203+
std::swap(Impl->CurrentConformanceAccessPaths, oldPaths);
41904204

4191-
// From each path in the buffer, compute all paths of length plus one.
4192-
for (const auto &pair : Impl->CurrentConformanceAccessPaths) {
4205+
for (const auto &pair : oldPaths) {
41934206
const auto &lastElt = pair.second.back();
41944207
auto *lastProto = lastElt.second;
41954208

@@ -4213,12 +4226,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
42134226
if (!nextCanType->isTypeParameter())
42144227
continue;
42154228

4216-
// Check if we already have a conformance access path for this anchor.
4217-
auto key = std::make_pair(nextCanType, nextProto);
4218-
42194229
// If we've already seen a path for this conformance, skip it and
4220-
// don't add it to the buffer.
4221-
if (Impl->ConformanceAccessPaths.count(key))
4230+
// don't add it to the buffer. Note that because we iterate over
4231+
// conformance access paths in lexshort order, the existing
4232+
// conformance access path is shorter than the one we found just now.
4233+
if (Impl->ConformanceAccessPaths.count(
4234+
std::make_pair(nextCanType, nextProto)))
42224235
continue;
42234236

42244237
if (entries.empty()) {
@@ -4233,18 +4246,9 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
42334246
ConformanceAccessPath result = Context.AllocateCopy(entries);
42344247
entries.pop_back();
42354248

4236-
// Add the path to the buffer.
4237-
morePaths.emplace_back(nextCanType, result);
4238-
4239-
// Add the path to the map.
4240-
auto inserted = Impl->ConformanceAccessPaths.insert(
4241-
std::make_pair(key, result));
4242-
assert(inserted.second);
4243-
(void) inserted;
4249+
recordPath(nextCanType, nextProto, result);
42444250
}
42454251
}
4246-
4247-
std::swap(morePaths, Impl->CurrentConformanceAccessPaths);
42484252
}
42494253
}
42504254

0 commit comments

Comments
 (0)