зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1407986 - [MIPS] Fix unwinding during the interrupt in wasm prologue/epilogue. r=bbouvier
--HG-- extra : rebase_source : 3b48f1e2efc23109e8c3c705a2ff912035c9bab7
This commit is contained in:
Родитель
f873105fa5
Коммит
a9a9e66e71
|
@ -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<uint32_t> poppedExitReason = masm.currentOffset();
|
||||
|
||||
masm.pop(WasmTlsReg);
|
||||
DebugOnly<uint32_t> 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<Frame*>(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
|
||||
|
|
|
@ -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<uint8_t*>(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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче