@@ -41,63 +41,68 @@ static bool doesClosureHaveBody(AbstractClosureExpr *ACE) {
41
41
return false ;
42
42
}
43
43
44
- // / Check whether a root AST node is unmapped, i.e not profiled.
45
- static bool isUnmapped (ASTNode N) {
46
- // Do not map AST nodes with invalid source locations.
44
+ // / Check whether a root AST node should be profiled.
45
+ static bool shouldProfile (ASTNode N) {
46
+ // Do not profile AST nodes with invalid source locations.
47
47
if (N.getStartLoc ().isInvalid () || N.getEndLoc ().isInvalid ()) {
48
48
LLVM_DEBUG (llvm::dbgs ()
49
49
<< " Skipping ASTNode: invalid start/end locations\n " );
50
- return true ;
50
+ return false ;
51
51
}
52
52
53
53
if (auto *E = N.dyn_cast <Expr *>()) {
54
54
if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
55
- // Only map closure expressions with bodies.
55
+ // Only profile closure expressions with bodies.
56
56
if (!doesClosureHaveBody (CE)) {
57
57
LLVM_DEBUG (llvm::dbgs () << " Skipping ASTNode: closure without body\n " );
58
- return true ;
58
+ return false ;
59
59
}
60
60
61
- // Don't map implicit closures, unless they're autoclosures.
61
+ // Don't profile implicit closures, unless they're autoclosures.
62
62
if (!isa<AutoClosureExpr>(CE) && CE->isImplicit ()) {
63
63
LLVM_DEBUG (llvm::dbgs () << " Skipping ASTNode: implicit closure expr\n " );
64
- return true ;
64
+ return false ;
65
65
}
66
66
}
67
67
68
- // Map all other kinds of expressions.
69
- return false ;
68
+ // Profile all other kinds of expressions.
69
+ return true ;
70
70
}
71
71
72
72
auto *D = N.get <Decl *>();
73
73
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
74
- // Don't map functions without bodies.
74
+ // Don't profile functions without bodies.
75
75
if (!AFD->hasBody ()) {
76
76
LLVM_DEBUG (llvm::dbgs () << " Skipping ASTNode: function without body\n " );
77
- return true ;
77
+ return false ;
78
78
}
79
79
80
- // Map implicit getters for lazy variables.
80
+ // Profile implicit getters for lazy variables.
81
81
if (auto *accessor = dyn_cast<AccessorDecl>(AFD)) {
82
82
if (accessor->isImplicit () && accessor->isGetter () &&
83
83
accessor->getStorage ()->getAttrs ().hasAttribute <LazyAttr>()) {
84
- return false ;
84
+ return true ;
85
85
}
86
86
}
87
87
}
88
88
89
89
// Skip any remaining implicit, or otherwise unsupported decls.
90
90
if (D->isImplicit () || isa<EnumCaseDecl>(D)) {
91
91
LLVM_DEBUG (llvm::dbgs () << " Skipping ASTNode: implicit/unsupported decl\n " );
92
- return true ;
92
+ return false ;
93
93
}
94
94
95
- return false ;
95
+ return true ;
96
96
}
97
97
98
98
namespace swift {
99
99
bool doesASTRequireProfiling (SILModule &M, ASTNode N) {
100
- return M.getOptions ().GenerateProfile && !isUnmapped (N);
100
+ // If profiling isn't enabled, don't profile anything.
101
+ auto &Opts = M.getOptions ();
102
+ if (Opts.UseProfile .empty () && !Opts.GenerateProfile )
103
+ return false ;
104
+
105
+ return shouldProfile (N);
101
106
}
102
107
} // namespace swift
103
108
@@ -152,7 +157,7 @@ static bool canCreateProfilerForAST(ASTNode N, SILDeclRef forDecl) {
152
157
153
158
SILProfiler *SILProfiler::create (SILModule &M, ASTNode N, SILDeclRef Ref) {
154
159
const auto &Opts = M.getOptions ();
155
- if (!doesASTRequireProfiling (M, N) && Opts. UseProfile . empty () )
160
+ if (!doesASTRequireProfiling (M, N))
156
161
return nullptr ;
157
162
158
163
if (!canCreateProfilerForAST (N, Ref)) {
@@ -185,44 +190,53 @@ visitFunctionDecl(ASTWalker &Walker, AbstractFunctionDecl *AFD, F Func) {
185
190
return ASTWalker::Action::SkipChildren ();
186
191
}
187
192
188
- // / Whether to skip visitation of an expression. If the expression should be
189
- // / skipped, a walker action is returned that determines whether or not the
190
- // / children should also be skipped.
191
- static Optional<ASTWalker::PreWalkResult<Expr *>>
192
- shouldSkipExpr (Expr *E, ASTWalker::ParentTy Parent) {
193
+ // / Whether to walk the children of a given expression.
194
+ ASTWalker::PreWalkResult<Expr *>
195
+ shouldWalkIntoExpr (Expr *E, ASTWalker::ParentTy Parent, SILDeclRef Constant) {
193
196
using Action = ASTWalker::Action;
194
- using Result = ASTWalker::PreWalkResult<Expr *>;
195
197
196
198
// Profiling for closures should be handled separately. Do not visit
197
199
// closure expressions twice.
198
- if (isa<AbstractClosureExpr>(E) && !Parent.isNull ())
199
- return Result (Action::SkipChildren (E));
200
-
201
- // Expressions with no location should be skipped, but we still want to visit
202
- // their children.
203
- if (E->getStartLoc ().isInvalid () || E->getEndLoc ().isInvalid ())
204
- return Result (Action::Continue (E));
200
+ if (isa<AbstractClosureExpr>(E)) {
201
+ // A non-null parent means we have a closure child, which we will visit
202
+ // separately. Even if the parent is null, don't walk into a closure if the
203
+ // SILDeclRef is not for a closure, as it could be for a property
204
+ // initializer instead.
205
+ if (!Parent.isNull () || !Constant || !Constant.getAbstractClosureExpr ())
206
+ return Action::SkipChildren (E);
207
+ }
208
+ return Action::Continue (E);
209
+ }
205
210
206
- return None;
211
+ // / Whether to skip visitation of an expression. The children may however still
212
+ // / be visited
213
+ bool shouldSkipExpr (Expr *E) {
214
+ // Expressions with no location should be skipped.
215
+ return E->getStartLoc ().isInvalid () || E->getEndLoc ().isInvalid ();
207
216
}
208
217
209
- // / Whether the children of an unmapped decl should still be walked.
210
- static bool shouldWalkUnmappedDecl (const Decl *D) {
218
+ // / Whether the children of a decl that isn't explicitly handled should be
219
+ // / walked.
220
+ static bool shouldWalkIntoUnhandledDecl (const Decl *D) {
211
221
// We want to walk into the initializer for a pattern binding decl. This
212
222
// allows us to map LazyInitializerExprs.
213
223
return isa<PatternBindingDecl>(D);
214
224
}
215
225
216
226
// / An ASTWalker that maps ASTNodes to profiling counters.
217
227
struct MapRegionCounters : public ASTWalker {
228
+ // / The SIL function being profiled.
229
+ SILDeclRef Constant;
230
+
218
231
// / The next counter value to assign.
219
232
unsigned NextCounter = 0 ;
220
233
221
234
// / The map of statements to counters.
222
235
llvm::DenseMap<ASTNode, unsigned > &CounterMap;
223
236
224
- MapRegionCounters (llvm::DenseMap<ASTNode, unsigned > &CounterMap)
225
- : CounterMap(CounterMap) {}
237
+ MapRegionCounters (SILDeclRef Constant,
238
+ llvm::DenseMap<ASTNode, unsigned > &CounterMap)
239
+ : Constant(Constant), CounterMap(CounterMap) {}
226
240
227
241
LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
228
242
// We want to walk lazy initializers present in the synthesized getter for
@@ -247,15 +261,13 @@ struct MapRegionCounters : public ASTWalker {
247
261
}
248
262
249
263
PreWalkAction walkToDeclPre (Decl *D) override {
250
- if (isUnmapped (D))
251
- return Action::VisitChildrenIf (shouldWalkUnmappedDecl (D));
252
-
253
264
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
254
265
return visitFunctionDecl (*this , AFD, [&] { mapRegion (AFD->getBody ()); });
255
266
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
256
267
mapRegion (TLCD->getBody ());
268
+ return Action::Continue ();
257
269
}
258
- return Action::Continue ( );
270
+ return Action::VisitChildrenIf ( shouldWalkIntoUnhandledDecl (D) );
259
271
}
260
272
261
273
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
@@ -283,8 +295,8 @@ struct MapRegionCounters : public ASTWalker {
283
295
}
284
296
285
297
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
286
- if (auto SkipAction = shouldSkipExpr (E, Parent ))
287
- return *SkipAction ;
298
+ if (shouldSkipExpr (E))
299
+ return shouldWalkIntoExpr (E, Parent, Constant) ;
288
300
289
301
// If AST visitation begins with an expression, the counter map must be
290
302
// empty. Set up a counter for the root.
@@ -300,7 +312,7 @@ struct MapRegionCounters : public ASTWalker {
300
312
if (isa<LazyInitializerExpr>(E))
301
313
mapRegion (E);
302
314
303
- return Action::Continue (E );
315
+ return shouldWalkIntoExpr (E, Parent, Constant );
304
316
}
305
317
};
306
318
@@ -520,6 +532,9 @@ class SourceMappingRegion {
520
532
// / CoverageMapping walker to recompute the correct counter information
521
533
// / for this walker.
522
534
struct PGOMapping : public ASTWalker {
535
+ // / The SIL function being profiled.
536
+ SILDeclRef Constant;
537
+
523
538
// / The counter indices for AST nodes.
524
539
const llvm::DenseMap<ASTNode, unsigned > &CounterMap;
525
540
@@ -530,11 +545,12 @@ struct PGOMapping : public ASTWalker {
530
545
llvm::DenseMap<ASTNode, ProfileCounter> &LoadedCounterMap;
531
546
llvm::DenseMap<ASTNode, ASTNode> &CondToParentMap;
532
547
533
- PGOMapping (const llvm::DenseMap<ASTNode, unsigned > &CounterMap,
548
+ PGOMapping (SILDeclRef Constant,
549
+ const llvm::DenseMap<ASTNode, unsigned > &CounterMap,
534
550
const llvm::InstrProfRecord &LoadedCounts,
535
551
llvm::DenseMap<ASTNode, ProfileCounter> &LoadedCounterMap,
536
552
llvm::DenseMap<ASTNode, ASTNode> &RegionCondToParentMap)
537
- : CounterMap(CounterMap), LoadedCounts(LoadedCounts),
553
+ : Constant(Constant), CounterMap(CounterMap), LoadedCounts(LoadedCounts),
538
554
LoadedCounterMap (LoadedCounterMap),
539
555
CondToParentMap(RegionCondToParentMap) {}
540
556
@@ -596,17 +612,16 @@ struct PGOMapping : public ASTWalker {
596
612
}
597
613
598
614
PreWalkAction walkToDeclPre (Decl *D) override {
599
- if (isUnmapped (D))
600
- return Action::VisitChildrenIf (shouldWalkUnmappedDecl (D));
601
615
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
602
616
return visitFunctionDecl (*this , AFD, [&] {
603
617
setKnownExecutionCount (AFD->getBody ());
604
618
});
605
619
}
606
- if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D))
620
+ if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
607
621
setKnownExecutionCount (TLCD->getBody ());
608
-
609
- return Action::Continue ();
622
+ return Action::Continue ();
623
+ }
624
+ return Action::VisitChildrenIf (shouldWalkIntoUnhandledDecl (D));
610
625
}
611
626
612
627
LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
@@ -671,8 +686,8 @@ struct PGOMapping : public ASTWalker {
671
686
}
672
687
673
688
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
674
- if (auto SkipAction = shouldSkipExpr (E, Parent ))
675
- return *SkipAction ;
689
+ if (shouldSkipExpr (E))
690
+ return shouldWalkIntoExpr (E, Parent, Constant) ;
676
691
677
692
unsigned parent = getParentCounter ();
678
693
@@ -701,7 +716,7 @@ struct PGOMapping : public ASTWalker {
701
716
if (isa<LazyInitializerExpr>(E))
702
717
setKnownExecutionCount (E);
703
718
704
- return Action::Continue (E );
719
+ return shouldWalkIntoExpr (E, Parent, Constant );
705
720
}
706
721
};
707
722
@@ -712,6 +727,9 @@ struct CoverageMapping : public ASTWalker {
712
727
private:
713
728
const SourceManager &SM;
714
729
730
+ // / The SIL function being profiled.
731
+ SILDeclRef Constant;
732
+
715
733
// / Storage for counter expressions.
716
734
std::forward_list<CounterExpr> Exprs;
717
735
@@ -935,7 +953,8 @@ struct CoverageMapping : public ASTWalker {
935
953
}
936
954
937
955
public:
938
- CoverageMapping (const SourceManager &SM) : SM(SM) {}
956
+ CoverageMapping (const SourceManager &SM, SILDeclRef Constant)
957
+ : SM(SM), Constant(Constant) {}
939
958
940
959
LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
941
960
// We want to walk lazy initializers present in the synthesized getter for
@@ -969,18 +988,16 @@ struct CoverageMapping : public ASTWalker {
969
988
}
970
989
971
990
PreWalkAction walkToDeclPre (Decl *D) override {
972
- if (isUnmapped (D))
973
- return Action::VisitChildrenIf (shouldWalkUnmappedDecl (D));
974
-
975
991
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
976
992
return visitFunctionDecl (*this , AFD, [&] {
977
993
assignCounter (AFD->getBody ());
978
994
});
979
995
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
980
996
assignCounter (TLCD->getBody ());
981
997
ImplicitTopLevelBody = TLCD->getBody ();
998
+ return Action::Continue ();
982
999
}
983
- return Action::Continue ( );
1000
+ return Action::VisitChildrenIf ( shouldWalkIntoUnhandledDecl (D) );
984
1001
}
985
1002
986
1003
PostWalkAction walkToDeclPost (Decl *D) override {
@@ -1176,8 +1193,8 @@ struct CoverageMapping : public ASTWalker {
1176
1193
}
1177
1194
1178
1195
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
1179
- if (auto SkipAction = shouldSkipExpr (E, Parent ))
1180
- return *SkipAction ;
1196
+ if (shouldSkipExpr (E))
1197
+ return shouldWalkIntoExpr (E, Parent, Constant) ;
1181
1198
1182
1199
// If we're in an 'incomplete' region, update it to include this node. This
1183
1200
// ensures we only create the region if needed.
@@ -1205,11 +1222,19 @@ struct CoverageMapping : public ASTWalker {
1205
1222
assignCounter (IE->getElseExpr (),
1206
1223
CounterExpr::Sub (getCurrentCounter (), ThenCounter));
1207
1224
}
1208
- return Action::Continue (E);
1225
+ auto WalkResult = shouldWalkIntoExpr (E, Parent, Constant);
1226
+ if (WalkResult.Action .Action == PreWalkAction::SkipChildren) {
1227
+ // We need to manually pop the region here as the ASTWalker won't call
1228
+ // the post-visitation.
1229
+ // FIXME: The ASTWalker should do a post-visit.
1230
+ if (hasCounter (E))
1231
+ popRegions (E);
1232
+ }
1233
+ return WalkResult;
1209
1234
}
1210
1235
1211
1236
PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
1212
- if (shouldSkipExpr (E, Parent ))
1237
+ if (shouldSkipExpr (E))
1213
1238
return Action::Continue (E);
1214
1239
1215
1240
if (hasCounter (E))
@@ -1248,7 +1273,7 @@ void SILProfiler::assignRegionCounters() {
1248
1273
1249
1274
CurrentFileName = getCurrentFileName (Root, forDecl);
1250
1275
1251
- MapRegionCounters Mapper (RegionCounterMap);
1276
+ MapRegionCounters Mapper (forDecl, RegionCounterMap);
1252
1277
1253
1278
std::string CurrentFuncName;
1254
1279
FormalLinkage CurrentFuncLinkage;
@@ -1284,7 +1309,7 @@ void SILProfiler::assignRegionCounters() {
1284
1309
PGOFuncHash = 0x0 ;
1285
1310
1286
1311
if (EmitCoverageMapping) {
1287
- CoverageMapping Coverage (SM);
1312
+ CoverageMapping Coverage (SM, forDecl );
1288
1313
Root.walk (Coverage);
1289
1314
CovMap =
1290
1315
Coverage.emitSourceRegions (M, CurrentFuncName, PGOFuncName, PGOFuncHash,
@@ -1301,7 +1326,7 @@ void SILProfiler::assignRegionCounters() {
1301
1326
llvm::dbgs () << PGOFuncName << " \n " ;
1302
1327
return ;
1303
1328
}
1304
- PGOMapping pgoMapper (RegionCounterMap, LoadedCounts.get (),
1329
+ PGOMapping pgoMapper (forDecl, RegionCounterMap, LoadedCounts.get (),
1305
1330
RegionLoadedCounterMap, RegionCondToParentMap);
1306
1331
Root.walk (pgoMapper);
1307
1332
}
0 commit comments