Repository: electron/electron
Pull request: feat: add support for `--js-flags=--perf-prof` on macOS

#### Description of Change

<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->
allows for profiling of macOS electron apps using https://github.com/mstange/samply,
which can capture cpu usage for an entire process tree, including
both c/c++ frames and interpreted + jit-compiled JS stack frames

Backport of #46757

cc #46759

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [ ] relevant API documentation, tutorials, and examples are updated and follow the [documentation style guide](https://github.com/electron/electron/blob/main/docs/development/style-guide.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Added support for `--js-flags=--perf-prof` on macOS


Changed files:
filename: patches/v8/.patches
patch: @@ -1,2 +1,3 @@
 chore_allow_customizing_microtask_policy_per_context.patch
 deps_add_v8_object_setinternalfieldfornodecore.patch
+enable_--perf-prof_flag_on_macos.patch

filename: patches/v8/enable_--perf-prof_flag_on_macos.patch
patch: @@ -0,0 +1,465 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: yangwenming <yangwenming@bytedance.com>
+Date: Wed, 23 Apr 2025 22:14:00 +0800
+Subject: Enable --perf-prof flag on MacOS
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+MacOS actually can share the implementation of {PerfJitLogger} with
+Linux. From the issue 40112126, only Fuzzer tests on Windows ran
+into UNREACHABLE/FATAL because of the unimplemented {PerfJitLogger}.
+This CL enables the flag --perf-prof on MacOS.
+
+Bug: 403765219
+Change-Id: I97871fbcc0cb9890c51ca14fd7a6e65bd0e3c0d2
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6385655
+Reviewed-by: Clemens Backes <clemensb@chromium.org>
+Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
+Auto-Submit: 杨文明 <yangwenming@bytedance.com>
+Commit-Queue: Clemens Backes <clemensb@chromium.org>
+Cr-Commit-Position: refs/heads/main@{#99885}
+
+diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc
+index 023cee8098e232b67acbed311c899732854cc01f..ad557facb9d46814273a67136878c9fbdfe6197e 100644
+--- a/src/compiler/backend/code-generator.cc
++++ b/src/compiler/backend/code-generator.cc
+@@ -435,7 +435,7 @@ void CodeGenerator::AssembleCode() {
+     }
+   }
+ 
+-  // The LinuxPerfJitLogger logs code up until here, excluding the safepoint
++  // The PerfJitLogger logs code up until here, excluding the safepoint
+   // table. Resolve the unwinding info now so it is aware of the same code
+   // size as reported by perf.
+   unwinding_info_writer_.Finish(masm()->pc_offset());
+diff --git a/src/diagnostics/perf-jit.cc b/src/diagnostics/perf-jit.cc
+index 6af13fe8cf29c4ab10fab2107d10de7df8722f10..c509e4220c8e164594665afdea97cc75f13da05c 100644
+--- a/src/diagnostics/perf-jit.cc
++++ b/src/diagnostics/perf-jit.cc
+@@ -30,8 +30,8 @@
+ #include "src/common/assert-scope.h"
+ #include "src/flags/flags.h"
+ 
+-// Only compile the {LinuxPerfJitLogger} on Linux.
+-#if V8_OS_LINUX
++// Only compile the {PerfJitLogger} on Linux & Darwin.
++#if V8_OS_LINUX || V8_OS_DARWIN
+ 
+ #include <fcntl.h>
+ #include <sys/mman.h>
+@@ -118,22 +118,22 @@ struct PerfJitCodeUnwindingInfo : PerfJitBase {
+   // Followed by size_ - sizeof(PerfJitCodeUnwindingInfo) bytes of data.
+ };
+ 
+-const char LinuxPerfJitLogger::kFilenameFormatString[] = "%s/jit-%d.dump";
++const char PerfJitLogger::kFilenameFormatString[] = "%s/jit-%d.dump";
+ 
+ // Extra padding for the PID in the filename
+-const int LinuxPerfJitLogger::kFilenameBufferPadding = 16;
++const int PerfJitLogger::kFilenameBufferPadding = 16;
+ 
+ static const char kStringTerminator[] = {'\0'};
+ 
+ // The following static variables are protected by
+ // GetFileMutex().
+-int LinuxPerfJitLogger::process_id_ = 0;
+-uint64_t LinuxPerfJitLogger::reference_count_ = 0;
+-void* LinuxPerfJitLogger::marker_address_ = nullptr;
+-uint64_t LinuxPerfJitLogger::code_index_ = 0;
+-FILE* LinuxPerfJitLogger::perf_output_handle_ = nullptr;
++int PerfJitLogger::process_id_ = 0;
++uint64_t PerfJitLogger::reference_count_ = 0;
++void* PerfJitLogger::marker_address_ = nullptr;
++uint64_t PerfJitLogger::code_index_ = 0;
++FILE* PerfJitLogger::perf_output_handle_ = nullptr;
+ 
+-void LinuxPerfJitLogger::OpenJitDumpFile() {
++void PerfJitLogger::OpenJitDumpFile() {
+   // Open the perf JIT dump file.
+   perf_output_handle_ = nullptr;
+ 
+@@ -153,8 +153,17 @@ void LinuxPerfJitLogger::OpenJitDumpFile() {
+   if (v8_flags.perf_prof_delete_file)
+     CHECK_EQ(0, unlink(perf_dump_name.begin()));
+ 
++  // On Linux, call OpenMarkerFile so that perf knows about the file path via
++  // an MMAP record.
++  // On macOS, don't call OpenMarkerFile because samply has already detected
++  // the file path during the call to `open` above (it interposes `open` with
++  // a preloaded library), and because the mmap call can be slow.
++#if V8_OS_DARWIN
++  marker_address_ = nullptr;
++#else
+   marker_address_ = OpenMarkerFile(fd);
+   if (marker_address_ == nullptr) return;
++#endif
+ 
+   perf_output_handle_ = fdopen(fd, "w+");
+   if (perf_output_handle_ == nullptr) return;
+@@ -162,13 +171,13 @@ void LinuxPerfJitLogger::OpenJitDumpFile() {
+   setvbuf(perf_output_handle_, nullptr, _IOFBF, kLogBufferSize);
+ }
+ 
+-void LinuxPerfJitLogger::CloseJitDumpFile() {
++void PerfJitLogger::CloseJitDumpFile() {
+   if (perf_output_handle_ == nullptr) return;
+   base::Fclose(perf_output_handle_);
+   perf_output_handle_ = nullptr;
+ }
+ 
+-void* LinuxPerfJitLogger::OpenMarkerFile(int fd) {
++void* PerfJitLogger::OpenMarkerFile(int fd) {
+   long page_size = sysconf(_SC_PAGESIZE);  // NOLINT(runtime/int)
+   if (page_size == -1) return nullptr;
+ 
+@@ -180,15 +189,14 @@ void* LinuxPerfJitLogger::OpenMarkerFile(int fd) {
+   return (marker_address == MAP_FAILED) ? nullptr : marker_address;
+ }
+ 
+-void LinuxPerfJitLogger::CloseMarkerFile(void* marker_address) {
++void PerfJitLogger::CloseMarkerFile(void* marker_address) {
+   if (marker_address == nullptr) return;
+   long page_size = sysconf(_SC_PAGESIZE);  // NOLINT(runtime/int)
+   if (page_size == -1) return;
+   munmap(marker_address, page_size);
+ }
+ 
+-LinuxPerfJitLogger::LinuxPerfJitLogger(Isolate* isolate)
+-    : CodeEventLogger(isolate) {
++PerfJitLogger::PerfJitLogger(Isolate* isolate) : CodeEventLogger(isolate) {
+   base::LockGuard<base::RecursiveMutex> guard_file(GetFileMutex().Pointer());
+   process_id_ = base::OS::GetCurrentProcessId();
+ 
+@@ -201,7 +209,7 @@ LinuxPerfJitLogger::LinuxPerfJitLogger(Isolate* isolate)
+   }
+ }
+ 
+-LinuxPerfJitLogger::~LinuxPerfJitLogger() {
++PerfJitLogger::~PerfJitLogger() {
+   base::LockGuard<base::RecursiveMutex> guard_file(GetFileMutex().Pointer());
+ 
+   reference_count_--;
+@@ -211,16 +219,11 @@ LinuxPerfJitLogger::~LinuxPerfJitLogger() {
+   }
+ }
+ 
+-uint64_t LinuxPerfJitLogger::GetTimestamp() {
+-  struct timespec ts;
+-  int result = clock_gettime(CLOCK_MONOTONIC, &ts);
+-  DCHECK_EQ(0, result);
+-  USE(result);
+-  static const uint64_t kNsecPerSec = 1000000000;
+-  return (ts.tv_sec * kNsecPerSec) + ts.tv_nsec;
++uint64_t PerfJitLogger::GetTimestamp() {
++  return base::TimeTicks::Now().since_origin().InNanoseconds();
+ }
+ 
+-void LinuxPerfJitLogger::LogRecordedBuffer(
++void PerfJitLogger::LogRecordedBuffer(
+     Tagged<AbstractCode> abstract_code,
+     MaybeDirectHandle<SharedFunctionInfo> maybe_sfi, const char* name,
+     size_t length) {
+@@ -264,8 +267,8 @@ void LinuxPerfJitLogger::LogRecordedBuffer(
+ }
+ 
+ #if V8_ENABLE_WEBASSEMBLY
+-void LinuxPerfJitLogger::LogRecordedBuffer(const wasm::WasmCode* code,
+-                                           const char* name, size_t length) {
++void PerfJitLogger::LogRecordedBuffer(const wasm::WasmCode* code,
++                                      const char* name, size_t length) {
+   base::LockGuard<base::RecursiveMutex> guard_file(GetFileMutex().Pointer());
+ 
+   if (perf_output_handle_ == nullptr) return;
+@@ -277,10 +280,9 @@ void LinuxPerfJitLogger::LogRecordedBuffer(const wasm::WasmCode* code,
+ }
+ #endif  // V8_ENABLE_WEBASSEMBLY
+ 
+-void LinuxPerfJitLogger::WriteJitCodeLoadEntry(const uint8_t* code_pointer,
+-                                               uint32_t code_size,
+-                                               const char* name,
+-                                               size_t name_length) {
++void PerfJitLogger::WriteJitCodeLoadEntry(const uint8_t* code_pointer,
++                                          uint32_t code_size, const char* name,
++                                          size_t name_length) {
+   PerfJitCodeLoad code_load;
+   code_load.event_ = PerfJitCodeLoad::kLoad;
+   code_load.size_ =
+@@ -342,8 +344,8 @@ SourcePositionInfo GetSourcePositionInfo(
+ 
+ }  // namespace
+ 
+-void LinuxPerfJitLogger::LogWriteDebugInfo(
+-    Tagged<Code> code, DirectHandle<SharedFunctionInfo> shared) {
++void PerfJitLogger::LogWriteDebugInfo(Tagged<Code> code,
++                                      DirectHandle<SharedFunctionInfo> shared) {
+   // Line ends of all scripts have been initialized prior to this.
+   DisallowGarbageCollection no_gc;
+   // The WasmToJS wrapper stubs have source position entries.
+@@ -425,7 +427,7 @@ void LinuxPerfJitLogger::LogWriteDebugInfo(
+ }
+ 
+ #if V8_ENABLE_WEBASSEMBLY
+-void LinuxPerfJitLogger::LogWriteDebugInfo(const wasm::WasmCode* code) {
++void PerfJitLogger::LogWriteDebugInfo(const wasm::WasmCode* code) {
+   if (code->IsAnonymous()) {
+     return;
+   }
+@@ -497,7 +499,7 @@ void LinuxPerfJitLogger::LogWriteDebugInfo(const wasm::WasmCode* code) {
+ }
+ #endif  // V8_ENABLE_WEBASSEMBLY
+ 
+-void LinuxPerfJitLogger::LogWriteUnwindingInfo(Tagged<Code> code) {
++void PerfJitLogger::LogWriteUnwindingInfo(Tagged<Code> code) {
+   PerfJitCodeUnwindingInfo unwinding_info_header;
+   unwinding_info_header.event_ = PerfJitCodeLoad::kUnwindingInfo;
+   unwinding_info_header.time_stamp_ = GetTimestamp();
+@@ -532,13 +534,13 @@ void LinuxPerfJitLogger::LogWriteUnwindingInfo(Tagged<Code> code) {
+   LogWriteBytes(padding_bytes, padding_size);
+ }
+ 
+-void LinuxPerfJitLogger::LogWriteBytes(const char* bytes, size_t size) {
++void PerfJitLogger::LogWriteBytes(const char* bytes, size_t size) {
+   size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
+   DCHECK_EQ(size, rv);
+   USE(rv);
+ }
+ 
+-void LinuxPerfJitLogger::LogWriteHeader() {
++void PerfJitLogger::LogWriteHeader() {
+   DCHECK_NOT_NULL(perf_output_handle_);
+   PerfJitHeader header;
+ 
+@@ -559,4 +561,4 @@ void LinuxPerfJitLogger::LogWriteHeader() {
+ }  // namespace internal
+ }  // namespace v8
+ 
+-#endif  // V8_OS_LINUX
++#endif  // V8_OS_LINUX || V8_OS_DARWIN
+diff --git a/src/diagnostics/perf-jit.h b/src/diagnostics/perf-jit.h
+index 84f669ca3f98690264e1ee05bfe6842c47bbcbd0..e95c3bb6fe0f445904df9dff3e6fe35735cd7045 100644
+--- a/src/diagnostics/perf-jit.h
++++ b/src/diagnostics/perf-jit.h
+@@ -30,8 +30,8 @@
+ 
+ #include "include/v8config.h"
+ 
+-// {LinuxPerfJitLogger} is only implemented on Linux.
+-#if V8_OS_LINUX
++// {PerfJitLogger} is only implemented on Linux & Darwin.
++#if V8_OS_LINUX || V8_OS_DARWIN
+ 
+ #include "src/logging/log.h"
+ 
+@@ -39,10 +39,10 @@ namespace v8 {
+ namespace internal {
+ 
+ // Linux perf tool logging support.
+-class LinuxPerfJitLogger : public CodeEventLogger {
++class PerfJitLogger : public CodeEventLogger {
+  public:
+-  explicit LinuxPerfJitLogger(Isolate* isolate);
+-  ~LinuxPerfJitLogger() override;
++  explicit PerfJitLogger(Isolate* isolate);
++  ~PerfJitLogger() override;
+ 
+   void CodeMoveEvent(Tagged<InstructionStream> from,
+                      Tagged<InstructionStream> to) override {
+@@ -143,6 +143,6 @@ class LinuxPerfJitLogger : public CodeEventLogger {
+ }  // namespace internal
+ }  // namespace v8
+ 
+-#endif  // V8_OS_LINUX
++#endif  // V8_OS_LINUX || V8_OS_DARWIN
+ 
+ #endif  // V8_DIAGNOSTICS_PERF_JIT_H_
+diff --git a/src/flags/flag-definitions.h b/src/flags/flag-definitions.h
+index dd713090c674585c23f9b9574df7ed258c0cd23e..8c12e97c4e256fb8bc6ef51c7abd6a926df7b008 100644
+--- a/src/flags/flag-definitions.h
++++ b/src/flags/flag-definitions.h
+@@ -3262,7 +3262,7 @@ DEFINE_IMPLICATION(prof, log_code)
+ 
+ DEFINE_BOOL(ll_prof, false, "Enable low-level linux profiler.")
+ 
+-#if V8_OS_LINUX
++#if V8_OS_LINUX || V8_OS_DARWIN
+ #define DEFINE_PERF_PROF_BOOL(nam, cmt) DEFINE_BOOL(nam, false, cmt)
+ #define DEFINE_PERF_PROF_IMPLICATION DEFINE_IMPLICATION
+ #else
+@@ -3279,7 +3279,7 @@ DEFINE_BOOL(ll_prof, false, "Enable low-level linux profiler.")
+ #endif
+ 
+ DEFINE_PERF_PROF_BOOL(perf_basic_prof,
+-                      "Enable perf linux profiler (basic support).")
++                      "Enable basic support for perf profiler.")
+ DEFINE_NEG_IMPLICATION(perf_basic_prof, compact_code_space)
+ DEFINE_STRING(perf_basic_prof_path, DEFAULT_PERF_BASIC_PROF_PATH,
+               "directory to write perf-<pid>.map symbol file to")
+@@ -3288,8 +3288,8 @@ DEFINE_PERF_PROF_BOOL(
+     "Only report function code ranges to perf (i.e. no stubs).")
+ DEFINE_PERF_PROF_IMPLICATION(perf_basic_prof_only_functions, perf_basic_prof)
+ 
+-DEFINE_PERF_PROF_BOOL(
+-    perf_prof, "Enable perf linux profiler (experimental annotate support).")
++DEFINE_PERF_PROF_BOOL(perf_prof,
++                      "Enable experimental annotate support for perf profiler.")
+ DEFINE_STRING(perf_prof_path, DEFAULT_PERF_PROF_PATH,
+               "directory to write jit-<pid>.dump symbol file to")
+ DEFINE_PERF_PROF_BOOL(
+diff --git a/src/logging/log.cc b/src/logging/log.cc
+index ea07e176391b027287f007dadd44e64db8f62c3d..fe4096d4dadcc314274d2892c6ba1ed25b426b29 100644
+--- a/src/logging/log.cc
++++ b/src/logging/log.cc
+@@ -350,12 +350,12 @@ void CodeEventLogger::RegExpCodeCreateEvent(DirectHandle<AbstractCode> code,
+                     name_buffer_->get(), name_buffer_->size());
+ }
+ 
+-// Linux perf tool logging support.
+-#if V8_OS_LINUX
+-class LinuxPerfBasicLogger : public CodeEventLogger {
++// Linux & Darwin perf tool logging support.
++#if V8_OS_LINUX || V8_OS_DARWIN
++class PerfBasicLogger : public CodeEventLogger {
+  public:
+-  explicit LinuxPerfBasicLogger(Isolate* isolate);
+-  ~LinuxPerfBasicLogger() override;
++  explicit PerfBasicLogger(Isolate* isolate);
++  ~PerfBasicLogger() override;
+ 
+   void CodeMoveEvent(Tagged<InstructionStream> from,
+                      Tagged<InstructionStream> to) override {}
+@@ -388,21 +388,20 @@ class LinuxPerfBasicLogger : public CodeEventLogger {
+ };
+ 
+ // Extra space for the "perf-%d.map" filename, including the PID.
+-const int LinuxPerfBasicLogger::kFilenameBufferPadding = 32;
++const int PerfBasicLogger::kFilenameBufferPadding = 32;
+ 
+ // static
+-base::LazyRecursiveMutex& LinuxPerfBasicLogger::GetFileMutex() {
++base::LazyRecursiveMutex& PerfBasicLogger::GetFileMutex() {
+   static base::LazyRecursiveMutex file_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER;
+   return file_mutex;
+ }
+ 
+ // The following static variables are protected by
+-// LinuxPerfBasicLogger::GetFileMutex().
+-uint64_t LinuxPerfBasicLogger::reference_count_ = 0;
+-FILE* LinuxPerfBasicLogger::perf_output_handle_ = nullptr;
++// PerfBasicLogger::GetFileMutex().
++uint64_t PerfBasicLogger::reference_count_ = 0;
++FILE* PerfBasicLogger::perf_output_handle_ = nullptr;
+ 
+-LinuxPerfBasicLogger::LinuxPerfBasicLogger(Isolate* isolate)
+-    : CodeEventLogger(isolate) {
++PerfBasicLogger::PerfBasicLogger(Isolate* isolate) : CodeEventLogger(isolate) {
+   base::LockGuard<base::RecursiveMutex> guard_file(GetFileMutex().Pointer());
+   int process_id_ = base::OS::GetCurrentProcessId();
+   reference_count_++;
+@@ -424,7 +423,7 @@ LinuxPerfBasicLogger::LinuxPerfBasicLogger(Isolate* isolate)
+   }
+ }
+ 
+-LinuxPerfBasicLogger::~LinuxPerfBasicLogger() {
++PerfBasicLogger::~PerfBasicLogger() {
+   base::LockGuard<base::RecursiveMutex> guard_file(GetFileMutex().Pointer());
+   reference_count_--;
+ 
+@@ -436,9 +435,9 @@ LinuxPerfBasicLogger::~LinuxPerfBasicLogger() {
+   }
+ }
+ 
+-void LinuxPerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address,
+-                                                  size_t size, const char* name,
+-                                                  size_t name_length) {
++void PerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address, size_t size,
++                                             const char* name,
++                                             size_t name_length) {
+   // Linux perf expects hex literals without a leading 0x, while some
+   // implementations of printf might prepend one when using the %p format
+   // for pointers, leading to wrongly formatted JIT symbols maps. On the other
+@@ -456,9 +455,9 @@ void LinuxPerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address,
+ #endif
+ }
+ 
+-void LinuxPerfBasicLogger::LogRecordedBuffer(
+-    Tagged<AbstractCode> code, MaybeDirectHandle<SharedFunctionInfo>,
+-    const char* name, size_t length) {
++void PerfBasicLogger::LogRecordedBuffer(Tagged<AbstractCode> code,
++                                        MaybeDirectHandle<SharedFunctionInfo>,
++                                        const char* name, size_t length) {
+   DisallowGarbageCollection no_gc;
+   PtrComprCageBase cage_base(isolate_);
+   if (v8_flags.perf_basic_prof_only_functions &&
+@@ -472,13 +471,13 @@ void LinuxPerfBasicLogger::LogRecordedBuffer(
+ }
+ 
+ #if V8_ENABLE_WEBASSEMBLY
+-void LinuxPerfBasicLogger::LogRecordedBuffer(const wasm::WasmCode* code,
+-                                             const char* name, size_t length) {
++void PerfBasicLogger::LogRecordedBuffer(const wasm::WasmCode* code,
++                                        const char* name, size_t length) {
+   WriteLogRecordedBuffer(static_cast<uintptr_t>(code->instruction_start()),
+                          code->instructions().length(), name, length);
+ }
+ #endif  // V8_ENABLE_WEBASSEMBLY
+-#endif  // V8_OS_LINUX
++#endif  // V8_OS_LINUX || V8_OS_DARWIN
+ 
+ // External LogEventListener
+ ExternalLogEventListener::ExternalLogEventListener(Isolate* isolate)
+@@ -2304,14 +2303,14 @@ bool V8FileLogger::SetUp(Isolate* isolate) {
+   PrepareLogFileName(log_file_name, isolate, v8_flags.logfile);
+   log_file_ = std::make_unique<LogFile>(this, log_file_name.str());
+ 
+-#if V8_OS_LINUX
++#if V8_OS_LINUX || V8_OS_DARWIN
+   if (v8_flags.perf_basic_prof) {
+-    perf_basic_logger_ = std::make_unique<LinuxPerfBasicLogger>(isolate);
++    perf_basic_logger_ = std::make_unique<PerfBasicLogger>(isolate);
+     CHECK(logger()->AddListener(perf_basic_logger_.get()));
+   }
+ 
+   if (v8_flags.perf_prof) {
+-    perf_jit_logger_ = std::make_unique<LinuxPerfJitLogger>(isolate);
++    perf_jit_logger_ = std::make_unique<PerfJitLogger>(isolate);
+     CHECK(logger()->AddListener(perf_jit_logger_.get()));
+   }
+ #else
+@@ -2457,7 +2456,7 @@ FILE* V8FileLogger::TearDownAndGetLogFile() {
+   ticker_.reset();
+   timer_.Stop();
+ 
+-#if V8_OS_LINUX
++#if V8_OS_LINUX || V8_OS_DARWIN
+   if (perf_basic_logger_) {
+     CHECK(logger()->RemoveListener(perf_basic_logger_.get()));
+     perf_basic_logger_.reset();
+diff --git a/src/logging/log.h b/src/logging/log.h
+index ec39b1ec097a864b6f7aaf5625fd681d8b2437a9..b8b5c2be526a456e35b393e9ed8dfae74ef00eb1 100644
+--- a/src/logging/log.h
++++ b/src/logging/log.h
+@@ -64,8 +64,8 @@ class Isolate;
+ class JitLogger;
+ class LogFile;
+ class LowLevelLogger;
+-class LinuxPerfBasicLogger;
+-class LinuxPerfJitLogger;
++class PerfBasicLogger;
++class PerfJitLogger;
+ class Profiler;
+ class SourcePosition;
+ class Ticker;
+@@ -363,9 +363,9 @@ class V8FileLogger : public LogEventListener {
+ 
+   std::atomic<bool> is_logging_;
+   std::unique_ptr<LogFile> log_file_;
+-#if V8_OS_LINUX
+-  std::unique_ptr<LinuxPerfBasicLogger> perf_basic_logger_;
+-  std::unique_ptr<LinuxPerfJitLogger> perf_jit_logger_;
++#if V8_OS_LINUX || V8_OS_DARWIN
++  std::unique_ptr<PerfBasicLogger> perf_basic_logger_;
++  std::unique_ptr<PerfJitLogger> perf_jit_logger_;
+ #endif
+   std::unique_ptr<LowLevelLogger> ll_logger_;
+   std::unique_ptr<JitLogger> jit_logger_;