Home | History | Annotate | Line # | Download | only in Support
      1 //===-- Signposts.cpp - Interval debug annotations ------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Support/Signposts.h"
     11 #include "llvm/Support/Timer.h"
     12 
     13 #include "llvm/Config/config.h"
     14 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
     15 #include "llvm/ADT/DenseMap.h"
     16 #include "llvm/Support/Mutex.h"
     17 #include <Availability.h>
     18 #include <os/signpost.h>
     19 #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
     20 
     21 using namespace llvm;
     22 
     23 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
     24 #define SIGNPOSTS_AVAILABLE()                                                  \
     25   __builtin_available(macos 10.14, iOS 12, tvOS 12, watchOS 5, *)
     26 namespace {
     27 os_log_t *LogCreator() {
     28   os_log_t *X = new os_log_t;
     29   *X = os_log_create("org.llvm.signposts", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
     30   return X;
     31 }
     32 struct LogDeleter {
     33   void operator()(os_log_t *X) const {
     34     os_release(*X);
     35     delete X;
     36   }
     37 };
     38 } // end anonymous namespace
     39 
     40 namespace llvm {
     41 class SignpostEmitterImpl {
     42   using LogPtrTy = std::unique_ptr<os_log_t, LogDeleter>;
     43   using LogTy = LogPtrTy::element_type;
     44 
     45   LogPtrTy SignpostLog;
     46   DenseMap<const void *, os_signpost_id_t> Signposts;
     47   sys::SmartMutex<true> Mutex;
     48 
     49   LogTy &getLogger() const { return *SignpostLog; }
     50   os_signpost_id_t getSignpostForObject(const void *O) {
     51     sys::SmartScopedLock<true> Lock(Mutex);
     52     const auto &I = Signposts.find(O);
     53     if (I != Signposts.end())
     54       return I->second;
     55     os_signpost_id_t ID = {};
     56     if (SIGNPOSTS_AVAILABLE()) {
     57       ID = os_signpost_id_make_with_pointer(getLogger(), O);
     58     }
     59     const auto &Inserted = Signposts.insert(std::make_pair(O, ID));
     60     return Inserted.first->second;
     61   }
     62 
     63 public:
     64   SignpostEmitterImpl() : SignpostLog(LogCreator()) {}
     65 
     66   bool isEnabled() const {
     67     if (SIGNPOSTS_AVAILABLE())
     68       return os_signpost_enabled(*SignpostLog);
     69     return false;
     70   }
     71 
     72   void startInterval(const void *O, llvm::StringRef Name) {
     73     if (isEnabled()) {
     74       if (SIGNPOSTS_AVAILABLE()) {
     75         // Both strings used here are required to be constant literal strings.
     76         os_signpost_interval_begin(getLogger(), getSignpostForObject(O),
     77                                    "LLVM Timers", "Begin %s", Name.data());
     78       }
     79     }
     80   }
     81 
     82   void endInterval(const void *O, llvm::StringRef Name) {
     83     if (isEnabled()) {
     84       if (SIGNPOSTS_AVAILABLE()) {
     85         // Both strings used here are required to be constant literal strings.
     86         os_signpost_interval_end(getLogger(), getSignpostForObject(O),
     87                                  "LLVM Timers", "End %s", Name.data());
     88       }
     89     }
     90   }
     91 };
     92 } // end namespace llvm
     93 #else
     94 /// Definition necessary for use of std::unique_ptr in SignpostEmitter::Impl.
     95 class llvm::SignpostEmitterImpl {};
     96 #endif // if LLVM_SUPPORT_XCODE_SIGNPOSTS
     97 
     98 #if LLVM_SUPPORT_XCODE_SIGNPOSTS
     99 #define HAVE_ANY_SIGNPOST_IMPL 1
    100 #else
    101 #define HAVE_ANY_SIGNPOST_IMPL 0
    102 #endif
    103 
    104 SignpostEmitter::SignpostEmitter() {
    105 #if HAVE_ANY_SIGNPOST_IMPL
    106   Impl = std::make_unique<SignpostEmitterImpl>();
    107 #endif // if !HAVE_ANY_SIGNPOST_IMPL
    108 }
    109 
    110 SignpostEmitter::~SignpostEmitter() = default;
    111 
    112 bool SignpostEmitter::isEnabled() const {
    113 #if HAVE_ANY_SIGNPOST_IMPL
    114   return Impl->isEnabled();
    115 #else
    116   return false;
    117 #endif // if !HAVE_ANY_SIGNPOST_IMPL
    118 }
    119 
    120 void SignpostEmitter::startInterval(const void *O, StringRef Name) {
    121 #if HAVE_ANY_SIGNPOST_IMPL
    122   if (Impl == nullptr)
    123     return;
    124   return Impl->startInterval(O, Name);
    125 #endif // if !HAVE_ANY_SIGNPOST_IMPL
    126 }
    127 
    128 void SignpostEmitter::endInterval(const void *O, StringRef Name) {
    129 #if HAVE_ANY_SIGNPOST_IMPL
    130   if (Impl == nullptr)
    131     return;
    132   Impl->endInterval(O, Name);
    133 #endif // if !HAVE_ANY_SIGNPOST_IMPL
    134 }
    135