mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When enabled, send a notification before/after every "compilation", which for now means `performSema`. This piggy-backs and modifies some existing code that we had for "tracing" operations in sourcekitd that unfortunately was untested. At least now some of the basic parts are tested via the new notifications. Part of rdar://38438512
89 lines
3.0 KiB
C++
89 lines
3.0 KiB
C++
//===--- Tracing.cpp ------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "SourceKit/Support/Tracing.h"
|
|
|
|
#include "swift/Frontend/Frontend.h"
|
|
|
|
#include "llvm/Support/Mutex.h"
|
|
#include "llvm/Support/YAMLTraits.h"
|
|
|
|
using namespace SourceKit;
|
|
using namespace llvm;
|
|
using swift::OptionSet;
|
|
|
|
static llvm::sys::Mutex consumersLock;
|
|
// Must hold consumersLock to access.
|
|
static std::vector<trace::TraceConsumer *> consumers;
|
|
// Must hold consumersLock to modify, but can be read any time.
|
|
static std::atomic<uint64_t> tracedOperations;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Trace commands
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Is tracing enabled
|
|
bool trace::anyEnabled() { return static_cast<bool>(tracedOperations); }
|
|
|
|
bool trace::enabled(OperationKind op) {
|
|
return OptionSet<OperationKind>(tracedOperations).contains(op);
|
|
}
|
|
|
|
// Trace start of perform sema call, returns OpId
|
|
uint64_t trace::startOperation(trace::OperationKind OpKind,
|
|
const trace::SwiftInvocation &Inv,
|
|
const trace::StringPairs &OpArgs) {
|
|
static std::atomic<uint64_t> operationId(0);
|
|
auto OpId = ++operationId;
|
|
if (trace::anyEnabled()) {
|
|
llvm::sys::ScopedLock L(consumersLock);
|
|
for (auto *consumer : consumers) {
|
|
consumer->operationStarted(OpId, OpKind, Inv, OpArgs);
|
|
}
|
|
}
|
|
return OpId;
|
|
}
|
|
|
|
// Operation previously started with startXXX has finished
|
|
void trace::operationFinished(uint64_t OpId, trace::OperationKind OpKind) {
|
|
if (trace::anyEnabled()) {
|
|
llvm::sys::ScopedLock L(consumersLock);
|
|
for (auto *consumer : consumers) {
|
|
consumer->operationFinished(OpId, OpKind);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Must be called with consumersLock held.
|
|
static void updateTracedOperations() {
|
|
OptionSet<trace::OperationKind> operations;
|
|
for (auto *consumer : consumers) {
|
|
operations |= consumer->desiredOperations();
|
|
}
|
|
// It is safe to store without a compare, because writers hold consumersLock.
|
|
tracedOperations.store(uint64_t(operations), std::memory_order_relaxed);
|
|
}
|
|
|
|
// Register trace consumer
|
|
void trace::registerConsumer(trace::TraceConsumer *Consumer) {
|
|
llvm::sys::ScopedLock L(consumersLock);
|
|
consumers.push_back(Consumer);
|
|
updateTracedOperations();
|
|
}
|
|
|
|
void trace::unregisterConsumer(trace::TraceConsumer *Consumer) {
|
|
llvm::sys::ScopedLock L(consumersLock);
|
|
consumers.erase(std::remove(consumers.begin(), consumers.end(), Consumer),
|
|
consumers.end());
|
|
updateTracedOperations();
|
|
}
|