Back out 7196b000f9df (bug 673125 part 2).
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 23 Aug 2011 15:34:59 -0500
changeset 75771 3cbe0a312779fa89bd7d5adbda36494437563c68
parent 75770 46dcf0b550eed68464e3a9a9ee942caa1e58a007
child 75772 5ed21fb6d81a9f530a8ce4b638db67c791f8f262
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs673125
milestone9.0a1
backs out7196b000f9dfc0ef65d2e1b82d96f8cc3695668e
Back out 7196b000f9df (bug 673125 part 2).
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsinterp.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/methodjit/Compiler.cpp
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -76,16 +76,19 @@
 #include "jsinterpinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/Stack-inl.h"
 
 #include "jsautooplen.h"
 
+#include "methodjit/MethodJIT.h"
+#include "methodjit/Retcon.h"
+
 #ifdef __APPLE__
 #include "sharkctl.h"
 #endif
 
 using namespace js;
 using namespace js::gc;
 
 JS_PUBLIC_API(JSBool)
@@ -146,16 +149,44 @@ ScriptDebugEpilogue(JSContext *cx, Stack
 } /* namespace js */
 
 JS_FRIEND_API(JSBool)
 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)
 {
     JSBool debugMode = JS_GetDebugMode(cx);
     /*
      * :TODO:
      * This probably should be an assertion, since it's indicative of a severe
      * API misuse.
@@ -169,17 +200,17 @@ CheckDebugMode(JSContext *cx)
 
 JS_PUBLIC_API(JSBool)
 JS_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep)
 {
     assertSameCompartment(cx, script);
     if (!CheckDebugMode(cx))
         return JS_FALSE;
 
-    return script->setStepModeFlag(cx, singleStep);
+    return js_SetSingleStepMode(cx, script, singleStep);
 }
 
 jsbytecode *
 js_UntrapScriptCode(JSContext *cx, JSScript *script)
 {
     jsbytecode *code = script->code;
     BreakpointSiteMap &sites = script->compartment->breakpointSites;
     for (BreakpointSiteMap::Range r = sites.all(); !r.empty(); r.popFront()) {
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -126,16 +126,20 @@ JS_FRIEND_API(JSBool)
 JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug);
 
 /*
  * Turn on/off debugging mode for a context's compartment.
  */
 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);
 
 /*
  * Unexported library-private helper used to unpatch all traps in a script.
  * Returns script->code if script has no traps, else a JS_malloc'ed copy of
  * script->code which the caller must JS_free, or null on JS_malloc OOM.
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -340,22 +340,21 @@ class InterpreterFrames {
     ~InterpreterFrames();
 
     /* If this js::Interpret frame is running |script|, enable interrupts. */
     void enableInterruptsIfRunning(JSScript *script) {
         if (script == regs->fp()->script())
             enabler.enableInterrupts();
     }
 
-    InterpreterFrames *older;
-
   private:
     JSContext *context;
     FrameRegs *regs;
     const InterruptEnablerBase &enabler;
+    InterpreterFrames *older;
 };
 
 } /* namespace js */
 
 /*
  * JS_LONE_INTERPRET indicates that the compiler should see just the code for
  * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
  * from the file should be visible only when compiling jsinvoke.cpp. It allows
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -64,17 +64,16 @@
 #include "jsparse.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jstracer.h"
 #if JS_HAS_XDR
 #include "jsxdrapi.h"
 #endif
 #include "methodjit/MethodJIT.h"
-#include "methodjit/Retcon.h"
 #include "vm/Debugger.h"
 
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
@@ -1825,63 +1824,8 @@ js_CloneScript(JSContext *cx, JSScript *
     return script;
 }
 
 void
 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));
-}
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -458,25 +458,16 @@ struct JSScript {
 
   public:
     uint16          nfixed;     /* number of slots besides stack operands in
                                    slot array */
   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.
      */
   public:
     uint8           objectsOffset;  /* offset to the array of nested function,
                                        block, scope, xml and one-time regexps
                                        objects */
     uint8           upvarsOffset;   /* offset of the array of display ("up")
@@ -496,16 +487,17 @@ struct JSScript {
     bool            usesEval:1;       /* script uses eval() */
     bool            usesArguments:1;  /* script uses arguments */
     bool            warnedAboutTwoArgumentEval:1; /* have warned about use of
                                                      obsolete eval(s, o) in
                                                      this script */
     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 */
     JSAtomMap       atomMap;    /* maps immediate index to literal struct */
     JSCompartment   *compartment; /* compartment the script was compiled for */
     const char      *filename;  /* source filename or null */
     uint32          lineno;     /* base line number of script */
     uint16          nslots;     /* vars plus maximum stack depth */
@@ -682,52 +674,16 @@ struct JSScript {
     }
 
     uint32 getClosedVar(uint32 index) {
         JS_ASSERT(index < nClosedVars);
         return closedSlots[nClosedArgs + index];
     }
 
     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
                                            uses sharp variables */
 
 static JS_INLINE uintN
 StackDepth(JSScript *script)
 {
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -469,17 +469,17 @@ mjit::Compiler::finishThisUp(JITScript *
         return Compile_Error;
     }
 
     JITScript *jit = new(cursor) JITScript;
     cursor += sizeof(JITScript);
 
     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();
     }
 
     /* 
      * WARNING: mics(), callICs() et al depend on the ordering of these
      * variable-length sections.  See JITScript's declaration for details.
@@ -898,17 +898,17 @@ mjit::Compiler::generateMethod()
         JSOp op = JSOp(*PC);
         int trap = stubs::JSTRAP_NONE;
         if (op == JSOP_TRAP) {
             if (!trapper.untrap(PC))
                 return Compile_Error;
             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) {
             RegisterID r1 = frame.allocReg();
             RegisterID r2 = frame.allocReg();
 
             masm.move(ImmPtr(&script->pcCounters.get(JSRUNMODE_METHODJIT, PC - script->code)), r1);
             Address pcCounter(r1);