author | Jim Blandy <jimb@mozilla.com> |
Tue, 06 Dec 2011 11:40:27 -0800 | |
changeset 82080 | 9aca452cf4519114e31f6917a37050366e5a3d57 |
parent 82079 | 6a2bb05dd97ea248d19b1e657d656cdd5fbd3104 |
child 82081 | 2e7abb74ed3e960add927b34721470b1918533e5 |
push id | 21582 |
push user | bmo@edmorley.co.uk |
push date | Wed, 07 Dec 2011 09:30:09 +0000 |
treeherder | mozilla-central@489f2d51b011 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jorendorff |
bugs | 687683 |
milestone | 11.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1785,16 +1785,18 @@ js::Interpret(JSContext *cx, StackFrame #endif /* Don't call the script prologue if executing between Method and Trace JIT. */ if (interpMode == JSINTERP_NORMAL) { StackFrame *fp = regs.fp(); JS_ASSERT_IF(!fp->isGeneratorFrame(), regs.pc == script->code); if (!ScriptPrologueOrGeneratorResume(cx, fp, UseNewTypeAtEntry(cx, fp))) goto error; + if (cx->compartment->debugMode()) + ScriptDebugPrologue(cx, fp); } /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */ if (interpMode == JSINTERP_REJOIN) interpMode = JSINTERP_NORMAL; JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP, JSOp(*regs.pc) == JSOP_TRAP); @@ -2026,16 +2028,20 @@ BEGIN_CASE(JSOP_STOP) */ CHECK_BRANCH(); interpReturnOK = true; if (entryFrame != regs.fp()) inline_return: { JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0)); + + if (cx->compartment->debugMode()) + interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK); + interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK); /* The JIT inlines ScriptEpilogue. */ #ifdef JS_METHODJIT jit_return: #endif /* The results of lowered call/apply frames need to be shifted. */ @@ -3502,16 +3508,19 @@ BEGIN_CASE(JSOP_FUNAPPLY) goto jit_return; } } #endif if (!ScriptPrologue(cx, regs.fp(), newType)) goto error; + if (cx->compartment->debugMode()) + ScriptDebugPrologue(cx, regs.fp()); + CHECK_INTERRUPT_HANDLER(); /* Load first op and dispatch it (safe since JSOP_STOP). */ op = (JSOp) *regs.pc; DO_OP(); } BEGIN_CASE(JSOP_SETCALL) @@ -5519,16 +5528,18 @@ END_CASE(JSOP_ARRAYPUSH) */ interpReturnOK &= (JSBool)UnwindScope(cx, 0, interpReturnOK || cx->isExceptionPending()); JS_ASSERT(regs.sp == regs.fp()->base()); if (entryFrame != regs.fp()) goto inline_return; exit: + if (cx->compartment->debugMode()) + interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK); interpReturnOK = ScriptEpilogueOrGeneratorYield(cx, regs.fp(), interpReturnOK); regs.fp()->setFinishedInInterpreter(); /* * At this point we are inevitably leaving an interpreted function or a * top-level script, and returning to one of: * (a) an "out of line" call made through Invoke; * (b) a js_Execute activation;
--- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -200,28 +200,24 @@ ScriptPrologue(JSContext *cx, StackFrame if (fp->isConstructing()) { JSObject *obj = js_CreateThisForFunction(cx, &fp->callee(), newType); if (!obj) return false; fp->functionThis().setObject(*obj); } Probes::enterJSFun(cx, fp->maybeFun(), fp->script()); - if (cx->compartment->debugMode()) - ScriptDebugPrologue(cx, fp); return true; } inline bool ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok) { Probes::exitJSFun(cx, fp->maybeFun(), fp->script()); - if (cx->compartment->debugMode()) - ok = ScriptDebugEpilogue(cx, fp, ok); /* * If inline-constructing, replace primitive rval with the new object * passed in via |this|, and instrument this constructor invocation. */ if (fp->isConstructing() && ok) { if (fp->returnValue().isPrimitive()) fp->setReturnValue(ObjectValue(fp->constructorThis())); @@ -230,28 +226,24 @@ ScriptEpilogue(JSContext *cx, StackFrame return ok; } inline bool ScriptPrologueOrGeneratorResume(JSContext *cx, StackFrame *fp, bool newType) { if (!fp->isGeneratorFrame()) return ScriptPrologue(cx, fp, newType); - if (cx->compartment->debugMode()) - ScriptDebugPrologue(cx, fp); return true; } inline bool ScriptEpilogueOrGeneratorYield(JSContext *cx, StackFrame *fp, bool ok) { if (!fp->isYielding()) return ScriptEpilogue(cx, fp, ok); - if (cx->compartment->debugMode()) - return ScriptDebugEpilogue(cx, fp, ok); return ok; } inline void InterpreterFrames::enableInterruptsIfRunning(JSScript *script) { if (script == regs->fp()->script()) enabler.enableInterrupts();
--- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -571,16 +571,20 @@ js_InternalThrow(VMFrame &f) // The JIT guarantees that ScriptEpilogue() has always been run // upon exiting to its caller. This is important for consistency, // where execution modes make similar guarantees about prologues // and epilogues. RunTracer(), Interpret(), and Invoke() all // rely on this property. JS_ASSERT(!f.fp()->finishedInInterpreter()); UnwindScope(cx, 0, cx->isExceptionPending()); + + if (cx->compartment->debugMode()) + js::ScriptDebugEpilogue(cx, f.fp(), false); + ScriptEpilogue(f.cx, f.fp(), false); // Don't remove the last frame, this is the responsibility of // JaegerShot()'s caller. We only guarantee that ScriptEpilogue() // has been run. if (f.entryfp == f.fp()) break; @@ -910,16 +914,20 @@ js_InternalInterpret(void *returnData, v /* FALLTHROUGH */ case REJOIN_FUNCTION_PROLOGUE: fp->scopeChain(); /* Construct the 'this' object for the frame if necessary. */ if (!ScriptPrologueOrGeneratorResume(cx, fp, types::UseNewTypeAtEntry(cx, fp))) return js_InternalThrow(f); + + if (cx->compartment->debugMode()) + js::ScriptDebugPrologue(cx, fp); + break; case REJOIN_CALL_PROLOGUE: case REJOIN_CALL_PROLOGUE_LOWERED_CALL: case REJOIN_CALL_PROLOGUE_LOWERED_APPLY: if (returnReg) { uint32 argc = 0; if (rejoin == REJOIN_CALL_PROLOGUE)
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -2347,21 +2347,25 @@ stubs::FunctionFrameEpilogue(VMFrame &f) { f.fp()->functionEpilogue(); } void JS_FASTCALL stubs::AnyFrameEpilogue(VMFrame &f) { /* - * On the normal execution path, emitReturn inlines ScriptEpilogue. - * This function implements forced early returns, so it must have the - * same effect. + * On the normal execution path, emitReturn calls ScriptDebugEpilogue + * and inlines ScriptEpilogue. This function implements forced early + * returns, so it must have the same effect. */ - if (!ScriptEpilogue(f.cx, f.fp(), true)) + bool ok = true; + if (f.cx->compartment->debugMode()) + ok = js::ScriptDebugEpilogue(f.cx, f.fp(), ok); + ok = ScriptEpilogue(f.cx, f.fp(), ok); + if (!ok) THROW(); if (f.fp()->isNonEvalFunctionFrame()) f.fp()->functionEpilogue(); } template <bool Clamped> int32 JS_FASTCALL stubs::ConvertToTypedInt(JSContext *cx, Value *vp)