Commit 3c320128 authored by Nathan Froyd's avatar Nathan Froyd
Browse files

Bug 1658375 - add support for arm64 macOS to profiler sampling and unwinding; r=mstange

The registers referenced in this patch and the assembly have been tested to
compile; the code changes have not been tested to actually work.

Differential Revision: https://phabricator.services.mozilla.com/D86612
parent 7951ffdf
Loading
Loading
Loading
Loading
+37 −4
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ void Sampler::SuspendAndSampleAndResumeThread(
  // what we do here, or risk deadlock.  See the corresponding comment in
  // platform-linux-android.cpp for details.

#if defined(__x86_64__)
  thread_state_flavor_t flavor = x86_THREAD_STATE64;
  x86_thread_state64_t state;
  mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
@@ -114,14 +115,34 @@ void Sampler::SuspendAndSampleAndResumeThread(
#  else
#    define REGISTER_FIELD(name) r##name
#  endif  // __DARWIN_UNIX03
#elif defined(__aarch64__)
  thread_state_flavor_t flavor = ARM_THREAD_STATE64;
  arm_thread_state64_t state;
  mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
#  if __DARWIN_UNIX03
#    define REGISTER_FIELD(name) __##name
#  else
#    define REGISTER_FIELD(name) name
#  endif  // __DARWIN_UNIX03
#else
#  error "unknown architecture"
#endif

  if (thread_get_state(samplee_thread, flavor,
                       reinterpret_cast<natural_t*>(&state),
                       &count) == KERN_SUCCESS) {
    Registers regs;
#if defined(__x86_64__)
    regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
    regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
    regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
#elif defined(__aarch64__)
    regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(pc));
    regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
    regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(fp));
#else
#  error "unknown architecture"
#endif
    regs.mLR = 0;

    aProcessRegs(regs, aNow);
@@ -183,6 +204,7 @@ static void PlatformInit(PSLockRef aLock) {}

#if defined(HAVE_NATIVE_UNWIND)
void Registers::SyncPopulate() {
#if defined(__x86_64__)
  asm(
      // Compute caller's %rsp by adding to %rbp:
      // 8 bytes for previous %rbp, 8 bytes for return address
@@ -190,6 +212,17 @@ void Registers::SyncPopulate() {
      // Dereference %rbp to get previous %rbp
      "movq (%%rbp), %1\n\t"
      : "=r"(mSP), "=r"(mFP));
#elif defined(__aarch64__)
  asm(
      // Compute caller's sp by adding to fp:
      // 8 bytes for previous fp, 8 bytes for return address
      "add %0, x29, #0x10\n\t"
      // Dereference fp to get previous fp
      "ldr %1, [x29]\n\t"
      : "=r"(mSP), "=r"(mFP));
#else
#  error "unknown architecture"
#endif
  mPC = reinterpret_cast<Address>(
      __builtin_extract_return_addr(__builtin_return_address(0)));
  mLR = 0;
+37 −4
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ void Sampler::SuspendAndSampleAndResumeThread(
  // what we do here, or risk deadlock.  See the corresponding comment in
  // platform-linux-android.cpp for details.

#if defined(__x86_64__)
  thread_state_flavor_t flavor = x86_THREAD_STATE64;
  x86_thread_state64_t state;
  mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
@@ -109,14 +110,34 @@ void Sampler::SuspendAndSampleAndResumeThread(
#  else
#    define REGISTER_FIELD(name) r##name
#  endif  // __DARWIN_UNIX03
#elif defined(__aarch64__)
  thread_state_flavor_t flavor = ARM_THREAD_STATE64;
  arm_thread_state64_t state;
  mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
#  if __DARWIN_UNIX03
#    define REGISTER_FIELD(name) __##name
#  else
#    define REGISTER_FIELD(name) name
#  endif  // __DARWIN_UNIX03
#else
#  error "unknown architecture"
#endif

  if (thread_get_state(samplee_thread, flavor,
                       reinterpret_cast<natural_t*>(&state),
                       &count) == KERN_SUCCESS) {
    Registers regs;
#if defined(__x86_64__)
    regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
    regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
    regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
#elif defined(__aarch64__)
    regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(pc));
    regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
    regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(fp));
#else
#  error "unknown architecture"
#endif
    regs.mLR = 0;

    aProcessRegs(regs, aNow);
@@ -184,6 +205,7 @@ static void PlatformInit(PSLockRef aLock) {}

#if defined(HAVE_NATIVE_UNWIND)
void Registers::SyncPopulate() {
#if defined(__x86_64__)
  asm(
      // Compute caller's %rsp by adding to %rbp:
      // 8 bytes for previous %rbp, 8 bytes for return address
@@ -191,6 +213,17 @@ void Registers::SyncPopulate() {
      // Dereference %rbp to get previous %rbp
      "movq (%%rbp), %1\n\t"
      : "=r"(mSP), "=r"(mFP));
#elif defined(__aarch64__)
  asm(
      // Compute caller's sp by adding to fp:
      // 8 bytes for previous fp, 8 bytes for return address
      "add %0, x29, #0x10\n\t"
      // Dereference fp to get previous fp
      "ldr %1, [x29]\n\t"
      : "=r"(mSP), "=r"(mFP));
#else
#  error "unknown architecture"
#endif
  mPC = reinterpret_cast<Address>(
      __builtin_extract_return_addr(__builtin_return_address(0)));
  mLR = 0;