mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Stats] Reduce layering violations in FrontendStatsTracer.
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
#ifndef SWIFT_BASIC_STATISTIC_H
|
||||
#define SWIFT_BASIC_STATISTIC_H
|
||||
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "swift/AST/Identifier.h"
|
||||
@@ -86,19 +85,29 @@ public:
|
||||
int dummyInstanceVariableToGetConstructorToParse;
|
||||
};
|
||||
|
||||
typedef llvm::PointerUnion4<const Decl*,
|
||||
const clang::Decl*,
|
||||
const Expr*,
|
||||
const SILFunction*> TraceEntity;
|
||||
// To trace an entity, you have to provide a TraceFormatter for it. This is a
|
||||
// separate type since we do not have retroactive conformances in C++, and it
|
||||
// is a type that takes void* arguments since we do not have existentials
|
||||
// separate from objects in C++. Pity us.
|
||||
struct TraceFormatter {
|
||||
virtual void traceName(const void *Entity, raw_ostream &OS) const = 0;
|
||||
virtual void traceLoc(const void *Entity,
|
||||
SourceManager *SourceMgr,
|
||||
clang::SourceManager *ClangSourceMgr,
|
||||
raw_ostream &OS) const = 0;
|
||||
virtual ~TraceFormatter();
|
||||
};
|
||||
|
||||
struct FrontendStatsTracer
|
||||
{
|
||||
UnifiedStatsReporter *Reporter;
|
||||
llvm::TimeRecord SavedTime;
|
||||
StringRef EventName;
|
||||
TraceEntity Entity;
|
||||
const void *Entity;
|
||||
const TraceFormatter *Formatter;
|
||||
FrontendStatsTracer(StringRef EventName,
|
||||
TraceEntity Entity,
|
||||
const void *Entity,
|
||||
const TraceFormatter *Formatter,
|
||||
UnifiedStatsReporter *Reporter);
|
||||
FrontendStatsTracer();
|
||||
FrontendStatsTracer(FrontendStatsTracer&& other);
|
||||
@@ -117,7 +126,8 @@ public:
|
||||
StringRef CounterName;
|
||||
size_t CounterDelta;
|
||||
size_t CounterValue;
|
||||
TraceEntity Entity;
|
||||
const void *Entity;
|
||||
const TraceFormatter *Formatter;
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -162,9 +172,10 @@ public:
|
||||
AlwaysOnFrontendCounters &getFrontendCounters();
|
||||
AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers();
|
||||
void noteCurrentProcessExitStatus(int);
|
||||
// We provide 4 explicit overloads here, rather than a single function that
|
||||
// takes a TraceEntity, to save all of our clients from having to include all
|
||||
// 4 headers that define these 4 forward-declared types.
|
||||
// We declare 4 explicit overloads here, but the _definitions_ live in the
|
||||
// upper-level files (in libswiftAST or libswiftSIL) that provide the types
|
||||
// being traced. If you want to trace those types, it's assumed you're linking
|
||||
// with the object files that define the tracer.
|
||||
FrontendStatsTracer getStatsTracer(StringRef EventName, const Decl *D);
|
||||
FrontendStatsTracer getStatsTracer(StringRef EventName, const clang::Decl*D);
|
||||
FrontendStatsTracer getStatsTracer(StringRef EventName, const Expr *E);
|
||||
|
||||
@@ -5658,3 +5658,37 @@ void Decl::setClangNode(ClangNode Node) {
|
||||
}
|
||||
*(ptr - 1) = Node.getOpaqueValue();
|
||||
}
|
||||
|
||||
// See swift/Basic/Statistic.h for declaration: this enables tracing Decls, is
|
||||
// defined here to avoid too much layering violation / circular linkage
|
||||
// dependency.
|
||||
|
||||
struct DeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
|
||||
void traceName(const void *Entity, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const Decl *D = static_cast<const Decl *>(Entity);
|
||||
if (auto const *VD = dyn_cast<const ValueDecl>(D)) {
|
||||
VD->getFullName().print(OS, false);
|
||||
}
|
||||
}
|
||||
void traceLoc(const void *Entity, SourceManager *SM,
|
||||
clang::SourceManager *CSM, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const Decl *D = static_cast<const Decl *>(Entity);
|
||||
D->getSourceRange().print(OS, *SM, false);
|
||||
}
|
||||
};
|
||||
|
||||
static DeclTraceFormatter TF;
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName, const Decl *D) {
|
||||
if (LastTracedFrontendCounters)
|
||||
// Return live tracer object.
|
||||
return FrontendStatsTracer(EventName, D, &TF, this);
|
||||
else
|
||||
// Return inert tracer object.
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/AST/Expr.h"
|
||||
#include "swift/Basic/Statistic.h"
|
||||
#include "swift/Basic/Unicode.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTVisitor.h"
|
||||
@@ -2276,3 +2277,32 @@ void KeyPathExpr::Component::setSubscriptIndexHashableConformances(
|
||||
llvm_unreachable("no hashable conformances for this kind");
|
||||
}
|
||||
}
|
||||
|
||||
// See swift/Basic/Statistic.h for declaration: this enables tracing Decls, is
|
||||
// defined here to avoid too much layering violation / circular linkage
|
||||
// dependency.
|
||||
|
||||
struct ExprTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
|
||||
void traceName(const void *Entity, raw_ostream &OS) const {
|
||||
// Exprs don't have names.
|
||||
}
|
||||
void traceLoc(const void *Entity, SourceManager *SM,
|
||||
clang::SourceManager *CSM, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const Expr *D = static_cast<const Expr *>(Entity);
|
||||
D->getSourceRange().print(OS, *SM, false);
|
||||
}
|
||||
};
|
||||
|
||||
static ExprTraceFormatter TF;
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName, const Expr *E) {
|
||||
if (LastTracedFrontendCounters)
|
||||
// Return live tracer object.
|
||||
return FrontendStatsTracer(EventName, E, &TF, this);
|
||||
else
|
||||
// Return inert tracer object.
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
@@ -260,19 +260,23 @@ UnifiedStatsReporter::printAlwaysOnStatsAndTimers(raw_ostream &OS) {
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer(
|
||||
StringRef EventName,
|
||||
TraceEntity Entity,
|
||||
const void *Entity,
|
||||
const TraceFormatter *Formatter,
|
||||
UnifiedStatsReporter *Reporter)
|
||||
: Reporter(Reporter),
|
||||
SavedTime(llvm::TimeRecord::getCurrentTime()),
|
||||
EventName(EventName),
|
||||
Entity(Entity)
|
||||
Entity(Entity),
|
||||
Formatter(Formatter)
|
||||
{
|
||||
if (Reporter)
|
||||
Reporter->saveAnyFrontendStatsEvents(*this, true);
|
||||
}
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer()
|
||||
: Reporter(nullptr)
|
||||
: Reporter(nullptr),
|
||||
Entity(nullptr),
|
||||
Formatter(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -284,6 +288,7 @@ UnifiedStatsReporter::FrontendStatsTracer::operator=(
|
||||
SavedTime = other.SavedTime;
|
||||
EventName = other.EventName;
|
||||
Entity = other.Entity;
|
||||
Formatter = other.Formatter;
|
||||
other.Reporter = nullptr;
|
||||
return *this;
|
||||
}
|
||||
@@ -293,7 +298,8 @@ UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer(
|
||||
: Reporter(other.Reporter),
|
||||
SavedTime(other.SavedTime),
|
||||
EventName(other.EventName),
|
||||
Entity(other.Entity)
|
||||
Entity(other.Entity),
|
||||
Formatter(other.Formatter)
|
||||
{
|
||||
other.Reporter = nullptr;
|
||||
}
|
||||
@@ -304,47 +310,6 @@ UnifiedStatsReporter::FrontendStatsTracer::~FrontendStatsTracer()
|
||||
Reporter->saveAnyFrontendStatsEvents(*this, false);
|
||||
}
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const Decl *D)
|
||||
{
|
||||
if (LastTracedFrontendCounters)
|
||||
// Return live tracer object.
|
||||
return FrontendStatsTracer(EventName, D, this);
|
||||
else
|
||||
// Return inert tracer object.
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const Expr *E) {
|
||||
if (LastTracedFrontendCounters)
|
||||
return FrontendStatsTracer(EventName, E, this);
|
||||
else
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const clang::Decl *D)
|
||||
{
|
||||
if (LastTracedFrontendCounters)
|
||||
return FrontendStatsTracer(EventName, D, this);
|
||||
else
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const SILFunction *F)
|
||||
{
|
||||
if (LastTracedFrontendCounters)
|
||||
return FrontendStatsTracer(EventName, F, this);
|
||||
else
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
void
|
||||
UnifiedStatsReporter::saveAnyFrontendStatsEvents(
|
||||
FrontendStatsTracer const& T,
|
||||
@@ -366,7 +331,7 @@ UnifiedStatsReporter::saveAnyFrontendStatsEvents(
|
||||
LastTracedFrontendCounters->NAME = C.NAME; \
|
||||
FrontendStatsEvents.emplace_back(FrontendStatsEvent { \
|
||||
NowUS, LiveUS, IsEntry, T.EventName, name, \
|
||||
delta, total, T.Entity}); \
|
||||
delta, total, T.Entity, T.Formatter}); \
|
||||
} \
|
||||
} while (0);
|
||||
#include "swift/Basic/Statistics.def"
|
||||
@@ -382,56 +347,7 @@ UnifiedStatsReporter::AlwaysOnFrontendRecursiveSharedTimers::
|
||||
dummyInstanceVariableToGetConstructorToParse(0) {
|
||||
}
|
||||
|
||||
static inline void
|
||||
printTraceEntityName(raw_ostream &OS,
|
||||
UnifiedStatsReporter::TraceEntity E) {
|
||||
if (auto const *CD = E.dyn_cast<const clang::Decl*>()) {
|
||||
if (auto const *ND = dyn_cast<const clang::NamedDecl>(CD)) {
|
||||
ND->printName(OS);
|
||||
}
|
||||
} else if (auto const *D = E.dyn_cast<const Decl*>()) {
|
||||
if (auto const *VD = dyn_cast<const ValueDecl>(D)) {
|
||||
VD->getFullName().print(OS, false);
|
||||
}
|
||||
} else if (auto const *X = E.dyn_cast<const Expr*>()) {
|
||||
// Exprs don't have names
|
||||
} else if (auto const *F = E.dyn_cast<const SILFunction*>()) {
|
||||
OS << F->getName();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
printClangShortLoc(raw_ostream &OS,
|
||||
clang::SourceManager *CSM,
|
||||
clang::SourceLocation L) {
|
||||
if (!L.isValid() || !L.isFileID())
|
||||
return;
|
||||
auto PLoc = CSM->getPresumedLoc(L);
|
||||
OS << llvm::sys::path::filename(PLoc.getFilename())
|
||||
<< ':' << PLoc.getLine()
|
||||
<< ':' << PLoc.getColumn();
|
||||
}
|
||||
|
||||
static inline void
|
||||
printTraceEntityLoc(raw_ostream &OS,
|
||||
SourceManager *SM,
|
||||
clang::SourceManager *CSM,
|
||||
UnifiedStatsReporter::TraceEntity E) {
|
||||
if (auto const *CD = E.dyn_cast<const clang::Decl*>()) {
|
||||
if (CSM) {
|
||||
auto Range = CD->getSourceRange();
|
||||
printClangShortLoc(OS, CSM, Range.getBegin());
|
||||
OS << '-';
|
||||
printClangShortLoc(OS, CSM, Range.getEnd());
|
||||
}
|
||||
} else if (auto const *D = E.dyn_cast<const Decl*>()) {
|
||||
D->getSourceRange().print(OS, *SM, false);
|
||||
} else if (auto const *X = E.dyn_cast<const Expr*>()) {
|
||||
X->getSourceRange().print(OS, *SM, false);
|
||||
} else if (auto const *F = E.dyn_cast<const SILFunction*>()) {
|
||||
F->getLocation().getSourceRange().print(OS, *SM, false);
|
||||
}
|
||||
}
|
||||
UnifiedStatsReporter::TraceFormatter::~TraceFormatter() {}
|
||||
|
||||
UnifiedStatsReporter::~UnifiedStatsReporter()
|
||||
{
|
||||
@@ -519,10 +435,12 @@ UnifiedStatsReporter::~UnifiedStatsReporter()
|
||||
<< E.CounterDelta << ','
|
||||
<< E.CounterValue << ',';
|
||||
tstream << '"';
|
||||
printTraceEntityName(tstream, E.Entity);
|
||||
if (E.Formatter)
|
||||
E.Formatter->traceName(E.Entity, tstream);
|
||||
tstream << '"' << ',';
|
||||
tstream << '"';
|
||||
printTraceEntityLoc(tstream, SourceMgr, ClangSourceMgr, E.Entity);
|
||||
if (E.Formatter)
|
||||
E.Formatter->traceLoc(E.Entity, SourceMgr, ClangSourceMgr, tstream);
|
||||
tstream << '"' << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8585,3 +8585,53 @@ ClangImporter::getEnumConstantName(const clang::EnumConstantDecl *enumConstant){
|
||||
.getBaseIdentifier();
|
||||
}
|
||||
|
||||
// See swift/Basic/Statistic.h for declaration: this enables tracing
|
||||
// clang::Decls, is defined here to avoid too much layering violation / circular
|
||||
// linkage dependency.
|
||||
|
||||
struct ClangDeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
|
||||
void traceName(const void *Entity, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const clang::Decl *CD = static_cast<const clang::Decl *>(Entity);
|
||||
if (auto const *ND = dyn_cast<const clang::NamedDecl>(CD)) {
|
||||
ND->printName(OS);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void printClangShortLoc(raw_ostream &OS,
|
||||
clang::SourceManager *CSM,
|
||||
clang::SourceLocation L) {
|
||||
if (!L.isValid() || !L.isFileID())
|
||||
return;
|
||||
auto PLoc = CSM->getPresumedLoc(L);
|
||||
OS << llvm::sys::path::filename(PLoc.getFilename()) << ':' << PLoc.getLine()
|
||||
<< ':' << PLoc.getColumn();
|
||||
}
|
||||
|
||||
void traceLoc(const void *Entity, SourceManager *SM,
|
||||
clang::SourceManager *CSM, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
if (CSM) {
|
||||
const clang::Decl *CD = static_cast<const clang::Decl *>(Entity);
|
||||
auto Range = CD->getSourceRange();
|
||||
printClangShortLoc(OS, CSM, Range.getBegin());
|
||||
OS << '-';
|
||||
printClangShortLoc(OS, CSM, Range.getEnd());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static ClangDeclTraceFormatter TF;
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const clang::Decl *D) {
|
||||
if (LastTracedFrontendCounters)
|
||||
// Return live tracer object.
|
||||
return FrontendStatsTracer(EventName, D, &TF, this);
|
||||
else
|
||||
// Return inert tracer object.
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "swift/SIL/PrettyStackTrace.h"
|
||||
#include "swift/AST/GenericEnvironment.h"
|
||||
#include "swift/Basic/OptimizationMode.h"
|
||||
#include "swift/Basic/Statistic.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
@@ -490,3 +491,37 @@ SubstitutionList SILFunction::getForwardingSubstitutions() {
|
||||
bool SILFunction::shouldVerifyOwnership() const {
|
||||
return !hasSemanticsAttr("verify.ownership.sil.never");
|
||||
}
|
||||
|
||||
// See swift/Basic/Statistic.h for declaration: this enables tracing
|
||||
// SILFunctions, is defined here to avoid too much layering violation / circular
|
||||
// linkage dependency.
|
||||
|
||||
struct SILFunctionTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
|
||||
void traceName(const void *Entity, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const SILFunction *F = static_cast<const SILFunction *>(Entity);
|
||||
OS << F->getName();
|
||||
}
|
||||
|
||||
void traceLoc(const void *Entity, SourceManager *SM,
|
||||
clang::SourceManager *CSM, raw_ostream &OS) const {
|
||||
if (!Entity)
|
||||
return;
|
||||
const SILFunction *F = static_cast<const SILFunction *>(Entity);
|
||||
F->getLocation().getSourceRange().print(OS, *SM, false);
|
||||
}
|
||||
};
|
||||
|
||||
static SILFunctionTraceFormatter TF;
|
||||
|
||||
UnifiedStatsReporter::FrontendStatsTracer
|
||||
UnifiedStatsReporter::getStatsTracer(StringRef EventName,
|
||||
const SILFunction *F) {
|
||||
if (LastTracedFrontendCounters)
|
||||
// Return live tracer object.
|
||||
return FrontendStatsTracer(EventName, F, &TF, this);
|
||||
else
|
||||
// Return inert tracer object.
|
||||
return FrontendStatsTracer();
|
||||
}
|
||||
|
||||
9
test/Misc/stats_dir_tracer.swift
Normal file
9
test/Misc/stats_dir_tracer.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: rm -rf %t && mkdir -p %t
|
||||
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events
|
||||
// RUN: %FileCheck -input-file %t/*.csv %s
|
||||
|
||||
// CHECK: {{"Sema.NumTypesDeserialized"}}
|
||||
|
||||
public func foo() {
|
||||
print("hello")
|
||||
}
|
||||
Reference in New Issue
Block a user