diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp index 520e9df9bf80..5ef46733f283 100644 --- a/js/src/wasm/WasmFrameIter.cpp +++ b/js/src/wasm/WasmFrameIter.cpp @@ -246,6 +246,7 @@ static const unsigned PushedFP = 5; static const unsigned SetFP = 8; static const unsigned PoppedFP = 4; static const unsigned PoppedExitReason = 2; +static const unsigned PoppedTLSReg = 0; #elif defined(JS_CODEGEN_X86) static const unsigned PushedRetAddr = 0; static const unsigned PushedTLS = 1; @@ -254,6 +255,7 @@ static const unsigned PushedFP = 4; static const unsigned SetFP = 6; static const unsigned PoppedFP = 2; static const unsigned PoppedExitReason = 1; +static const unsigned PoppedTLSReg = 0; #elif defined(JS_CODEGEN_ARM) static const unsigned BeforePushRetAddr = 0; static const unsigned PushedRetAddr = 4; @@ -263,6 +265,7 @@ static const unsigned PushedFP = 20; static const unsigned SetFP = 24; static const unsigned PoppedFP = 8; static const unsigned PoppedExitReason = 4; +static const unsigned PoppedTLSReg = 0; #elif defined(JS_CODEGEN_ARM64) static const unsigned BeforePushRetAddr = 0; static const unsigned PushedRetAddr = 0; @@ -272,6 +275,7 @@ static const unsigned PushedFP = 0; static const unsigned SetFP = 0; static const unsigned PoppedFP = 0; static const unsigned PoppedExitReason = 0; +static const unsigned PoppedTLSReg = 0; #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) static const unsigned BeforePushRetAddr = 0; static const unsigned PushedRetAddr = 8; @@ -279,8 +283,9 @@ static const unsigned PushedTLS = 16; static const unsigned PushedExitReason = 28; static const unsigned PushedFP = 36; static const unsigned SetFP = 40; -static const unsigned PoppedFP = 16; -static const unsigned PoppedExitReason = 8; +static const unsigned PoppedFP = 24; +static const unsigned PoppedExitReason = 16; +static const unsigned PoppedTLSReg = 8; #elif defined(JS_CODEGEN_NONE) static const unsigned PushedRetAddr = 0; static const unsigned PushedTLS = 1; @@ -289,6 +294,7 @@ static const unsigned PushedFP = 0; static const unsigned SetFP = 0; static const unsigned PoppedFP = 0; static const unsigned PoppedExitReason = 0; +static const unsigned PoppedTLSReg = 0; #else # error "Unknown architecture!" #endif @@ -448,11 +454,20 @@ GenerateCallableEpilogue(MacroAssembler& masm, unsigned framePushed, ExitReason DebugOnly poppedExitReason = masm.currentOffset(); masm.pop(WasmTlsReg); + DebugOnly poppedTlsReg = masm.currentOffset(); + +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + masm.pop(ra); + *ret = masm.currentOffset(); + masm.branch(ra); +#else *ret = masm.currentOffset(); masm.ret(); +#endif MOZ_ASSERT_IF(!masm.oom(), PoppedFP == *ret - poppedFP); MOZ_ASSERT_IF(!masm.oom(), PoppedExitReason == *ret - poppedExitReason); + MOZ_ASSERT_IF(!masm.oom(), PoppedTLSReg == *ret - poppedTlsReg); } void @@ -734,7 +749,21 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r case CodeRange::BuiltinThunk: case CodeRange::TrapExit: case CodeRange::DebugTrap: -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + if ((offsetFromEntry >= BeforePushRetAddr && offsetFromEntry < PushedFP) || codeRange->isThunk()) { + // See BUG 1407986. + // On MIPS push is emulated by two instructions: adjusting the sp + // and storing the value to sp. + // Execution might be interrupted in between the two operation so we + // have to relay on register state instead of state saved on stack + // until the wasm::Frame is completely built. + // On entry the return address is in ra (registers.lr) and + // fp holds the caller's fp. + fixedPC = (uint8_t*) registers.lr; + fixedFP = fp; + AssertMatchesCallSite(activation, fixedPC, fixedFP); + } else +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) { // The return address is still in lr and fp holds the caller's fp. fixedPC = (uint8_t*) registers.lr; @@ -766,24 +795,45 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r fixedPC = reinterpret_cast(sp)->returnAddress; fixedFP = fp; AssertMatchesCallSite(activation, fixedPC, fixedFP); - } else if (offsetInCode == codeRange->ret() - PoppedFP) { + } else if (offsetInCode >= codeRange->ret() - PoppedFP && + offsetInCode < codeRange->ret() - PoppedExitReason) + { // The fixedFP field of the Frame has been popped into fp, but the // exit reason hasn't been popped yet. fixedPC = sp[2]; fixedFP = fp; AssertMatchesCallSite(activation, fixedPC, fixedFP); - } else if (offsetInCode == codeRange->ret() - PoppedExitReason) { + } else if (offsetInCode >= codeRange->ret() - PoppedExitReason && + offsetInCode < codeRange->ret() - PoppedTLSReg) + { // The fixedFP field of the Frame has been popped into fp, and the // exit reason has been popped. fixedPC = sp[1]; fixedFP = fp; AssertMatchesCallSite(activation, fixedPC, fixedFP); +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + } else if (offsetInCode >= codeRange->ret() - PoppedTLSReg && + offsetInCode < codeRange->ret()) + { + // The fixedFP field of the Frame has been popped into fp, but the + // exit reason hasn't been popped yet. + fixedPC = sp[0]; + fixedFP = fp; + AssertMatchesCallSite(activation, fixedPC, fixedFP); + } else if (offsetInCode == codeRange->ret()) { + // Both the TLS, fixedFP and ra have been popped and fp now + // points to the caller's frame. + fixedPC = (uint8_t*) registers.lr;; + fixedFP = fp; + AssertMatchesCallSite(activation, fixedPC, fixedFP); +#else } else if (offsetInCode == codeRange->ret()) { // Both the TLS and fixedFP fields have been popped and fp now // points to the caller's frame. fixedPC = sp[0]; fixedFP = fp; AssertMatchesCallSite(activation, fixedPC, fixedFP); +#endif } else { if (codeRange->kind() == CodeRange::ImportJitExit) { // The jit exit contains a range where the value of FP can't be diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp index 4dda8457c002..a8a8b27c5a17 100644 --- a/js/src/wasm/WasmSignalHandlers.cpp +++ b/js/src/wasm/WasmSignalHandlers.cpp @@ -173,6 +173,7 @@ class AutoSetHandlingSegFault # define EPC_sig(p) ((p)->uc_mcontext.pc) # define RFP_sig(p) ((p)->uc_mcontext.gregs[30]) # define RSP_sig(p) ((p)->uc_mcontext.gregs[29]) +# define R31_sig(p) ((p)->uc_mcontext.gregs[31]) # endif #elif defined(__NetBSD__) # define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i]) @@ -418,6 +419,7 @@ struct macos_arm_context { # define PC_sig(p) EPC_sig(p) # define FP_sig(p) RFP_sig(p) # define SP_sig(p) RSP_sig(p) +# define LR_sig(p) R31_sig(p) #endif static uint8_t** @@ -447,7 +449,7 @@ ContextToSP(CONTEXT* context) return reinterpret_cast(SP_sig(context)); } -# if defined(__arm__) || defined(__aarch64__) +# if defined(__arm__) || defined(__aarch64__) || defined(__mips__) static uint8_t* ContextToLR(CONTEXT* context) { @@ -538,7 +540,7 @@ ToRegisterState(CONTEXT* context) state.fp = ContextToFP(context); state.pc = *ContextToPC(context); state.sp = ContextToSP(context); -# if defined(__arm__) || defined(__aarch64__) +# if defined(__arm__) || defined(__aarch64__) || defined(__mips__) state.lr = ContextToLR(context); # endif return state;