Signposts.cpp 3.7 KB

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