15
15
16
16
#include " llvm/ADT/SmallString.h"
17
17
#include " llvm/ADT/Statistic.h"
18
- #include " swift/AST/Identifier.h"
19
- #include " swift/Basic/SourceLoc.h"
18
+ #include " swift/Basic/LLVM.h"
20
19
#include " swift/Basic/Timer.h"
21
20
22
21
#define SWIFT_FUNC_STAT \
@@ -56,35 +55,29 @@ namespace clang {
56
55
namespace swift {
57
56
58
57
class Decl ;
58
+ class ProtocolConformance ;
59
59
class Expr ;
60
60
class SILFunction ;
61
+ class FrontendStatsTracer ;
62
+ class SourceManager ;
61
63
62
64
class UnifiedStatsReporter {
63
65
64
66
public:
65
67
struct AlwaysOnDriverCounters
66
68
{
67
- #define DRIVER_STATISTIC (ID ) size_t ID;
69
+ #define DRIVER_STATISTIC (ID ) int64_t ID;
68
70
#include " Statistics.def"
69
71
#undef DRIVER_STATISTIC
70
72
};
71
73
72
74
struct AlwaysOnFrontendCounters
73
75
{
74
- #define FRONTEND_STATISTIC (NAME, ID ) size_t ID;
76
+ #define FRONTEND_STATISTIC (NAME, ID ) int64_t ID;
75
77
#include " Statistics.def"
76
78
#undef FRONTEND_STATISTIC
77
79
};
78
80
79
- struct AlwaysOnFrontendRecursiveSharedTimers {
80
- AlwaysOnFrontendRecursiveSharedTimers ();
81
- #define FRONTEND_RECURSIVE_SHARED_TIMER (ID ) RecursiveSharedTimer ID;
82
- #include " Statistics.def"
83
- #undef FRONTEND_RECURSIVE_SHARED_TIMER
84
-
85
- int dummyInstanceVariableToGetConstructorToParse;
86
- };
87
-
88
81
// To trace an entity, you have to provide a TraceFormatter for it. This is a
89
82
// separate type since we do not have retroactive conformances in C++, and it
90
83
// is a type that takes void* arguments since we do not have existentials
@@ -98,63 +91,67 @@ class UnifiedStatsReporter {
98
91
virtual ~TraceFormatter ();
99
92
};
100
93
101
- struct FrontendStatsTracer
102
- {
103
- UnifiedStatsReporter *Reporter;
104
- llvm::TimeRecord SavedTime;
105
- StringRef EventName;
106
- const void *Entity;
107
- const TraceFormatter *Formatter;
108
- FrontendStatsTracer (StringRef EventName,
109
- const void *Entity,
110
- const TraceFormatter *Formatter,
111
- UnifiedStatsReporter *Reporter);
112
- FrontendStatsTracer ();
113
- FrontendStatsTracer (FrontendStatsTracer&& other);
114
- FrontendStatsTracer& operator =(FrontendStatsTracer&&);
115
- ~FrontendStatsTracer ();
116
- FrontendStatsTracer (const FrontendStatsTracer&) = delete ;
117
- FrontendStatsTracer& operator =(const FrontendStatsTracer&) = delete ;
118
- };
119
-
120
94
struct FrontendStatsEvent
121
95
{
122
96
uint64_t TimeUSec;
123
97
uint64_t LiveUSec;
124
98
bool IsEntry;
125
99
StringRef EventName;
126
100
StringRef CounterName;
127
- size_t CounterDelta;
128
- size_t CounterValue;
101
+ int64_t CounterDelta;
102
+ int64_t CounterValue;
129
103
const void *Entity;
130
104
const TraceFormatter *Formatter;
131
105
};
132
106
107
+ // We only write fine-grained trace entries when the user passed
108
+ // -trace-stats-events, but we recycle the same FrontendStatsTracers to give
109
+ // us some free recursion-save phase timings whenever -trace-stats-dir is
110
+ // active at all. Reduces redundant machinery.
111
+ class RecursionSafeTimers ;
112
+
113
+ // We also keep a few banks of optional hierarchical profilers for times and
114
+ // statistics, activated with -profile-stats-events and
115
+ // -profile-stats-entities, which are part way between the detail level of the
116
+ // aggregate statistic JSON files and the fine-grained CSV traces. Naturally
117
+ // these are written in yet a different file format: the input format for
118
+ // flamegraphs.
119
+ struct StatsProfilers ;
120
+
133
121
private:
134
122
bool currentProcessExitStatusSet;
135
123
int currentProcessExitStatus;
136
124
SmallString<128 > StatsFilename;
137
125
SmallString<128 > TraceFilename;
126
+ SmallString<128 > ProfileDirname;
138
127
llvm::TimeRecord StartedTime;
128
+
129
+ // This is unique_ptr because NamedRegionTimer is non-copy-constructable.
139
130
std::unique_ptr<llvm::NamedRegionTimer> Timer;
131
+
140
132
SourceManager *SourceMgr;
141
133
clang::SourceManager *ClangSourceMgr;
142
- std::unique_ptr<AlwaysOnDriverCounters> DriverCounters;
143
- std::unique_ptr<AlwaysOnFrontendCounters> FrontendCounters;
144
- std::unique_ptr<AlwaysOnFrontendCounters> LastTracedFrontendCounters;
145
- std::vector<FrontendStatsEvent> FrontendStatsEvents;
146
- std::unique_ptr<AlwaysOnFrontendRecursiveSharedTimers>
147
- FrontendRecursiveSharedTimers;
134
+ Optional<AlwaysOnDriverCounters> DriverCounters;
135
+ Optional<AlwaysOnFrontendCounters> FrontendCounters;
136
+ Optional<AlwaysOnFrontendCounters> LastTracedFrontendCounters;
137
+ Optional<std::vector<FrontendStatsEvent>> FrontendStatsEvents;
138
+
139
+ // These are unique_ptr so we can use incomplete types here.
140
+ std::unique_ptr<RecursionSafeTimers> RecursiveTimers;
141
+ std::unique_ptr<StatsProfilers> EventProfilers;
142
+ std::unique_ptr<StatsProfilers> EntityProfilers;
148
143
149
144
void publishAlwaysOnStatsToLLVM ();
150
- void printAlwaysOnStatsAndTimers (llvm:: raw_ostream &OS);
145
+ void printAlwaysOnStatsAndTimers (raw_ostream &OS);
151
146
152
147
UnifiedStatsReporter (StringRef ProgramName,
153
148
StringRef AuxName,
154
149
StringRef Directory,
155
150
SourceManager *SM,
156
151
clang::SourceManager *CSM,
157
- bool TraceEvents);
152
+ bool TraceEvents,
153
+ bool ProfileEvents,
154
+ bool ProfileEntities);
158
155
public:
159
156
UnifiedStatsReporter (StringRef ProgramName,
160
157
StringRef ModuleName,
@@ -165,23 +162,83 @@ class UnifiedStatsReporter {
165
162
StringRef Directory,
166
163
SourceManager *SM=nullptr ,
167
164
clang::SourceManager *CSM=nullptr ,
168
- bool TraceEvents=false );
165
+ bool TraceEvents=false ,
166
+ bool ProfileEvents=false ,
167
+ bool ProfileEntities=false );
169
168
~UnifiedStatsReporter ();
170
169
171
170
AlwaysOnDriverCounters &getDriverCounters ();
172
171
AlwaysOnFrontendCounters &getFrontendCounters ();
173
- AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers ();
174
172
void noteCurrentProcessExitStatus (int );
175
- // We declare 4 explicit overloads here, but the _definitions_ live in the
176
- // upper-level files (in libswiftAST or libswiftSIL) that provide the types
177
- // being traced. If you want to trace those types, it's assumed you're linking
178
- // with the object files that define the tracer.
179
- FrontendStatsTracer getStatsTracer (StringRef EventName, const Decl *D);
180
- FrontendStatsTracer getStatsTracer (StringRef EventName, const clang::Decl*D);
181
- FrontendStatsTracer getStatsTracer (StringRef EventName, const Expr *E);
182
- FrontendStatsTracer getStatsTracer (StringRef EventName, const SILFunction *F);
183
173
void saveAnyFrontendStatsEvents (FrontendStatsTracer const &T, bool IsEntry);
184
174
};
185
175
176
+ // This is a non-nested type just to make it less work to write at call sites.
177
+ class FrontendStatsTracer
178
+ {
179
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter,
180
+ StringRef EventName,
181
+ const void *Entity,
182
+ const UnifiedStatsReporter::TraceFormatter *Formatter);
183
+
184
+ // In the general case we do not know how to format an entity for tracing.
185
+ template <typename T> static
186
+ const UnifiedStatsReporter::TraceFormatter *getTraceFormatter () {
187
+ return nullptr ;
188
+ }
189
+
190
+ public:
191
+ UnifiedStatsReporter *Reporter;
192
+ llvm::TimeRecord SavedTime;
193
+ StringRef EventName;
194
+ const void *Entity;
195
+ const UnifiedStatsReporter::TraceFormatter *Formatter;
196
+ FrontendStatsTracer ();
197
+ FrontendStatsTracer (FrontendStatsTracer&& other);
198
+ FrontendStatsTracer& operator =(FrontendStatsTracer&&);
199
+ ~FrontendStatsTracer ();
200
+ FrontendStatsTracer (const FrontendStatsTracer&) = delete ;
201
+ FrontendStatsTracer& operator =(const FrontendStatsTracer&) = delete ;
202
+
203
+ // / These are the convenience constructors you want to be calling throughout
204
+ // / the compiler: they select an appropriate trace formatter for the provided
205
+ // / entity type, and produce a tracer that's either active or inert depending
206
+ // / on whether the provided \p Reporter is null (nullptr means "tracing is
207
+ // / disabled").
208
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName);
209
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName,
210
+ const Decl *D);
211
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName,
212
+ const ProtocolConformance *P);
213
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName,
214
+ const clang::Decl *D);
215
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName,
216
+ const Expr *E);
217
+ FrontendStatsTracer (UnifiedStatsReporter *Reporter, StringRef EventName,
218
+ const SILFunction *F);
219
+ };
220
+
221
+ // In particular cases, we do know how to format traced entities: we declare
222
+ // explicit specializations of getTraceFormatter() here, matching the overloaded
223
+ // constructors of FrontendStatsTracer above, where the _definitions_ live in
224
+ // the upper-level files (in libswiftAST or libswiftSIL), and provide tracing
225
+ // for those entity types. If you want to trace those types, it's assumed you're
226
+ // linking with the object files that define the tracer.
227
+
228
+ template <> const UnifiedStatsReporter::TraceFormatter*
229
+ FrontendStatsTracer::getTraceFormatter<const Decl *>();
230
+
231
+ template <> const UnifiedStatsReporter::TraceFormatter*
232
+ FrontendStatsTracer::getTraceFormatter<const ProtocolConformance *>();
233
+
234
+ template <> const UnifiedStatsReporter::TraceFormatter*
235
+ FrontendStatsTracer::getTraceFormatter<const clang::Decl *>();
236
+
237
+ template <> const UnifiedStatsReporter::TraceFormatter*
238
+ FrontendStatsTracer::getTraceFormatter<const Expr *>();
239
+
240
+ template <> const UnifiedStatsReporter::TraceFormatter*
241
+ FrontendStatsTracer::getTraceFormatter<const SILFunction *>();
242
+
186
243
}
187
244
#endif // SWIFT_BASIC_STATISTIC_H
0 commit comments