diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 4ef22910848..89be6ff7ef5 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -81,6 +81,9 @@ #include "jsautooplen.h" +#include "methodjit/MethodJIT.h" +#include "methodjit/Retcon.h" + #ifdef __APPLE__ #include "sharkctl.h" #endif @@ -151,6 +154,34 @@ JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug) return comp->setDebugModeFromC(cx, !!debug); } +JS_FRIEND_API(JSBool) +js_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep) +{ + assertSameCompartment(cx, script); + +#ifdef JS_METHODJIT + if (!script->singleStepMode == !singleStep) + return JS_TRUE; +#endif + + JS_ASSERT_IF(singleStep, cx->compartment->debugMode()); + +#ifdef JS_METHODJIT + /* request the next recompile to inject single step interrupts */ + script->singleStepMode = !!singleStep; + + js::mjit::JITScript *jit = script->jitNormal ? script->jitNormal : script->jitCtor; + if (jit && script->singleStepMode != jit->singleStepMode) { + js::mjit::Recompiler recompiler(cx, script); + if (!recompiler.recompile()) { + script->singleStepMode = !singleStep; + return JS_FALSE; + } + } +#endif + return JS_TRUE; +} + static JSBool CheckDebugMode(JSContext *cx) { @@ -174,7 +205,7 @@ JS_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep) if (!CheckDebugMode(cx)) return JS_FALSE; - return script->setStepModeFlag(cx, singleStep); + return js_SetSingleStepMode(cx, script, singleStep); } jsbytecode * diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index edc31f39fd6..5c888bbbffd 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -131,6 +131,10 @@ JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug); JS_FRIEND_API(JSBool) JS_SetDebugMode(JSContext *cx, JSBool debug); +/* Turn on single step mode. Requires debug mode. */ +extern JS_FRIEND_API(JSBool) +js_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep); + /* Turn on single step mode. */ extern JS_PUBLIC_API(JSBool) JS_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep); diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 91ee517d10c..2557675ae7e 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -345,12 +345,11 @@ class InterpreterFrames { enabler.enableInterrupts(); } - InterpreterFrames *older; - private: JSContext *context; FrameRegs *regs; const InterruptEnablerBase &enabler; + InterpreterFrames *older; }; } /* namespace js */ diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 4c6f56a4ce5..77fd4ee2a9e 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -69,7 +69,6 @@ #include "jsxdrapi.h" #endif #include "methodjit/MethodJIT.h" -#include "methodjit/Retcon.h" #include "vm/Debugger.h" #include "jsobjinlines.h" @@ -1830,58 +1829,3 @@ JSScript::copyClosedSlotsTo(JSScript *other) { memcpy(other->closedSlots, closedSlots, nClosedArgs + nClosedVars); } - -bool -JSScript::recompileForStepMode(JSContext *cx) -{ -#ifdef JS_METHODJIT - js::mjit::JITScript *jit = jitNormal ? jitNormal : jitCtor; - if (jit && stepModeEnabled() != jit->singleStepMode) { - js::mjit::Recompiler recompiler(cx, this); - return recompiler.recompile(); - } -#endif - return true; -} - -bool -JSScript::tryNewStepMode(JSContext *cx, uint32 newValue) -{ - uint32 prior = stepMode; - stepMode = newValue; - - if (!prior != !newValue) { - /* Step mode has been enabled or disabled. Alert the methodjit. */ - if (!recompileForStepMode(cx)) { - stepMode = prior; - return false; - } - - if (newValue) { - /* Step mode has been enabled. Alert the interpreter. */ - InterpreterFrames *frames; - for (frames = JS_THREAD_DATA(cx)->interpreterFrames; frames; frames = frames->older) - frames->enableInterruptsIfRunning(this); - } - } - return true; -} - -bool -JSScript::setStepModeFlag(JSContext *cx, bool step) -{ - return tryNewStepMode(cx, (stepMode & stepCountMask) | (step ? stepFlagMask : 0)); -} - -bool -JSScript::changeStepModeCount(JSContext *cx, int delta) -{ - assertSameCompartment(cx, this); - JS_ASSERT_IF(delta > 0, cx->compartment->debugMode()); - - uint32 count = stepMode & stepCountMask; - JS_ASSERT(((count + delta) & stepCountMask) == count + delta); - return tryNewStepMode(cx, - (stepMode & stepFlagMask) | - ((count + delta) & stepCountMask)); -} diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 67a0c87258d..5029769ef9e 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -462,15 +462,6 @@ struct JSScript { private: size_t callCount_; /* Number of times the script has been called. */ - /* - * When non-zero, compile script in single-step mode. The top bit is set and - * cleared by setStepMode, as used by JSD. The lower bits are a count, - * adjusted by changeStepModeCount, used by the Debugger object. Only - * when the bit is clear and the count is zero may we compile the script - * without single-step support. - */ - uint32 stepMode; - /* * Offsets to various array structures from the end of this script, or * JSScript::INVALID_OFFSET if the array has length 0. @@ -501,6 +492,7 @@ struct JSScript { bool hasSingletons:1; /* script has singleton objects */ #ifdef JS_METHODJIT bool debugMode:1; /* script was compiled in debug mode */ + bool singleStepMode:1; /* compile script in single-step mode */ #endif jsbytecode *main; /* main entry point, after predef'ing prolog */ @@ -687,42 +679,6 @@ struct JSScript { } void copyClosedSlotsTo(JSScript *other); - - private: - static const uint32 stepFlagMask = 0x80000000U; - static const uint32 stepCountMask = 0x7fffffffU; - - /* - * Attempt to recompile with or without single-stepping support, as directed - * by stepModeEnabled(). - */ - bool recompileForStepMode(JSContext *cx); - - /* Attempt to change this->stepMode to |newValue|. */ - bool tryNewStepMode(JSContext *cx, uint32 newValue); - - public: - /* - * Set or clear the single-step flag. If the flag is set or the count - * (adjusted by changeStepModeCount) is non-zero, then the script is in - * single-step mode. (JSD uses an on/off-style interface; Debugger uses a - * count-style interface.) - */ - bool setStepModeFlag(JSContext *cx, bool step); - - /* - * Increment or decrement the single-step count. If the count is non-zero or - * the flag (set by setStepModeFlag) is set, then the script is in - * single-step mode. (JSD uses an on/off-style interface; Debugger uses a - * count-style interface.) - */ - bool changeStepModeCount(JSContext *cx, int delta); - - bool stepModeEnabled() { return !!stepMode; } - -#ifdef DEBUG - uint32 stepModeCount() { return stepMode & stepCountMask; } -#endif }; #define SHARP_NSLOTS 2 /* [#array, #depth] slots if the script diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 62721cbcd4b..c7a1572a696 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -474,7 +474,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp) jit->code = JSC::MacroAssemblerCodeRef(result, execPool, masm.size() + stubcc.size()); jit->invokeEntry = result; - jit->singleStepMode = script->stepModeEnabled(); + jit->singleStepMode = script->singleStepMode; if (fun) { jit->arityCheckEntry = stubCode.locationOf(arityLabel).executableAddress(); jit->fastEntry = fullCode.locationOf(invokeLabel).executableAddress(); @@ -903,7 +903,7 @@ mjit::Compiler::generateMethod() op = JSOp(*PC); trap |= stubs::JSTRAP_TRAP; } - if (script->stepModeEnabled() && scanner.firstOpInLine(PC - script->code)) + if (script->singleStepMode && scanner.firstOpInLine(PC - script->code)) trap |= stubs::JSTRAP_SINGLESTEP; if (cx->hasRunOption(JSOPTION_PCCOUNT) && script->pcCounters) {