Signposts.cpp 3.7 KB

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