Bug 838014 - More rooting in Debugger, plus some minor rooting in JSD and xpconnect for some should-be-private JSAPI changes. r=terrence
authorSteve Fink <sfink@mozilla.com>
Tue, 12 Feb 2013 12:27:02 -0800
changeset 131881 19857f43d44b08e879ef24f0a554a963f558eab3
parent 131880 17579083472fc8e51f97007b128751d4f8b34b3f
child 131882 77bd010e0e621b3f7eb5cefbefdd60d3159866b0
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs838014
milestone21.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
Bug 838014 - More rooting in Debugger, plus some minor rooting in JSD and xpconnect for some should-be-private JSAPI changes. r=terrence
js/jsd/jsd.h
js/jsd/jsd_stak.cpp
js/jsd/jsd_step.cpp
js/jsd/jsd_xpc.cpp
js/jsd/jsdebug.cpp
js/jsd/jsdebug.h
js/src/jsapi-tests/testDebugger.cpp
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsopcode.cpp
js/src/jsopcodeinlines.h
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/xpconnect/src/XPCDebug.cpp
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -693,25 +693,25 @@ extern void
 jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
 
 extern JSBool
 jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
                                  JSDThreadState* jsdthreadstate,
                                  JSDStackFrameInfo* jsdframe,
                                  const jschar *bytes, unsigned length,
                                  const char *filename, unsigned lineno,
-                                 JSBool eatExceptions, jsval *rval);
+                                 JSBool eatExceptions, JS::MutableHandleValue rval);
 
 extern JSBool
 jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
                                JSDThreadState* jsdthreadstate,
                                JSDStackFrameInfo* jsdframe,
                                const char *bytes, unsigned length,
                                const char *filename, unsigned lineno,
-                               JSBool eatExceptions, jsval *rval);
+                               JSBool eatExceptions, JS::MutableHandleValue rval);
 
 extern JSString*
 jsd_ValToStringInStackFrame(JSDContext* jsdc,
                             JSDThreadState* jsdthreadstate,
                             JSDStackFrameInfo* jsdframe,
                             jsval val);
 
 extern JSBool
--- a/js/jsd/jsd_stak.cpp
+++ b/js/jsd/jsd_stak.cpp
@@ -89,17 +89,17 @@ jsd_NewThreadState(JSDContext* jsdc, JSC
     JS_BeginRequest(jsdthreadstate->context);
 
     JSBrokenFrameIterator iter(cx);
     while(!iter.done())
     {
         JSAbstractFramePtr frame = iter.abstractFramePtr();
         JSScript* script = frame.script();
         uintptr_t  pc = (uintptr_t)iter.pc();
-        jsval dummyThis;
+        js::RootedValue dummyThis(cx);
 
         /*
          * don't construct a JSDStackFrame for dummy frames (those without a
          * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
          * isn't set.
          */
         if (frame.getThisValue(cx, &dummyThis))
         {
@@ -306,17 +306,17 @@ jsd_GetThisForStackFrame(JSDContext* jsd
                          JSDStackFrameInfo* jsdframe)
 {
     JSDValue* jsdval = NULL;
     JSD_LOCK_THREADSTATES(jsdc);
 
     if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
     {
         JSBool ok;
-        jsval thisval;
+        js::RootedValue thisval(jsdthreadstate->context);
         JS_BeginRequest(jsdthreadstate->context);
         ok = jsdframe->frame.getThisValue(jsdthreadstate->context, &thisval);
         JS_EndRequest(jsdthreadstate->context);
         if(ok)
             jsdval = JSD_NewValue(jsdc, thisval);
     }
 
     JSD_UNLOCK_THREADSTATES(jsdc);
@@ -387,17 +387,17 @@ jsd_IsStackFrameConstructing(JSDContext*
 }
 
 JSBool
 jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc, 
                                  JSDThreadState* jsdthreadstate,
                                  JSDStackFrameInfo* jsdframe,
                                  const jschar *bytes, unsigned length,
                                  const char *filename, unsigned lineno,
-                                 JSBool eatExceptions, jsval *rval)
+                                 JSBool eatExceptions, JS::MutableHandleValue rval)
 {
     JSBool retval;
     JSBool valid;
     JSExceptionState* exceptionState = NULL;
     JSContext* cx;
 
     JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
 
@@ -425,17 +425,17 @@ jsd_EvaluateUCScriptInStackFrame(JSDCont
 }
 
 JSBool
 jsd_EvaluateScriptInStackFrame(JSDContext* jsdc, 
                                JSDThreadState* jsdthreadstate,
                                JSDStackFrameInfo* jsdframe,
                                const char *bytes, unsigned length,
                                const char *filename, unsigned lineno,
-                               JSBool eatExceptions, jsval *rval)
+                               JSBool eatExceptions, JS::MutableHandleValue rval)
 {
     JSBool retval;
     JSBool valid;
     JSExceptionState* exceptionState = NULL;
     JSContext *cx;
 
     JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
 
--- a/js/jsd/jsd_step.cpp
+++ b/js/jsd/jsd_step.cpp
@@ -90,17 +90,17 @@ JSBool
     {
         /* no hook to call, no profile data needs to be collected,
          * so there is nothing to do here.
          */
         return hookresult;
     }
 
     if (before && isConstructing) {
-        jsval newObj;
+        js::RootedValue newObj(cx);
         if (!frame.getThisValue(cx, &newObj))
             return JS_FALSE;
         jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), frame);
     }
 
     jsscript = frame.script();
     if (jsscript)
     {
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -2020,20 +2020,20 @@ jsdStackFrame::Eval (const nsAString &by
         return NS_ERROR_INVALID_ARG;
 
     // get pointer to buffer contained in |bytes|
     nsAString::const_iterator h;
     bytes.BeginReading(h);
     const jschar *char_bytes = reinterpret_cast<const jschar *>(h.get());
 
     JSExceptionState *estate = 0;
-    jsval jv;
 
     JSContext *cx = JSD_GetJSContext (mCx, mThreadState);
 
+    js::RootedValue jv(cx);
     JSAutoRequest ar(cx);
 
     estate = JS_SaveExceptionState (cx);
     JS_ClearPendingException (cx);
 
     nsresult rv;
     nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
     if (NS_SUCCEEDED(rv))
@@ -2045,17 +2045,17 @@ jsdStackFrame::Eval (const nsAString &by
 
     *_rval = JSD_AttemptUCScriptInStackFrame (mCx, mThreadState,
                                               mStackFrameInfo,
                                               char_bytes, bytes.Length(),
                                               PromiseFlatCString(fileName).get(),
                                               line, &jv);
     if (!*_rval) {
         if (JS_IsExceptionPending(cx))
-            JS_GetPendingException (cx, &jv);
+            JS_GetPendingException (cx, jv.address());
         else
             jv = JSVAL_NULL;
     }
 
     JS_RestoreExceptionState (cx, estate);
 
 #ifdef DEBUG
     JSContext* poppedCX;
--- a/js/jsd/jsdebug.cpp
+++ b/js/jsd/jsdebug.cpp
@@ -760,78 +760,74 @@ JSD_IsStackFrameConstructing(JSDContext*
     return jsd_IsStackFrameConstructing(jsdc, jsdthreadstate, jsdframe);
 }
 
 JSD_PUBLIC_API(JSBool)
 JSD_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
                                  JSDThreadState* jsdthreadstate,
                                  JSDStackFrameInfo* jsdframe,
                                  const jschar *bytes, unsigned length,
-                                 const char *filename, unsigned lineno, jsval *rval)
+                                 const char *filename, unsigned lineno, JS::MutableHandleValue rval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JS_ASSERT(bytes);
     JS_ASSERT(length);
     JS_ASSERT(filename);
-    JS_ASSERT(rval);
 
     return jsd_EvaluateUCScriptInStackFrame(jsdc, jsdthreadstate,jsdframe,
                                             bytes, length, filename, lineno,
-                                             JS_TRUE, rval);
+                                            JS_TRUE, rval);
 }
 
 JSD_PUBLIC_API(JSBool)
 JSD_AttemptUCScriptInStackFrame(JSDContext* jsdc,
                                 JSDThreadState* jsdthreadstate,
                                 JSDStackFrameInfo* jsdframe,
                                 const jschar *bytes, unsigned length,
                                 const char *filename, unsigned lineno,
-                                jsval *rval)
+                                JS::MutableHandleValue rval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JS_ASSERT(bytes);
     JS_ASSERT(length);
     JS_ASSERT(filename);
-    JS_ASSERT(rval);
 
     return jsd_EvaluateUCScriptInStackFrame(jsdc, jsdthreadstate,jsdframe,
                                             bytes, length, filename, lineno,
                                             JS_FALSE, rval);
 }
 
 JSD_PUBLIC_API(JSBool)
 JSD_EvaluateScriptInStackFrame(JSDContext* jsdc,
                                JSDThreadState* jsdthreadstate,
                                JSDStackFrameInfo* jsdframe,
                                const char *bytes, unsigned length,
-                               const char *filename, unsigned lineno, jsval *rval)
+                               const char *filename, unsigned lineno, JS::MutableHandleValue rval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JS_ASSERT(bytes);
     JS_ASSERT(length);
     JS_ASSERT(filename);
-    JS_ASSERT(rval);
 
     return jsd_EvaluateScriptInStackFrame(jsdc, jsdthreadstate,jsdframe,
                                           bytes, length,
                                           filename, lineno, JS_TRUE, rval);
 }
 
 JSD_PUBLIC_API(JSBool)
 JSD_AttemptScriptInStackFrame(JSDContext* jsdc,
                               JSDThreadState* jsdthreadstate,
                               JSDStackFrameInfo* jsdframe,
                               const char *bytes, unsigned length,
-                              const char *filename, unsigned lineno, jsval *rval)
+                              const char *filename, unsigned lineno, JS::MutableHandleValue rval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JS_ASSERT(bytes);
     JS_ASSERT(length);
     JS_ASSERT(filename);
-    JS_ASSERT(rval);
 
     return jsd_EvaluateScriptInStackFrame(jsdc, jsdthreadstate,jsdframe,
                                           bytes, length,
                                           filename, lineno, JS_FALSE, rval);
 }
 
 JSD_PUBLIC_API(JSString*)
 JSD_ValToStringInStackFrame(JSDContext* jsdc,
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -985,46 +985,46 @@ JSD_IsStackFrameConstructing(JSDContext*
 * NOTE: The ErrorReporter hook might be called if this fails.
 */
 extern JSD_PUBLIC_API(JSBool)
 JSD_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
                                  JSDThreadState* jsdthreadstate,
                                  JSDStackFrameInfo* jsdframe,
                                  const jschar *bytes, unsigned length,
                                  const char *filename, unsigned lineno,
-                                 jsval *rval);
+                                 JS::MutableHandleValue rval);
 
 /*
 * Same as above, but does not eat exceptions.
 */
 extern JSD_PUBLIC_API(JSBool)
 JSD_AttemptUCScriptInStackFrame(JSDContext* jsdc,
                                 JSDThreadState* jsdthreadstate,
                                 JSDStackFrameInfo* jsdframe,
                                 const jschar *bytes, unsigned length,
                                 const char *filename, unsigned lineno,
-                                jsval *rval);
+                                JS::MutableHandleValue rval);
 
 /* single byte character version of JSD_EvaluateUCScriptInStackFrame */
 extern JSD_PUBLIC_API(JSBool)
 JSD_EvaluateScriptInStackFrame(JSDContext* jsdc,
                                JSDThreadState* jsdthreadstate,
                                JSDStackFrameInfo* jsdframe,
                                const char *bytes, unsigned length,
-                               const char *filename, unsigned lineno, jsval *rval);
+                               const char *filename, unsigned lineno, JS::MutableHandleValue rval);
 
 /*
 * Same as above, but does not eat exceptions.
 */
 extern JSD_PUBLIC_API(JSBool)
 JSD_AttemptScriptInStackFrame(JSDContext* jsdc,
                               JSDThreadState* jsdthreadstate,
                               JSDStackFrameInfo* jsdframe,
                               const char *bytes, unsigned length,
-                              const char *filename, unsigned lineno, jsval *rval);
+                              const char *filename, unsigned lineno, JS::MutableHandleValue rval);
 
 /*
 * Convert the given jsval to a string
 * NOTE: The ErrorReporter hook might be called if this fails.
 */
 extern JSD_PUBLIC_API(JSString*)
 JSD_ValToStringInStackFrame(JSDContext* jsdc,
                             JSDThreadState* jsdthreadstate,
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -13,17 +13,17 @@
 static int callCount[2] = {0, 0};
 
 static void *
 callCountHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
               JSBool *ok, void *closure)
 {
     callCount[before]++;
 
-    jsval thisv;
+    js::RootedValue thisv(cx);
     frame.getThisValue(cx, &thisv); // assert if fp is incomplete
 
     return cx;  // any non-null value causes the hook to be called again after
 }
 
 BEGIN_TEST(testDebugger_bug519719)
 {
     CHECK(JS_SetDebugMode(cx, JS_TRUE));
@@ -40,17 +40,17 @@ END_TEST(testDebugger_bug519719)
 
 static void *
 nonStrictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
                   JSBool *ok, void *closure)
 {
     if (before) {
         bool *allWrapped = (bool *) closure;
         js::RootedValue thisv(cx);
-        frame.getThisValue(cx, thisv.address());
+        frame.getThisValue(cx, &thisv);
         *allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
     }
     return NULL;
 }
 
 BEGIN_TEST(testDebugger_getThisNonStrict)
 {
     bool allWrapped = true;
@@ -79,17 +79,17 @@ END_TEST(testDebugger_getThisNonStrict)
 
 static void *
 strictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
                JSBool *ok, void *closure)
 {
     if (before) {
         bool *anyWrapped = (bool *) closure;
         js::RootedValue thisv(cx);
-        frame.getThisValue(cx, thisv.address());
+        frame.getThisValue(cx, &thisv);
         *anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
     }
     return NULL;
 }
 
 BEGIN_TEST(testDebugger_getThisStrict)
 {
     bool anyWrapped = false;
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1357,41 +1357,41 @@ JSAbstractFramePtr::maybeFun()
 JSScript *
 JSAbstractFramePtr::script()
 {
     AbstractFramePtr frame = Valueify(*this);
     return frame.script();
 }
 
 bool
-JSAbstractFramePtr::getThisValue(JSContext *cx, jsval *thisv)
+JSAbstractFramePtr::getThisValue(JSContext *cx, MutableHandleValue thisv)
 {
     AbstractFramePtr frame = Valueify(*this);
 
     RootedObject scopeChain(cx, frame.scopeChain());
     js::AutoCompartment ac(cx, scopeChain);
     if (!ComputeThis(cx, frame))
         return false;
 
-    *thisv = frame.thisValue();
+    thisv.set(frame.thisValue());
     return true;
 }
 
 bool
 JSAbstractFramePtr::isDebuggerFrame()
 {
     AbstractFramePtr frame = Valueify(*this);
     return frame.isDebuggerFrame();
 }
 
 bool
 JSAbstractFramePtr::evaluateInStackFrame(JSContext *cx,
                                          const char *bytes, unsigned length,
                                          const char *filename, unsigned lineno,
-                                         jsval *rval)
+                                         MutableHandleValue rval)
 {
     if (!CheckDebugMode(cx))
         return false;
 
     size_t len = length;
     jschar *chars = InflateString(cx, bytes, &len);
     if (!chars)
         return false;
@@ -1402,17 +1402,17 @@ JSAbstractFramePtr::evaluateInStackFrame
 
     return ok;
 }
 
 bool
 JSAbstractFramePtr::evaluateUCInStackFrame(JSContext *cx,
                                            const jschar *chars, unsigned length,
                                            const char *filename, unsigned lineno,
-                                           jsval *rval)
+                                           MutableHandleValue rval)
 {
     if (!CheckDebugMode(cx))
         return false;
 
     RootedObject scope(cx, scopeChain(cx));
     Rooted<Env*> env(cx, scope);
     if (!env)
         return false;
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -303,29 +303,29 @@ class JS_PUBLIC_API(JSAbstractFramePtr)
     operator bool() const { return !!ptr_; }
 
     JSObject *scopeChain(JSContext *cx);
     JSObject *callObject(JSContext *cx);
 
     JSFunction *maybeFun();
     JSScript *script();
 
-    bool getThisValue(JSContext *cx, jsval *thisv);
+    bool getThisValue(JSContext *cx, JS::MutableHandleValue thisv);
 
     bool isDebuggerFrame();
 
     bool evaluateInStackFrame(JSContext *cx,
                               const char *bytes, unsigned length,
                               const char *filename, unsigned lineno,
-                              jsval *rval);
+                              JS::MutableHandleValue rval);
 
     bool evaluateUCInStackFrame(JSContext *cx,
                                 const jschar *chars, unsigned length,
                                 const char *filename, unsigned lineno,
-                                jsval *rval);
+                                JS::MutableHandleValue rval);
 };
 
 class JS_PUBLIC_API(JSNullFramePtr) : public JSAbstractFramePtr
 {
   public:
     JSNullFramePtr()
       : JSAbstractFramePtr()
     {}
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2080,17 +2080,17 @@ js::CallResultEscapes(jsbytecode *pc)
 
     return (*pc != JSOP_IFEQ);
 }
 
 extern bool
 js::IsValidBytecodeOffset(JSContext *cx, JSScript *script, size_t offset)
 {
     // This could be faster (by following jump instructions if the target is <= offset).
-    for (BytecodeRange r(script); !r.empty(); r.popFront()) {
+    for (BytecodeRange r(cx, script); !r.empty(); r.popFront()) {
         size_t here = r.frontOffset();
         if (here >= offset)
             return here == offset;
     }
     return false;
 }
 
 JS_FRIEND_API(size_t)
--- a/js/src/jsopcodeinlines.h
+++ b/js/src/jsopcodeinlines.h
@@ -26,26 +26,26 @@ GetNameFromBytecode(JSContext *cx, JSScr
 
     PropertyName *name;
     GET_NAME_FROM_BYTECODE(script, pc, 0, name);
     return name;
 }
 
 class BytecodeRange {
   public:
-    BytecodeRange(JSScript *script)
-      : script(script), pc(script->code), end(pc + script->length) {}
+    BytecodeRange(JSContext *cx, JSScript *script)
+      : script(cx, script), pc(script->code), end(pc + script->length) {}
     bool empty() const { return pc == end; }
     jsbytecode *frontPC() const { return pc; }
     JSOp frontOpcode() const { return JSOp(*pc); }
     size_t frontOffset() const { return pc - script->code; }
     void popFront() { pc += GetBytecodeLength(pc); }
 
   private:
-    JSScript *script;
+    RootedScript script;
     jsbytecode *pc, *end;
 };
 
 class SrcNoteLineScanner
 {
     /* offset of the current JSOp in the bytecode */
     ptrdiff_t offset;
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1501,41 +1501,44 @@ GetScriptAndPCArgs(JSContext *cx, unsign
     }
 
     scriptp.set(script);
 
     return true;
 }
 
 static JSTrapStatus
-TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval,
+TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rvalArg,
             jsval closure)
 {
     JSString *str = JSVAL_TO_STRING(closure);
+    RootedValue rval(cx, *rvalArg);
 
     ScriptFrameIter iter(cx);
     JS_ASSERT(!iter.done());
 
     /* Debug-mode currently disables Ion compilation. */
     JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
     RootedScript script(cx, iter.script());
 
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
     if (!chars)
         return JSTRAP_ERROR;
 
     if (!frame.evaluateUCInStackFrame(cx, chars, length,
                                       script->filename,
                                       script->lineno,
-                                      rval))
+                                      &rval))
     {
+        *rvalArg = rval;
         return JSTRAP_ERROR;
     }
-    if (!JSVAL_IS_VOID(*rval))
+    *rvalArg = rval;
+    if (!rval.isUndefined())
         return JSTRAP_RETURN;
     return JSTRAP_CONTINUE;
 }
 
 static JSBool
 Trap(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedScript script(cx);
@@ -2591,17 +2594,17 @@ EvalInFrame(JSContext *cx, unsigned argc
         return false;
 
     JSAbstractFramePtr frame(Jsvalify(fi.abstractFramePtr()));
     RootedScript fpscript(cx, frame.script());
     bool ok = !!frame.evaluateUCInStackFrame(cx, chars, length,
                                              fpscript->filename,
                                              JS_PCToLineNumber(cx, fpscript,
                                                                fi.pc()),
-                                             vp);
+                                             MutableHandleValue::fromMarkedLocation(vp));
 
     if (saved)
         JS_RestoreFrameChain(cx);
 
     return ok;
 }
 
 static JSBool
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2892,17 +2892,17 @@ class BytecodeRangeWithLineNumbers : pri
 {
   public:
     using BytecodeRange::empty;
     using BytecodeRange::frontPC;
     using BytecodeRange::frontOpcode;
     using BytecodeRange::frontOffset;
 
     BytecodeRangeWithLineNumbers(JSContext *cx, JSScript *script)
-      : BytecodeRange(script), lineno(script->lineno), sn(script->notes()), snpc(script->code), skip(cx, thisForCtor())
+      : BytecodeRange(cx, script), lineno(script->lineno), sn(script->notes()), snpc(script->code)
     {
         if (!SN_IS_TERMINATOR(sn))
             snpc += SN_DELTA(sn);
         updateLine();
         while (frontPC() != script->main())
             popFront();
     }
 
@@ -2910,18 +2910,16 @@ class BytecodeRangeWithLineNumbers : pri
         BytecodeRange::popFront();
         if (!empty())
             updateLine();
     }
 
     size_t frontLineNumber() const { return lineno; }
 
   private:
-    BytecodeRangeWithLineNumbers *thisForCtor() { return this; }
-
     void updateLine() {
         /*
          * Determine the current line number by reading all source notes up to
          * and including the current offset.
          */
         while (!SN_IS_TERMINATOR(sn) && snpc <= frontPC()) {
             SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
             if (type == SRC_SETLINE)
@@ -2932,18 +2930,16 @@ class BytecodeRangeWithLineNumbers : pri
             sn = SN_NEXT(sn);
             snpc += SN_DELTA(sn);
         }
     }
 
     size_t lineno;
     jssrcnote *sn;
     jsbytecode *snpc;
-
-    SkipRoot skip;
 };
 
 static const size_t NoEdges = -1;
 static const size_t MultipleEdges = -2;
 
 /*
  * FlowGraphSummary::populate(cx, script) computes a summary of script's
  * control flow graph used by DebuggerScript_{getAllOffsets,getLineOffsets}.
@@ -3694,17 +3690,17 @@ DebuggerFrame_setOnPop(JSContext *cx, un
  * If |frame| is non-NULL, evaluate as for a direct eval in that frame; |env|
  * must be either |frame|'s DebugScopeObject, or some extension of that
  * environment; either way, |frame|'s scope is where newly declared variables
  * go. In this case, |frame| must have a computed 'this' value, equal to |thisv|.
  */
 JSBool
 js::EvaluateInEnv(JSContext *cx, Handle<Env*> env, HandleValue thisv, AbstractFramePtr frame,
                   StableCharPtr chars, unsigned length, const char *filename, unsigned lineno,
-                  Value *rval)
+                  MutableHandleValue rval)
 {
     assertSameCompartment(cx, env, frame);
     JS_ASSERT_IF(frame, thisv.get() == frame.thisValue());
 
     JS_ASSERT(!IsPoisonedPtr(chars.get()));
 
     /*
      * NB: This function breaks the assumption that the compiler can see all
@@ -3719,17 +3715,17 @@ js::EvaluateInEnv(JSContext *cx, Handle<
     RootedScript script(cx, frontend::CompileScript(cx, env, frame, options, chars.get(), length,
                                                     /* source = */ NULL,
                                                     /* staticLevel = */ frame ? 1 : 0));
     if (!script)
         return false;
 
     script->isActiveEval = true;
     ExecuteType type = !frame && env->isGlobal() ? EXECUTE_DEBUG_GLOBAL : EXECUTE_DEBUG;
-    return ExecuteKernel(cx, script, *env, thisv, type, frame, rval);
+    return ExecuteKernel(cx, script, *env, thisv, type, frame, rval.address());
 }
 
 static JSBool
 DebuggerGenericEval(JSContext *cx, const char *fullMethodName,
                     const Value &code, Value *bindings, MutableHandleValue vp,
                     Debugger *dbg, HandleObject scope, ScriptFrameIter *iter)
 {
     /* Either we're specifying the frame, or a global. */
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -694,13 +694,13 @@ Debugger::onNewGlobalObject(JSContext *c
     if (JS_CLIST_IS_EMPTY(&cx->runtime->onNewGlobalObjectWatchers))
         return true;
     return Debugger::slowPathOnNewGlobalObject(cx, global);
 }
 
 extern JSBool
 EvaluateInEnv(JSContext *cx, Handle<Env*> env, HandleValue thisv, AbstractFramePtr frame,
               StableCharPtr chars, unsigned length, const char *filename, unsigned lineno,
-              Value *rval);
+              MutableHandleValue rval);
 
 }
 
 #endif /* Debugger_h__ */
--- a/js/xpconnect/src/XPCDebug.cpp
+++ b/js/xpconnect/src/XPCDebug.cpp
@@ -97,17 +97,17 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx
         return false;
     }
 
     JSAutoRequest ar(cx);
 
     JSExceptionState* exceptionState = JS_SaveExceptionState(cx);
     JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
 
-    jsval rval;
+    js::RootedValue rval(cx);
     JSString* str;
     JSAutoByteString bytes;
     if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
         nullptr != (str = JS_ValueToString(cx, rval)) &&
         bytes.encode(cx, str)) {
         DebugDump("%s\n", bytes.ptr());
     } else
         DebugDump("%s", "eval failed!\n");