Bug 925308 - Dont pop profiler frames for stack frames pushed by invalidated IonScripts which didn not have profiler instrumentation. r=jandem

This commit is contained in:
Kannan Vijayan 2013-11-11 11:19:47 -05:00
parent 20c1ae1d0a
commit d2984a88e7
6 changed files with 44 additions and 28 deletions

View File

@ -0,0 +1,18 @@
// |jit-test| error: ReferenceError
var lfcode = new Array();
lfcode.push("3");
lfcode.push("enableSPSProfilingAssertions(false);foo();");
while (true) {
var file = lfcode.shift(); if (file == undefined) { break; }
loadFile(file)
}
function loadFile(lfVarx) {
if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
switch (lfRunTypeId) {
default: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
}
} else if (!isNaN(lfVarx)) {
lfRunTypeId = parseInt(lfVarx);
}
}

View File

@ -549,30 +549,41 @@ HandleException(ResumeFromException *rfe)
// Search each inlined frame for live iterator objects, and close
// them.
InlineFrameIterator frames(cx, &iter);
// Invalidation state will be the same for all inlined scripts in the frame.
IonScript *ionScript = nullptr;
bool invalidated = iter.checkInvalidation(&ionScript);
for (;;) {
HandleExceptionIon(cx, frames, rfe, &overrecursed);
if (rfe->kind == ResumeFromException::RESUME_BAILOUT) {
IonScript *ionScript = nullptr;
if (iter.checkInvalidation(&ionScript))
if (invalidated)
ionScript->decref(cx->runtime()->defaultFreeOp());
return;
}
JS_ASSERT(rfe->kind == ResumeFromException::RESUME_ENTRY_FRAME);
// Figure out whether SPS frame was pushed for this frame or not.
// Even if profiler is enabled, the frame being popped might have
// been entered prior to SPS being enabled, and thus not have
// a pushed SPS frame.
bool popSPSFrame = cx->runtime()->spsProfiler.enabled();
if (invalidated)
popSPSFrame = ionScript->hasSPSInstrumentation();
// When profiling, each frame popped needs a notification that
// the function has exited, so invoke the probe that a function
// is exiting.
JSScript *script = frames.script();
probes::ExitScript(cx, script, script->function(), nullptr);
probes::ExitScript(cx, script, script->function(), popSPSFrame);
if (!frames.more())
break;
++frames;
}
IonScript *ionScript = nullptr;
if (iter.checkInvalidation(&ionScript))
if (invalidated)
ionScript->decref(cx->runtime()->defaultFreeOp());
} else if (iter.isBaselineJS()) {
@ -585,7 +596,8 @@ HandleException(ResumeFromException *rfe)
// Unwind profiler pseudo-stack
JSScript *script = iter.script();
probes::ExitScript(cx, script, script->function(), iter.baselineFrame());
probes::ExitScript(cx, script, script->function(),
iter.baselineFrame()->hasPushedSPSFrame());
// After this point, any pushed SPS frame would have been popped if it needed
// to be. Unset the flag here so that if we call DebugEpilogue below,
// it doesn't try to pop the SPS frame again.

View File

@ -1660,7 +1660,7 @@ CASE(JSOP_RETRVAL)
if (!REGS.fp()->isYielding())
REGS.fp()->epilogue(cx);
else
probes::ExitScript(cx, script, script->function(), REGS.fp());
probes::ExitScript(cx, script, script->function(), REGS.fp()->hasPushedSPSFrame());
#if defined(JS_ION)
jit_return_pop_frame:
@ -3437,7 +3437,7 @@ DEFAULT()
if (!REGS.fp()->isYielding())
REGS.fp()->epilogue(cx);
else
probes::ExitScript(cx, script, script->function(), REGS.fp());
probes::ExitScript(cx, script, script->function(), REGS.fp()->hasPushedSPSFrame());
gc::MaybeVerifyBarriers(cx, true);

View File

@ -63,8 +63,7 @@ probes::EnterScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
}
inline bool
probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
AbstractFramePtr fp)
probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun, bool popSPSFrame)
{
bool ok = true;
@ -76,22 +75,10 @@ probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
cx->doFunctionCallback(maybeFun, script, 0);
#endif
JSRuntime *rt = cx->runtime();
/*
* Coming from IonMonkey, the fp might not be known (fp == nullptr), but
* IonMonkey will only call exitScript() when absolutely necessary, so it is
* guaranteed that fp->hasPushedSPSFrame() would have been true
*/
if ((!fp && rt->spsProfiler.enabled()) || (fp && fp.hasPushedSPSFrame()))
rt->spsProfiler.exit(cx, script, maybeFun);
return ok;
}
if (popSPSFrame && cx->runtime()->spsProfiler.enabled())
cx->runtime()->spsProfiler.exit(cx, script, maybeFun);
inline bool
probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
StackFrame *fp)
{
return probes::ExitScript(cx, script, maybeFun, fp ? AbstractFramePtr(fp) : AbstractFramePtr());
return ok;
}
inline bool

View File

@ -69,8 +69,7 @@ bool WantNativeAddressInfo(JSContext *);
bool EnterScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
/* About to leave a JS function */
bool ExitScript(JSContext *, JSScript *, JSFunction *, AbstractFramePtr);
bool ExitScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
bool ExitScript(JSContext *, JSScript *, JSFunction *, bool popSPSFrame);
/* Executing a script */
bool StartExecution(JSScript *script);

View File

@ -300,7 +300,7 @@ StackFrame::epilogue(JSContext *cx)
JS_ASSERT(!hasBlockChain());
RootedScript script(cx, this->script());
probes::ExitScript(cx, script, script->function(), this);
probes::ExitScript(cx, script, script->function(), hasPushedSPSFrame());
if (isEvalFrame()) {
if (isStrictEvalFrame()) {