Bug 914561: Use SPS EnterJIT marks to unwind past jitcode. r=BenWa

This commit is contained in:
Jed Davis 2014-03-27 19:20:20 -07:00
parent 6149675df1
commit 61bc0e9cc2
2 changed files with 59 additions and 7 deletions

View File

@ -163,6 +163,9 @@ private:
class EHInterp {
public:
// Note that stackLimit is exclusive and stackBase is inclusive
// (i.e, stackLimit < SP <= stackBase), following the convention
// set by the AAPCS spec.
EHInterp(EHState &aState, const EHEntry *aEntry,
uint32_t aStackLimit, uint32_t aStackBase)
: mState(aState),
@ -294,10 +297,11 @@ private:
};
bool EHState::unwind(const EHEntry *aEntry, const void *stackLimit) {
EHInterp interp(*this, aEntry, mRegs[R_SP] - 4,
reinterpret_cast<uint32_t>(stackLimit));
bool EHState::unwind(const EHEntry *aEntry, const void *stackBasePtr) {
// The unwinding program cannot set SP to less than the initial value.
uint32_t stackLimit = mRegs[R_SP] - 4;
uint32_t stackBase = reinterpret_cast<uint32_t>(stackBasePtr);
EHInterp interp(*this, aEntry, stackLimit, stackBase);
return interp.unwind();
}

View File

@ -487,9 +487,57 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample
0
};
ucontext_t *ucontext = reinterpret_cast<ucontext_t *>(aSample->context);
array.count = EHABIStackWalk(ucontext->uc_mcontext, aProfile.GetStackTop(),
sp_array, pc_array, array.size);
const mcontext_t *mcontext = &reinterpret_cast<ucontext_t *>(aSample->context)->uc_mcontext;
mcontext_t savedContext;
PseudoStack *pseudoStack = aProfile.GetPseudoStack();
array.count = 0;
// The pseudostack contains an "EnterJIT" frame whenever we enter
// JIT code with profiling enabled; the stack pointer value points
// the saved registers. We use this to unwind resume unwinding
// after encounting JIT code.
for (uint32_t i = pseudoStack->stackSize(); i > 0; --i) {
// The pseudostack grows towards higher indices, so we iterate
// backwards (from callee to caller).
volatile StackEntry &entry = pseudoStack->mStack[i - 1];
if (!entry.js() && strcmp(entry.label(), "EnterJIT") == 0) {
// Found JIT entry frame. Unwind up to that point (i.e., force
// the stack walk to stop before the block of saved registers;
// note that it yields nondecreasing stack pointers), then restore
// the saved state.
uint32_t *vSP = reinterpret_cast<uint32_t*>(entry.stackAddress());
array.count += EHABIStackWalk(*mcontext,
/* stackBase = */ vSP,
sp_array + array.count,
pc_array + array.count,
array.size - array.count);
memset(&savedContext, 0, sizeof(savedContext));
// See also: struct EnterJITStack in js/src/jit/arm/Trampoline-arm.cpp
savedContext.arm_r4 = *vSP++;
savedContext.arm_r5 = *vSP++;
savedContext.arm_r6 = *vSP++;
savedContext.arm_r7 = *vSP++;
savedContext.arm_r8 = *vSP++;
savedContext.arm_r9 = *vSP++;
savedContext.arm_r10 = *vSP++;
savedContext.arm_fp = *vSP++;
savedContext.arm_lr = *vSP++;
savedContext.arm_sp = reinterpret_cast<uint32_t>(vSP);
savedContext.arm_pc = savedContext.arm_lr;
mcontext = &savedContext;
}
}
// Now unwind whatever's left (starting from either the last EnterJIT
// frame or, if no EnterJIT was found, the original registers).
array.count += EHABIStackWalk(*mcontext,
aProfile.GetStackTop(),
sp_array + array.count,
pc_array + array.count,
array.size - array.count);
mergeNativeBacktrace(aProfile, array);
}