Bug 846363 - Fix SPS Profiler frame adjustment when bailing from Ion to Baseline. r=jandem

This commit is contained in:
Kannan Vijayan 2013-03-22 17:00:40 -04:00
parent 3e57f2d6eb
commit c8219ba2f8

View File

@ -443,8 +443,10 @@ struct BaselineStackBuilder
// +===============+
//
static bool
InitFromBailout(JSContext *cx, HandleFunction fun, HandleScript script, SnapshotIterator &iter,
bool invalidate, BaselineStackBuilder &builder, MutableHandleFunction nextCallee)
InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
HandleFunction fun, HandleScript script, SnapshotIterator &iter,
bool invalidate, BaselineStackBuilder &builder,
MutableHandleFunction nextCallee, jsbytecode **callPC)
{
uint32_t exprStackSlots = iter.slots() - (script->nfixed + CountArgSlots(fun));
@ -509,7 +511,8 @@ InitFromBailout(JSContext *cx, HandleFunction fun, HandleScript script, Snapshot
// Initialize BaselineFrame::scopeChain
JSObject *scopeChain = NULL;
if (iter.bailoutKind() == Bailout_ArgumentCheck) {
BailoutKind bailoutKind = iter.bailoutKind();
if (bailoutKind == Bailout_ArgumentCheck) {
// Temporary hack -- skip the (unused) scopeChain, because it could be
// bogus (we can fail before the scope chain slot is set). Strip the
// hasScopeChain flag and we'll check this later to run prologue().
@ -642,11 +645,14 @@ InitFromBailout(JSContext *cx, HandleFunction fun, HandleScript script, Snapshot
resumeAfter ? "after" : "at", (int) pcOff, js_CodeName[op],
PCToLineNumber(script, pc), script->filename(), (int) script->lineno);
IonSpew(IonSpew_BaselineBailouts, " Bailout kind: %s",
BailoutKindString(iter.bailoutKind()));
BailoutKindString(bailoutKind));
#endif
// If this was the last inline frame, then unpacking is almost done.
if (!iter.moreFrames()) {
// Last frame, so PC for call to next frame is set to NULL.
*callPC = NULL;
// If the bailout was a resumeAfter, and the opcode is monitored,
// then the bailed out state should be in a position to enter
// into the ICTypeMonitor chain for the op.
@ -752,6 +758,32 @@ InitFromBailout(JSContext *cx, HandleFunction fun, HandleScript script, Snapshot
// If bailing into prologue, HAS_PUSHED_SPS_FRAME should not be set on frame.
blFrame->unsetPushedSPSFrame();
// Additionally, if SPS is enabled, there are two corner cases to handle:
// 1. If resuming into the prologue, and innermost frame is an inlined frame,
// and bailout is because of argument check failure, then:
// Top SPS profiler entry would be for caller frame.
// Ion would not have set the PC index field on that frame
// (since this bailout happens before MFunctionBoundary).
// Make sure that's done now.
// 2. If resuming into the prologue, and the bailout is NOT because of an
// argument check, then:
// Top SPS profiler entry would be for callee frame.
// Ion would already have pushed an SPS entry for this frame.
// The pc for this entry would be set to NULL.
// Make sure it's set to script->pc.
if (cx->runtime->spsProfiler.enabled()) {
if (caller && bailoutKind == Bailout_ArgumentCheck) {
IonSpew(IonSpew_BaselineBailouts, " Setting PCidx on innermost "
"inlined frame's parent's SPS entry (%s:%d) (pcIdx=%d)!",
caller->filename(), caller->lineno, callerPC - caller->code);
cx->runtime->spsProfiler.updatePC(caller, callerPC);
} else if (bailoutKind != Bailout_ArgumentCheck) {
IonSpew(IonSpew_BaselineBailouts,
" Popping SPS entry for innermost inlined frame's SPS entry");
cx->runtime->spsProfiler.exit(cx, script, fun);
}
}
} else {
opReturnAddr = nativeCodeForPC;
}
@ -762,6 +794,8 @@ InitFromBailout(JSContext *cx, HandleFunction fun, HandleScript script, Snapshot
return true;
}
*callPC = pc;
// Write out descriptor of BaselineJS frame.
size_t baselineFrameDescr = MakeFrameDescriptor((uint32_t) builder.framePushed(),
IonFrame_BaselineJS);
@ -1018,18 +1052,29 @@ ion::BailoutIonToBaseline(JSContext *cx, IonActivation *activation, IonBailoutIt
int frameNo = 0;
// Reconstruct baseline frames using the builder.
RootedScript caller(cx);
jsbytecode *callerPC = NULL;
RootedFunction fun(cx, callee);
RootedScript scr(cx, iter.script());
while (true) {
IonSpew(IonSpew_BaselineBailouts, " FrameNo %d", frameNo);
jsbytecode *callPC = NULL;
RootedFunction nextCallee(cx, NULL);
if (!InitFromBailout(cx, fun, scr, snapIter, invalidate, builder, &nextCallee))
if (!InitFromBailout(cx, caller, callerPC, fun, scr, snapIter, invalidate, builder,
&nextCallee, &callPC))
{
return BAILOUT_RETURN_FATAL_ERROR;
}
if (!snapIter.moreFrames())
break;
if (!snapIter.moreFrames()) {
JS_ASSERT(!callPC);
break;
}
JS_ASSERT(nextCallee);
JS_ASSERT(callPC);
caller = scr;
callerPC = callPC;
fun = nextCallee;
scr = fun->nonLazyScript();
snapIter.nextFrame();