Skip to content

Commit 80a707d

Browse files
authored
[Coverage] Consolidate visitation logic for functions and nominal types (swiftlang#16012)
This should address an ASAN failure which arose due to the PGOMapping ASTWalker not being updated in sync with the other profiling-related walkers. rdar://39534066
1 parent ea39cea commit 80a707d

File tree

1 file changed

+45
-23
lines changed

1 file changed

+45
-23
lines changed

lib/SIL/SILProfiler.cpp

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,33 @@ std::pair<bool, Expr *> visitClosureExpr(ASTWalker &Walker,
157157
return {true, CE};
158158
}
159159

160+
/// Special logic for handling function visitation.
161+
///
162+
/// To avoid creating duplicate mappings, a function decl is only profiled if
163+
/// it hasn't been reached via recursive walk, or if it's a constructor for a
164+
/// nominal type (these are profiled in a group).
165+
///
166+
/// Apply \p Func is the function can be visited.
167+
template <typename F>
168+
bool visitFunctionDecl(ASTWalker &Walker, AbstractFunctionDecl *AFD, F Func) {
169+
bool continueWalk = Walker.Parent.isNull() || isa<ConstructorDecl>(AFD);
170+
if (continueWalk)
171+
Func();
172+
return continueWalk;
173+
}
174+
175+
/// Special logic for handling nominal type visitation.
176+
///
177+
/// Apply \p Func if the nominal type can be visited (i.e it has not been
178+
/// reached via recursive walk).
179+
template <typename F>
180+
bool visitNominalTypeDecl(ASTWalker &Walker, NominalTypeDecl *NTD, F Func) {
181+
bool continueWalk = Walker.Parent.isNull();
182+
if (continueWalk)
183+
Func();
184+
return continueWalk;
185+
}
186+
160187
/// An ASTWalker that maps ASTNodes to profiling counters.
161188
struct MapRegionCounters : public ASTWalker {
162189
/// The next counter value to assign.
@@ -176,18 +203,13 @@ struct MapRegionCounters : public ASTWalker {
176203
return false;
177204

178205
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
179-
// Don't map a nested function unless it's a constructor.
180-
bool continueWalk = Parent.isNull() || isa<ConstructorDecl>(AFD);
181-
if (continueWalk)
182-
CounterMap[AFD->getBody()] = NextCounter++;
183-
return continueWalk;
206+
return visitFunctionDecl(
207+
*this, AFD, [&] { CounterMap[AFD->getBody()] = NextCounter++; });
184208
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
185209
CounterMap[TLCD->getBody()] = NextCounter++;
186-
} else if (isa<NominalTypeDecl>(D)) {
187-
bool continueWalk = Parent.isNull();
188-
if (continueWalk)
189-
WithinNominalType = true;
190-
return continueWalk;
210+
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
211+
return visitNominalTypeDecl(*this, NTD,
212+
[&] { WithinNominalType = true; });
191213
}
192214
return true;
193215
}
@@ -411,17 +433,22 @@ struct PGOMapping : public ASTWalker {
411433
if (isUnmapped(D))
412434
return false;
413435
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
414-
auto node = AFD->getBody();
415-
CounterMap[node] = NextCounter++;
416-
auto count = loadExecutionCount(node);
417-
LoadedCounterMap[node] = count;
436+
return visitFunctionDecl(*this, AFD, [&] {
437+
auto node = AFD->getBody();
438+
CounterMap[node] = NextCounter++;
439+
auto count = loadExecutionCount(node);
440+
LoadedCounterMap[node] = count;
441+
});
418442
}
419443
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
420444
auto node = TLCD->getBody();
421445
CounterMap[node] = NextCounter++;
422446
auto count = loadExecutionCount(node);
423447
LoadedCounterMap[node] = count;
424448
}
449+
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
450+
return visitNominalTypeDecl(*this, NTD, [&] {});
451+
}
425452
return true;
426453
}
427454

@@ -768,26 +795,21 @@ struct CoverageMapping : public ASTWalker {
768795
return false;
769796

770797
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
771-
// Don't map a nested function unless it's a constructor.
772-
bool continueWalk = Parent.isNull() || isa<ConstructorDecl>(AFD);
773-
if (continueWalk) {
798+
return visitFunctionDecl(*this, AFD, [&] {
774799
CounterExpr &funcCounter = assignCounter(AFD->getBody());
775800

776801
if (isa<ConstructorDecl>(AFD))
777802
addToCounter(ParentNominalType, funcCounter);
778-
}
779-
return continueWalk;
803+
});
780804
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
781805
assignCounter(TLCD->getBody());
782806
ImplicitTopLevelBody = TLCD->getBody();
783807
} else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
784-
bool continueWalk = Parent.isNull();
785-
if (continueWalk) {
808+
return visitNominalTypeDecl(*this, NTD, [&] {
786809
ParentNominalType = NTD;
787810
assignCounter(NTD, CounterExpr::Zero());
788811
pushRegion(NTD);
789-
}
790-
return continueWalk;
812+
});
791813
}
792814
return true;
793815
}

0 commit comments

Comments
 (0)