Bug 1083866 - Handle potential invalidation of the bailing frame. r=jandem

This commit is contained in:
Nicolas B. Pierron 2014-10-22 18:37:35 +02:00
parent 5225ef8c26
commit 1fbcbe24d7
3 changed files with 23 additions and 5 deletions

View File

@ -40,6 +40,7 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
JitActivationIterator jitActivations(cx->runtime());
BailoutFrameInfo bailoutData(jitActivations, sp);
JitFrameIterator iter(jitActivations);
MOZ_ASSERT(!iter.ionScript()->invalidated());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogTimestamp(logger, TraceLogger::Bailout);
@ -78,6 +79,17 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
EnsureExitFrame(iter.jsFrame());
}
// This condition was wrong when we entered this bailout function, but it
// might be true now. A GC might have reclaimed all the Jit code and
// invalidated all frames which are currently on the stack. As we are
// already in a bailout, we could not switch to an invalidation
// bailout. When the code of an IonScript which is on the stack is
// invalidated (see InvalidateActivation), we remove references to it and
// increment the reference counter for each activation that appear on the
// stack. As the bailed frame is one of them, we have to decrement it now.
if (iter.ionScript()->invalidated())
iter.ionScript()->decref(cx->runtime()->defaultFreeOp());
return retval;
}

View File

@ -2683,7 +2683,7 @@ InvalidateActivation(FreeOp *fop, const JitActivationIterator &activations, bool
size_t frameno = 1;
for (JitFrameIterator it(activations); !it.done(); ++it, ++frameno) {
MOZ_ASSERT_IF(frameno == 1, it.type() == JitFrame_Exit);
MOZ_ASSERT_IF(frameno == 1, it.type() == JitFrame_Exit || it.type() == JitFrame_Bailout);
#ifdef DEBUG
switch (it.type()) {
@ -2725,7 +2725,7 @@ InvalidateActivation(FreeOp *fop, const JitActivationIterator &activations, bool
}
#endif
if (!it.isIonJS())
if (!it.isIonScripted())
continue;
bool calledFromLinkStub = false;
@ -2793,8 +2793,9 @@ InvalidateActivation(FreeOp *fop, const JitActivationIterator &activations, bool
}
ionCode->setInvalidated();
// Don't adjust OSI points in the linkStub (which don't exist).
if (calledFromLinkStub)
// Don't adjust OSI points in the linkStub (which don't exist), or in a
// bailout path.
if (calledFromLinkStub || it.isBailoutJS())
continue;
// Write the delta (from the return address offset to the

View File

@ -140,8 +140,13 @@ JitFrameIterator::checkInvalidation() const
bool
JitFrameIterator::checkInvalidation(IonScript **ionScriptOut) const
{
uint8_t *returnAddr = returnAddressToFp();
JSScript *script = this->script();
if (isBailoutJS()) {
*ionScriptOut = activation_->bailoutData()->ionScript();
return !script->hasIonScript() || script->ionScript() != *ionScriptOut;
}
uint8_t *returnAddr = returnAddressToFp();
// N.B. the current IonScript is not the same as the frame's
// IonScript if the frame has since been invalidated.
bool invalidated;