Bug 1505271 - Baldr: find the JSContext via fp in the signal handler (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Fri, 09 Nov 2018 09:44:27 -0600
changeset 445522 dfdd63aae0c53fe1ce5b91bccb0262040cbf90b4
parent 445521 b1d6491fc47e69c118a630a1367bca40af30632f
child 445523 0abbc0f316d3d1b4c47338ff34e8a2e02e6479f0
push id35020
push usershindli@mozilla.com
push dateSat, 10 Nov 2018 21:37:25 +0000
treeherdermozilla-central@39dba5141dd9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1505271
milestone65.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 1505271 - Baldr: find the JSContext via fp in the signal handler (r=bbouvier)
js/src/wasm/WasmSignalHandlers.cpp
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -334,21 +334,31 @@ struct macos_arm_context {
 # define SP_sig(p) RSP_sig(p)
 # define LR_sig(p) R31_sig(p)
 #elif defined(__ppc64__) ||  defined (__PPC64__) || defined(__ppc64le__) || defined (__PPC64LE__)
 # define PC_sig(p) R32_sig(p)
 # define SP_sig(p) R01_sig(p)
 # define FP_sig(p) R01_sig(p)
 #endif
 
-static uint8_t**
+static void
+SetContextPC(CONTEXT* context, uint8_t* pc)
+{
+#ifdef PC_sig
+    *reinterpret_cast<uint8_t**>(&PC_sig(context)) = pc;
+#else
+    MOZ_CRASH();
+#endif
+}
+
+static uint8_t*
 ContextToPC(CONTEXT* context)
 {
 #ifdef PC_sig
-    return reinterpret_cast<uint8_t**>(&PC_sig(context));
+    return reinterpret_cast<uint8_t*>(PC_sig(context));
 #else
     MOZ_CRASH();
 #endif
 }
 
 static uint8_t*
 ContextToFP(CONTEXT* context)
 {
@@ -381,17 +391,17 @@ ContextToLR(CONTEXT* context)
 }
 #endif
 
 static JS::ProfilingFrameIterator::RegisterState
 ToRegisterState(CONTEXT* context)
 {
     JS::ProfilingFrameIterator::RegisterState state;
     state.fp = ContextToFP(context);
-    state.pc = *ContextToPC(context);
+    state.pc = ContextToPC(context);
     state.sp = ContextToSP(context);
 #if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
     state.lr = ContextToLR(context);
 #else
     state.lr = (void*)UINTPTR_MAX;
 #endif
     return state;
 }
@@ -425,40 +435,50 @@ struct AutoHandlingTrap
 
     ~AutoHandlingTrap() {
         MOZ_ASSERT(sAlreadyHandlingTrap.get());
         sAlreadyHandlingTrap.set(false);
     }
 };
 
 static MOZ_MUST_USE bool
-HandleTrap(CONTEXT* context, JSContext* cx)
+HandleTrap(CONTEXT* context, JSContext* assertCx = nullptr)
 {
     MOZ_ASSERT(sAlreadyHandlingTrap.get());
 
-    uint8_t* pc = *ContextToPC(context);
+    uint8_t* pc = ContextToPC(context);
     const CodeSegment* codeSegment = LookupCodeSegment(pc);
     if (!codeSegment || !codeSegment->isModule()) {
         return false;
     }
 
     const ModuleSegment& segment = *codeSegment->asModule();
 
     Trap trap;
     BytecodeOffset bytecode;
     if (!segment.code().lookupTrap(pc, &trap, &bytecode)) {
         return false;
     }
 
-    // We have a safe, expected wasm trap. Call startWasmTrap() to store enough
-    // register state at the point of the trap to allow stack unwinding or
-    // resumption, both of which will call finishWasmTrap().
+    // We have a safe, expected wasm trap, so fp is well-defined to be a Frame*.
+    // For the first sanity check, the Trap::IndirectCallBadSig special case is
+    // due to this trap occurring in the indirect call prologue, while fp points
+    // to the caller's Frame which can be in a different Module. In any case,
+    // though, the containing JSContext is the same.
+    Instance* instance = ((Frame*)ContextToFP(context))->tls->instance;
+    MOZ_RELEASE_ASSERT(&instance->code() == &segment.code() || trap == Trap::IndirectCallBadSig);
+    JSContext* cx = instance->realm()->runtimeFromAnyThread()->mainContextFromAnyThread();
+    MOZ_RELEASE_ASSERT(!assertCx || cx == assertCx);
+
+    // JitActivation::startWasmTrap() stores enough register state from the
+    // point of the trap to allow stack unwinding or resumption, both of which
+    // will call finishWasmTrap().
     jit::JitActivation* activation = cx->activation()->asJit();
     activation->startWasmTrap(trap, bytecode.offset(), ToRegisterState(context));
-    *ContextToPC(context) = segment.trapCode();
+    SetContextPC(context, segment.trapCode());
     return true;
 }
 
 // =============================================================================
 // The following platform specific signal/exception handlers are installed by
 // wasm::EnsureSignalHandlers() and funnel all potential wasm traps into
 // HandleTrap() above.
 // =============================================================================