Bug 1353763 - Baldr: handle strange Windows exception + SetThreadContext interaction (r=red)
authorLuke Wagner <luke@mozilla.com>
Fri, 14 Apr 2017 15:29:41 -0500
changeset 353156 b411de2683e99d545e82f55113a0f0dc2920808b
parent 353155 caca2a2510f59a0464ae24b1362542da1c3f6af8
child 353157 02ab056d454b427ccc8f26b2e4e1c20d75ad2bc8
push id89215
push userlwagner@mozilla.com
push dateFri, 14 Apr 2017 20:34:11 +0000
treeherdermozilla-inbound@b411de2683e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersred
bugs1353763
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 1353763 - Baldr: handle strange Windows exception + SetThreadContext interaction (r=red) MozReview-Commit-ID: 4jrrBipq4xB
js/src/wasm/WasmSignalHandlers.cpp
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -858,16 +858,28 @@ HandleFault(PEXCEPTION_POINTERS exceptio
 
     uint8_t* faultingAddress = reinterpret_cast<uint8_t*>(record->ExceptionInformation[1]);
 
     // This check isn't necessary, but, since we can, check anyway to make
     // sure we aren't covering up a real bug.
     if (!IsHeapAccessAddress(*instance, faultingAddress))
         return false;
 
+    // Similar to the non-atomic situation above, on Windows, an OOB fault at a
+    // PC can trigger *after* an async interrupt observed that PC and attempted
+    // to redirect to the async stub. In this unique case, interrupted() is
+    // already true when the OOB handler is called. Since the point of the async
+    // interrupt is to get out of an iloop and the OOB trap will do just that,
+    // we can simply clear the interrupt. (The update to CONTEXT.pc made by
+    // HandleMemoryAccess will clobber the interrupt's previous update.)
+    if (activation->interrupted()) {
+        MOZ_ASSERT(activation->resumePC() == pc);
+        activation->finishInterrupt();
+    }
+
     HandleMemoryAccess(context, pc, faultingAddress, *instance, activation, ppc);
     return true;
 }
 
 static LONG WINAPI
 WasmFaultHandler(LPEXCEPTION_POINTERS exception)
 {
     if (HandleFault(exception))
@@ -1297,18 +1309,24 @@ RedirectJitCodeToInterruptCheck(JSContex
         const Code* code = activation->compartment()->wasm.lookupCode(pc);
         if (code && code->segment().containsFunctionPC(pc))
             cx->simulator()->trigger_wasm_interrupt();
 #else
         uint8_t** ppc = ContextToPC(context);
         uint8_t* pc = *ppc;
         uint8_t* fp = ContextToFP(context);
 
+        // Only interrupt in function code so that the frame iterators have the
+        // invariant that resumePC always has a function CodeRange and we can't
+        // get into any weird interrupt-during-interrupt-stub cases. Note that
+        // the out-of-bounds/unaligned trap paths which call startInterrupt() go
+        // through function code, so test if already interrupted. All these
+        // paths are temporary though, so this case can be removed later.
         const Code* code = activation->compartment()->wasm.lookupCode(pc);
-        if (code && code->segment().containsFunctionPC(pc) && fp) {
+        if (code && code->segment().containsFunctionPC(pc) && fp && !activation->interrupted()) {
             activation->startInterrupt(pc, fp);
             *ppc = code->segment().interruptCode();
             return true;
         }
 #endif
     }
 
     return false;