Stop using SharedTimer except to implement FrontendStatsTracer

Name binding can trigger swiftinterface compilation, which creates
a new ASTContext and runs a compilation job. If the compiler was
run with -stats-output-dir, this could trigger an assertion because
SharedTimer is not re-entrant.

Fix this by replacing all direct uses of SharedTimer in the frontend
with FrontendStatsTracer. SharedTimer is still used to _implement_
FrontendStatsTracer, however we can collapse some of the layers in
the implementation later. Many of the usages should also become
redundant over time once more code is converted over to requests.
This commit is contained in:
Slava Pestov
2019-11-15 14:45:50 -05:00
parent 4f9877233d
commit 86f6570662
10 changed files with 40 additions and 21 deletions

View File

@@ -1139,7 +1139,8 @@ static bool performMandatorySILPasses(CompilerInvocation &Invocation,
/// These may change across compiler versions.
static void performSILOptimizations(CompilerInvocation &Invocation,
SILModule *SM) {
SharedTimer timer("SIL optimization");
FrontendStatsTracer tracer(SM->getASTContext().Stats,
"SIL optimization");
if (Invocation.getFrontendOptions().RequestedAction ==
FrontendOptions::ActionType::MergeModules ||
!Invocation.getSILOptions().shouldOptimize()) {
@@ -1182,7 +1183,8 @@ bool CompilerInstance::performSILProcessing(SILModule *silModule,
return true;
{
SharedTimer timer("SIL verification, pre-optimization");
FrontendStatsTracer tracer(silModule->getASTContext().Stats,
"SIL verification, pre-optimization");
silModule->verify();
}
@@ -1192,7 +1194,8 @@ bool CompilerInstance::performSILProcessing(SILModule *silModule,
countStatsPostSILOpt(*stats, *silModule);
{
SharedTimer timer("SIL verification, post-optimization");
FrontendStatsTracer tracer(silModule->getASTContext().Stats,
"SIL verification, post-optimization");
silModule->verify();
}

View File

@@ -877,7 +877,7 @@ performIRGeneration(IRGenOptions &Opts, ModuleDecl *M,
runIRGenPreparePasses(*SILMod, IGM);
{
SharedTimer timer("IRGen");
FrontendStatsTracer tracer(Ctx.Stats, "IRGen");
// Emit the module contents.
irgen.emitGlobalTopLevel();
@@ -948,7 +948,7 @@ performIRGeneration(IRGenOptions &Opts, ModuleDecl *M,
if (outModuleHash) {
*outModuleHash = IGM.ModuleHash;
} else {
SharedTimer timer("LLVM pipeline");
FrontendStatsTracer tracer(Ctx.Stats, "LLVM pipeline");
// Since no out module hash was set, we need to performLLVM.
if (performLLVM(Opts, &IGM.Context.Diags, nullptr, IGM.ModuleHash,
@@ -1236,7 +1236,7 @@ static void performParallelIRGeneration(
// Bail out if there are any errors.
if (Ctx.hadError()) return;
SharedTimer timer("LLVM pipeline");
FrontendStatsTracer tracer(Ctx.Stats, "LLVM pipeline");
llvm::sys::Mutex DiagMutex;

View File

@@ -119,15 +119,16 @@ void swift::performCodeCompletionSecondPass(
void Parser::performCodeCompletionSecondPass(
PersistentParserState &ParserState,
CodeCompletionCallbacksFactory &Factory) {
SharedTimer timer("CodeCompletionSecondPass");
if (!ParserState.hasCodeCompletionDelayedDeclState())
return;
auto state = ParserState.takeCodeCompletionDelayedDeclState();
auto &SF = *state->ParentContext->getParentSourceFile();
auto &SM = SF.getASTContext().SourceMgr;
auto BufferID = SM.findBufferContainingLoc(state->BodyPos.Loc);
auto &Ctx = SF.getASTContext();
FrontendStatsTracer tracer(Ctx.Stats, "CodeCompletionSecondPass");
auto BufferID = Ctx.SourceMgr.findBufferContainingLoc(state->BodyPos.Loc);
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr);
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion(

View File

@@ -140,7 +140,7 @@ static bool parseIntoSourceFileImpl(SourceFile &SF,
if (SIL)
DelayBodyParsing = false;
SharedTimer timer("Parsing");
FrontendStatsTracer tracer(SF.getASTContext().Stats, "Parsing");
Parser P(BufferID, SF, SIL ? SIL->Impl.get() : nullptr,
PersistentState, STreeCreator, DelayBodyParsing);
PrettyStackTraceParser StackTrace(P);

View File

@@ -1689,7 +1689,7 @@ void SILGenModule::emitSourceFile(SourceFile *sf) {
std::unique_ptr<SILModule>
SILModule::constructSIL(ModuleDecl *mod, TypeConverter &tc,
SILOptions &options, FileUnit *SF) {
SharedTimer timer("SILGen");
FrontendStatsTracer tracer(mod->getASTContext().Stats, "SILGen");
const DeclContext *DC;
if (SF) {
DC = SF;

View File

@@ -398,7 +398,8 @@ static void insertPrecedenceGroupDecl(NameBinder &binder, SourceFile &SF,
/// unresolved type names as well. This handles import directives and forward
/// references.
void swift::performNameBinding(SourceFile &SF, unsigned StartElem) {
SharedTimer timer("Name binding");
FrontendStatsTracer tracer(SF.getASTContext().Stats, "Name binding");
// Make sure we skip adding the standard library imports if the
// source file is empty.
if (SF.ASTStage == SourceFile::NameBound || SF.Decls.empty()) {

View File

@@ -340,7 +340,7 @@ void swift::performTypeChecking(SourceFile &SF, unsigned StartElem) {
// Could build scope maps here because the AST is stable now.
{
SharedTimer timer("Type checking and Semantic analysis");
FrontendStatsTracer tracer(Ctx.Stats, "Type checking and Semantic analysis");
if (Ctx.TypeCheckerOpts.SkipNonInlinableFunctionBodies)
// Disable this optimization if we're compiling SwiftOnoneSupport, because
@@ -388,7 +388,7 @@ void swift::performTypeChecking(SourceFile &SF, unsigned StartElem) {
SF.ASTStage = SourceFile::TypeChecked;
{
SharedTimer timer("AST verification");
FrontendStatsTracer tracer(Ctx.Stats, "AST verification");
// Verify the SourceFile.
verify(SF);

View File

@@ -4815,7 +4815,8 @@ void swift::serializeToBuffers(
assert(!StringRef::withNullAsEmpty(options.OutputPath).empty());
{
SharedTimer timer("Serialization, swiftmodule, to buffer");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftmodule, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
Serializer::writeToStream(stream, DC, M, options);
@@ -4833,7 +4834,8 @@ void swift::serializeToBuffers(
}
if (!StringRef::withNullAsEmpty(options.DocOutputPath).empty()) {
SharedTimer timer("Serialization, swiftdoc, to buffer");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftdoc, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
writeDocToStream(stream, DC, options.GroupInfoPath);
@@ -4849,7 +4851,8 @@ void swift::serializeToBuffers(
}
if (!StringRef::withNullAsEmpty(options.SourceInfoOutputPath).empty()) {
SharedTimer timer("Serialization, swiftsourceinfo, to buffer");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftsourceinfo, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
writeSourceInfoToStream(stream, DC);
@@ -4880,7 +4883,8 @@ void swift::serialize(ModuleOrSourceFile DC,
bool hadError = withOutputFile(getContext(DC).Diags,
options.OutputPath,
[&](raw_ostream &out) {
SharedTimer timer("Serialization, swiftmodule");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftmodule");
Serializer::writeToStream(out, DC, M, options);
return false;
});
@@ -4891,7 +4895,8 @@ void swift::serialize(ModuleOrSourceFile DC,
(void)withOutputFile(getContext(DC).Diags,
options.DocOutputPath,
[&](raw_ostream &out) {
SharedTimer timer("Serialization, swiftdoc");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftdoc");
writeDocToStream(out, DC, options.GroupInfoPath);
return false;
});
@@ -4901,7 +4906,8 @@ void swift::serialize(ModuleOrSourceFile DC,
(void)withOutputFile(getContext(DC).Diags,
options.SourceInfoOutputPath,
[&](raw_ostream &out) {
SharedTimer timer("Serialization, swiftsourceinfo");
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftsourceinfo");
writeSourceInfoToStream(out, DC);
return false;
});

View File

@@ -0,0 +1,2 @@
// swift-interface-format-version: 1.0
// swift-module-flags: -swift-version 5

View File

@@ -0,0 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: mkdir %t/stats
// RUN: mkdir %t/cache
// RUN: %target-swift-frontend -typecheck %s -I %S/Inputs -stats-output-dir %t/stats -module-cache-path %t/cache
import empty