Bug 1407986 - [MIPS] Fix unwinding during the interrupt in wasm prologue/epilogue. r=bbouvier

--HG--
extra : rebase_source : 3b48f1e2efc23109e8c3c705a2ff912035c9bab7
This commit is contained in:
Dragan Mladjenovic 2017-10-19 04:33:00 -04:00
Родитель f873105fa5
Коммит a9a9e66e71
2 изменённых файлов: 59 добавлений и 7 удалений

Просмотреть файл

@ -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;