Bug 1353420: Register the JIT region with mozglue so it can avoid stack-walking that code. r=luke
authorDavid Major <dmajor@mozilla.com>
Tue, 18 Apr 2017 18:52:04 -0400
changeset 353884 3586c6c537791ff194d10746ee54e5836e2c23c4
parent 353762 edda32a96d465ad3f2ee03f031a202f3c4910676
child 353885 6164b30ebdae9b729c5662fccc44117d2e01d254
push id31681
push userkwierso@gmail.com
push dateThu, 20 Apr 2017 00:11:50 +0000
treeherdermozilla-central@20dff607fb88 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1353420
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1353420: Register the JIT region with mozglue so it can avoid stack-walking that code. r=luke
js/src/jit/ProcessExecutableMemory.cpp
mozglue/misc/StackWalk.cpp
mozglue/misc/StackWalk_windows.h
--- a/js/src/jit/ProcessExecutableMemory.cpp
+++ b/js/src/jit/ProcessExecutableMemory.cpp
@@ -212,26 +212,31 @@ ReserveProcessExecutableMemory(size_t by
 # ifdef HAVE_64BIT_BUILD
     if (sJitExceptionHandler) {
         if (!RegisterExecutableMemory(p, bytes, pageSize)) {
             VirtualFree(p, 0, MEM_RELEASE);
             return nullptr;
         }
 
         p = (uint8_t*)p + pageSize;
+        bytes -= pageSize;
     }
+
+    RegisterJitCodeRegion((uint8_t*)p, bytes);
 # endif
 
     return p;
 }
 
 static void
 DeallocateProcessExecutableMemory(void* addr, size_t bytes)
 {
 # ifdef HAVE_64BIT_BUILD
+    UnregisterJitCodeRegion((uint8_t*)addr, bytes);
+
     if (sJitExceptionHandler) {
         size_t pageSize = gc::SystemPageSize();
         addr = (uint8_t*)addr - pageSize;
         UnregisterExecutableMemory(addr, bytes, pageSize);
     }
 # endif
 
     VirtualFree(addr, 0, MEM_RELEASE);
--- a/mozglue/misc/StackWalk.cpp
+++ b/mozglue/misc/StackWalk.cpp
@@ -217,16 +217,21 @@ struct WalkStackData
   uint32_t sp_size;
   uint32_t sp_count;
   void* platformData;
 };
 
 DWORD gStackWalkThread;
 CRITICAL_SECTION gDbgHelpCS;
 
+#ifdef _M_AMD64
+static uint8_t* sJitCodeRegionStart;
+static size_t sJitCodeRegionSize;
+#endif
+
 // Routine to print an error message to standard error.
 static void
 PrintError(const char* aPrefix)
 {
   LPSTR lpMsgBuf;
   DWORD lastErr = GetLastError();
   FormatMessageA(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -392,16 +397,24 @@ WalkStackMain64(struct WalkStackData* aD
       }
     }
 
     if (!ok) {
       break;
     }
 
 #elif defined(_M_AMD64)
+    // If we reach a frame in JIT code, we don't have enough information to
+    // unwind, so we have to give up.
+    if (sJitCodeRegionStart &&
+        (uint8_t*)context.Rip >= sJitCodeRegionStart &&
+        (uint8_t*)context.Rip < sJitCodeRegionStart + sJitCodeRegionSize) {
+      break;
+    }
+
     // 64-bit frame unwinding.
     // Try to look up unwind metadata for the current function.
     ULONG64 imageBase;
     PRUNTIME_FUNCTION runtimeFunction =
       RtlLookupFunctionEntry(context.Rip, &imageBase, NULL);
 
     if (!runtimeFunction) {
       // Alas, this is probably a JIT frame, for which we don't generate unwind
@@ -495,16 +508,43 @@ TryAcquireStackWalkWorkaroundLock()
 MFBT_API void
 ReleaseStackWalkWorkaroundLock()
 {
 #ifdef _M_AMD64
   LeaveCriticalSection(&gWorkaroundLock.lock);
 #endif
 }
 
+MFBT_API void
+RegisterJitCodeRegion(uint8_t* aStart, size_t aSize)
+{
+#ifdef _M_AMD64
+  // Currently we can only handle one JIT code region at a time
+  MOZ_RELEASE_ASSERT(!sJitCodeRegionStart);
+
+  sJitCodeRegionStart = aStart;
+  sJitCodeRegionSize = aSize;
+#endif
+}
+
+MFBT_API void
+UnregisterJitCodeRegion(uint8_t* aStart, size_t aSize)
+{
+#ifdef _M_AMD64
+  // Currently we can only handle one JIT code region at a time
+  MOZ_RELEASE_ASSERT(sJitCodeRegionStart &&
+                     sJitCodeRegionStart == aStart &&
+                     sJitCodeRegionSize == aSize);
+
+  sJitCodeRegionStart = nullptr;
+  sJitCodeRegionSize = 0;
+#endif
+}
+
+
 static unsigned int WINAPI
 WalkStackThread(void* aData)
 {
   BOOL msgRet;
   MSG msg;
 
   // Call PeekMessage to force creation of a message queue so that
   // other threads can safely post events to us.
--- a/mozglue/misc/StackWalk_windows.h
+++ b/mozglue/misc/StackWalk_windows.h
@@ -13,9 +13,15 @@ MFBT_API void
 AcquireStackWalkWorkaroundLock();
 
 MFBT_API bool
 TryAcquireStackWalkWorkaroundLock();
 
 MFBT_API void
 ReleaseStackWalkWorkaroundLock();
 
+MFBT_API void
+RegisterJitCodeRegion(uint8_t* aStart, size_t size);
+
+MFBT_API void
+UnregisterJitCodeRegion(uint8_t* aStart, size_t size);
+
 #endif // mozilla_StackWalk_windows_h