Use HandleValue and MutableHandleValue in API hooks where possible, bug 776579. r=billm, sr=dmandelin
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 30 Jul 2012 05:19:09 -0600
changeset 100868 090fd1585e341ccc0f18b02c809e066a61fe3e77
parent 100867 ae22e27106b34397ba7e79ce61e6816ac3102955
child 100869 3e1924bf49c28e8586390d384aa0d6a85e9d9f4f
push idunknown
push userunknown
push dateunknown
reviewersbillm, dmandelin
bugs776579
milestone17.0a1
Use HandleValue and MutableHandleValue in API hooks where possible, bug 776579. r=billm, sr=dmandelin
content/canvas/src/CustomQS_Canvas2D.h
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/bindings/Codegen.py
dom/plugins/base/nsJSNPRuntime.cpp
dom/src/json/nsJSON.cpp
dom/workers/ChromeWorkerScope.cpp
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/ImageData.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/Worker.cpp
dom/workers/WorkerScope.cpp
js/ipc/ObjectWrapperParent.cpp
js/ipc/ObjectWrapperParent.h
js/src/builtin/Eval.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/RegExp.cpp
js/src/ctypes/CTypes.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/TokenStream.cpp
js/src/gc/Root.h
js/src/jsanalyze.cpp
js/src/jsapi-tests/testAddPropertyPropcache.cpp
js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi-tests/testPropCache.cpp
js/src/jsapi-tests/testSetProperty.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsbool.cpp
js/src/jsclass.h
js/src/jsclone.cpp
js/src/jscntxtinlines.h
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/json.h
js/src/jsonparser.cpp
js/src/jsonparser.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsproxy.cpp
js/src/jsreflect.cpp
js/src/jsscope.h
js/src/jsscopeinlines.h
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jswatchpoint.cpp
js/src/jswatchpoint.h
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/jsxml.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
js/src/methodjit/StubCalls.cpp
js/src/perf/jsperf.cpp
js/src/shell/js.cpp
js/src/vm/ArgumentsObject-inl.h
js/src/vm/ArgumentsObject.cpp
js/src/vm/ArgumentsObject.h
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/ObjectImpl.h
js/src/vm/ScopeObject.cpp
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCQuickStubs.h
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/codegen.py
js/xpconnect/src/dombindings.cpp
js/xpconnect/src/dombindings.h
js/xpconnect/src/qsgen.py
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -13,117 +13,117 @@
 #include "jsfriendapi.h"
 
 typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleSetterType, nsIDOMCanvasRenderingContext2D,
                              SetStrokeStyle_multi, (const nsAString &, nsISupports *));
 typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleGetterType, nsIDOMCanvasRenderingContext2D,
                              GetStrokeStyle_multi, (nsAString &, nsISupports **, PRInt32 *));
 
 static JSBool
-Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, JSMutableHandleValue vp,
                         CanvasStyleSetterType setfunc)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     JS::AutoValueRooter tvr(cx);
     if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     nsresult rv = NS_OK;
-    if (JSVAL_IS_STRING(*vp)) {
-        xpc_qsDOMString arg0(cx, *vp, vp,
+    if (JSVAL_IS_STRING(vp)) {
+        xpc_qsDOMString arg0(cx, vp, vp.address(),
                              xpc_qsDOMString::eDefaultNullBehavior,
                              xpc_qsDOMString::eDefaultUndefinedBehavior);
         if (!arg0.IsValid())
             return JS_FALSE;
 
         rv = (self->*setfunc)(arg0, nsnull);
     } else {
         nsISupports *arg0;
         xpc_qsSelfRef arg0ref;
-        rv = xpc_qsUnwrapArg<nsISupports>(cx, *vp, &arg0, &arg0ref.ptr, vp);
+        rv = xpc_qsUnwrapArg<nsISupports>(cx, vp, &arg0, &arg0ref.ptr, vp.address());
         if (NS_FAILED(rv)) {
             xpc_qsThrowBadSetterValue(cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);
             return JS_FALSE;
         }
 
         rv = (self->*setfunc)(NullString(), arg0);
     }
 
     if (NS_FAILED(rv))
         return xpc_qsThrowGetterSetterFailed(cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);
 
     return JS_TRUE;
 }
 
 static JSBool
-Canvas2D_GetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+Canvas2D_GetStyleHelper(JSContext *cx, JSObject *obj, jsid id, JSMutableHandleValue vp,
                         CanvasStyleGetterType getfunc)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     nsIDOMCanvasRenderingContext2D *self;
     xpc_qsSelfRef selfref;
     XPCLazyCallContext lccx(JS_CALLER, cx, obj);
-    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, vp, &lccx))
+    if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, vp.address(), &lccx))
         return JS_FALSE;
     nsresult rv;
 
     nsString resultString;
     nsCOMPtr<nsISupports> resultInterface;
     PRInt32 resultType;
     rv = (self->*getfunc)(resultString, getter_AddRefs(resultInterface), &resultType);
     if (NS_FAILED(rv))
-        return xpc_qsThrowGetterSetterFailed(cx, rv, JSVAL_TO_OBJECT(*vp), id);
+        return xpc_qsThrowGetterSetterFailed(cx, rv, JSVAL_TO_OBJECT(vp), id);
 
     switch (resultType) {
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_STRING:
-        return xpc::StringToJsval(cx, resultString, vp);
+        return xpc::StringToJsval(cx, resultString, vp.address());
 
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_PATTERN:
     {
         qsObjectHelper helper(resultInterface,
                               xpc_qsGetWrapperCache(resultInterface));
         return xpc_qsXPCOMObjectToJsval(lccx, helper,
                                         &NS_GET_IID(nsIDOMCanvasPattern),
-                                        &interfaces[k_nsIDOMCanvasPattern], vp);
+                                        &interfaces[k_nsIDOMCanvasPattern], vp.address());
     }
     case nsIDOMCanvasRenderingContext2D::CMG_STYLE_GRADIENT:
     {
         qsObjectHelper helper(resultInterface,
                               xpc_qsGetWrapperCache(resultInterface));
         return xpc_qsXPCOMObjectToJsval(lccx, helper,
                                         &NS_GET_IID(nsIDOMCanvasGradient),
-                                        &interfaces[k_nsIDOMCanvasGradient], vp);
+                                        &interfaces[k_nsIDOMCanvasGradient], vp.address());
     }
     default:
-        return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(*vp), id);
+        return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(vp), id);
     }
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
+nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
 {
     return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetStrokeStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
     return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetStrokeStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
+nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
 {
     return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetFillStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
     return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi);
 }
 
 static bool
 CreateImageData(JSContext* cx, JSObject* obj, uint32_t w, uint32_t h, jsval* vp)
 {
     using mozilla::CheckedInt;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -225,25 +225,25 @@ FieldGetterImpl(JSContext *cx, JS::CallA
   bool installed = false;
   JS::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
   JS::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
     return false;
   }
 
   if (!installed) {
-    args.rval() = JS::UndefinedValue();
+    args.rval().setUndefined();
     return true;
   }
 
   JS::Rooted<JS::Value> v(cx);
   if (!JS_GetPropertyById(cx, thisObj, id, v.address())) {
     return false;
   }
-  args.rval() = v;
+  args.rval().set(v);
   return true;
 }
 
 static JSBool
 FieldGetter(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   return JS::CallNonGenericMethod(cx, ValueHasISupportsPrivate, FieldGetterImpl,
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -107,25 +107,25 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo
 
   nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name,
                                          id, accessType);
   return NS_SUCCEEDED(rv);
 }
 
 static JSBool
 nsXBLDocGlobalObject_getProperty(JSContext *cx, JSHandleObject obj,
-                                 JSHandleId id, jsval *vp)
+                                 JSHandleId id, JSMutableHandleValue vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
 }
 
 static JSBool
 nsXBLDocGlobalObject_setProperty(JSContext *cx, JSHandleObject obj,
-                                 JSHandleId id, JSBool strict, jsval *vp)
+                                 JSHandleId id, JSBool strict, JSMutableHandleValue vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
 }
 
 static JSBool
 nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                  JSAccessMode mode, jsval *vp)
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5277,17 +5277,17 @@ static JSClass sGlobalScopePolluterClass
   JS_ConvertStub,
   nsHTMLDocumentSH::ReleaseDocument
 };
 
 
 // static
 JSBool
 nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
-                                           JSHandleId id, jsval *vp)
+                                           JSHandleId id, JSMutableHandleValue vp)
 {
   // Someone is accessing a element by referencing its name/id in the
   // global scope, do a security check to make sure that's ok.
 
   nsresult rv =
     sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
                                  "Window", id,
                                  nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
@@ -5300,17 +5300,17 @@ nsWindowSH::GlobalScopePolluterGetProper
   }
 
   return JS_TRUE;
 }
 
 // static
 JSBool
 nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      jsval *vp)
+                                      JSMutableHandleValue vp)
 {
   // Someone is accessing a element by referencing its name/id in the
   // global scope, do a security check to make sure that's ok.
 
   nsresult rv =
     sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
                                  "Window", id,
                                  nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
@@ -5318,17 +5318,17 @@ nsWindowSH::SecurityCheckOnAddDelProp(JS
   // If !NS_SUCCEEDED(rv) the security check failed. The security
   // manager set a JS exception for us.
   return NS_SUCCEEDED(rv);
 }
 
 // static
 JSBool
 nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                                   jsval *vp)
+                                   JSMutableHandleValue vp)
 {
   return SecurityCheckOnAddDelProp(cx, obj, id, vp);
 }
 
 static nsHTMLDocument*
 GetDocument(JSObject *obj)
 {
   return static_cast<nsHTMLDocument*>(
@@ -5864,17 +5864,17 @@ static const IDBConstant sIDBConstants[]
   { IDBConstant::IDBRequest,     "LOADING",           "pending" },
   { IDBConstant::IDBRequest,     "DONE",              "done" },
   { IDBConstant::IDBTransaction, "READ_ONLY",         "readonly" },
   { IDBConstant::IDBTransaction, "READ_WRITE",        "readwrite" },
   { IDBConstant::IDBTransaction, "VERSION_CHANGE",    "versionchange" },
 };
 
 static JSBool
-IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval* vp)
+IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
   JSString *idstr = JSID_TO_STRING(id);
   unsigned index;
   for (index = 0; index < mozilla::ArrayLength(sIDBConstants); index++) {
     JSBool match;
     if (!JS_StringEqualsAscii(cx, idstr, sIDBConstants[index].name, &match)) {
       return JS_FALSE;
     }
@@ -5938,17 +5938,17 @@ IDBConstantGetter(JSContext *cx, JSHandl
     return JS_FALSE;
   }
   if (!::JS_DefineProperty(cx, obj, c.name, value, nsnull, nsnull,
                            JSPROP_ENUMERATE)) {
     return JS_FALSE;
   }
 
   // Return value
-  *vp = value;
+  vp.set(value);
   return JS_TRUE;
 }
 
 static nsresult
 DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
 {
   const char* interface;
   if (aIID->Equals(NS_GET_IID(nsIIDBCursor))) {
@@ -6999,30 +6999,30 @@ LocationSetterGuts(JSContext *cx, JSObje
   NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
   
   return location->SetHref(depStr);
 }
 
 template<class Interface>
 static JSBool
 LocationSetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-               jsval *vp)
-{
-  nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
+               JSMutableHandleValue vp)
+{
+  nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp.address());
   if (NS_FAILED(rv)) {
     xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
 LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
-                        jsval *vp)
+                        JSMutableHandleValue vp)
 {
   JS::RootedObject obj(cx, obj_);
 
   JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
   if (wrapped) {
     obj = wrapped;
   }
 
@@ -7674,19 +7674,19 @@ nsNavigatorSH::PreCreate(nsISupports *na
   }
   return SetParentToWindow(win, parentObj);
 }
 
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
 static JSBool
-GetterShim(JSContext *cx, JSHandleObject obj, JSHandleId /* unused */, jsval *vp)
-{
-  nsresult rv = (*func)(cx, obj, vp);
+GetterShim(JSContext *cx, JSHandleObject obj, JSHandleId /* unused */, JSMutableHandleValue vp)
+{
+  nsresult rv = (*func)(cx, obj, vp.address());
   if (NS_FAILED(rv)) {
     xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   return JS_TRUE;  
 }
 
@@ -8819,17 +8819,17 @@ nsHTMLDocumentSH::GetDocumentAllNodeList
     return JS_FALSE;
   }
 
   return *nodeList != nsnull;
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
-                                         JSHandleId id, jsval *vp)
+                                         JSHandleId id, JSMutableHandleValue vp)
 {
   JSObject *obj = obj_;
 
   // document.all.item and .namedItem get their value in the
   // newResolve hook, so nothing to do for those properties here. And
   // we need to return early to prevent <div id="item"> from shadowing
   // document.all.item(), etc.
   if (sItem_id == id || sNamedItem_id == id) {
@@ -8866,17 +8866,17 @@ nsHTMLDocumentSH::DocumentAllGetProperty
       rv = nodeList->GetLength(&length);
 
       if (NS_FAILED(rv)) {
         xpc::Throw(cx, rv);
 
         return JS_FALSE;
       }
 
-      *vp = INT_TO_JSVAL(length);
+      vp.set(INT_TO_JSVAL(length));
 
       return JS_TRUE;
     } else if (sTags_id != id) {
       // For all other strings, look for an element by id or name.
 
       nsDependentJSString str(id);
 
       result = doc->GetDocumentAllResult(str, &cache, &rv);
@@ -8903,40 +8903,40 @@ nsHTMLDocumentSH::DocumentAllGetProperty
 
     result = node;
     cache = node;
   } else {
     result = nsnull;
   }
 
   if (result) {
-    rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), result, cache, true, vp);
+    rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), result, cache, true, vp.address());
     if (NS_FAILED(rv)) {
       xpc::Throw(cx, rv);
 
       return JS_FALSE;
     }
   } else {
-    *vp = JSVAL_VOID;
+    vp.setUndefined();
   }
 
   return JS_TRUE;
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                         unsigned flags, JSMutableHandleObject objp)
 {
   if (flags & JSRESOLVE_ASSIGNING) {
     // Nothing to do here if we're assigning
 
     return JS_TRUE;
   }
 
-  jsval v = JSVAL_VOID;
+  JS::RootedValue v(cx);
 
   if (sItem_id == id || sNamedItem_id == id) {
     // Define the item() or namedItem() method.
 
     JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
                                               0, JSPROP_ENUMERATE);
     objp.set(obj);
 
@@ -8968,17 +8968,17 @@ nsHTMLDocumentSH::DocumentAllNewResolve(
   } else {
     if (!DocumentAllGetProperty(cx, obj, id, &v)) {
       return JS_FALSE;
     }
   }
 
   JSBool ok = JS_TRUE;
 
-  if (v != JSVAL_VOID) {
+  if (v.get() != JSVAL_VOID) {
     ok = ::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull, 0);
     objp.set(obj);
   }
 
   return ok;
 }
 
 // Finalize hook used by document related JS objects, but also by
@@ -9057,17 +9057,17 @@ static inline PRUint32
 PrivateToFlags(void *priv)
 {
   JS_ASSERT(size_t(priv) <= PR_UINT32_MAX && (size_t(priv) & 1) == 0);
   return (PRUint32)(size_t(priv) >> 1);
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
-                                               JSHandleId id, JS::Value *vp)
+                                               JSHandleId id, JSMutableHandleValue vp)
 {
   if (nsDOMClassInfo::sAll_id != id) {
     return JS_TRUE;
   }
 
   JSObject *helper = GetDocumentAllHelper(obj);
 
   if (!helper) {
@@ -9080,22 +9080,22 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
 
   PRUint32 flags = PrivateToFlags(::JS_GetPrivate(helper));
 
   if (flags & JSRESOLVE_DETECTING || !(flags & JSRESOLVE_QUALIFIED)) {
     // document.all is either being detected, e.g. if (document.all),
     // or it was not being resolved with a qualified name. Claim that
     // document.all is undefined.
 
-    vp->setUndefined();
+    vp.setUndefined();
   } else {
     // document.all is not being detected, and it resolved with a
     // qualified name. Expose the document.all collection.
 
-    if (!vp->isObjectOrNull()) { 
+    if (!vp.isObjectOrNull()) { 
       // First time through, create the collection, and set the
       // document as its private nsISupports data.
       nsresult rv;
       nsCOMPtr<nsIHTMLDocument> doc = do_QueryWrapper(cx, obj, &rv);
       if (NS_FAILED(rv)) {
         xpc::Throw(cx, rv);
 
         return JS_FALSE;
@@ -9107,17 +9107,17 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
         return JS_FALSE;
       }
 
       // Let the JSObject take over ownership of doc.
       ::JS_SetPrivate(all, doc);
 
       doc.forget();
 
-      vp->setObject(*all);
+      vp.setObject(*all);
     }
   }
 
   return JS_TRUE;
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -381,21 +381,21 @@ public:
                       JSObject *obj);
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, JSObject * *_retval);
 
   static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                               JSHandleId id, unsigned flags,
                                               JSMutableHandleObject objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
-                                               JSHandleId id, jsval *vp);
+                                               JSHandleId id, JSMutableHandleValue vp);
   static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                          jsval *vp);
+                                          JSMutableHandleValue vp);
   static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                       JSBool strict, jsval *vp);
+                                       JSBool strict, JSMutableHandleValue vp);
   static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
   static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                              nsIHTMLDocument *doc);
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsWindowSH(aData);
   }
 };
@@ -775,23 +775,23 @@ protected:
   }
 
   static JSBool GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 
 public:
   static JSBool DocumentAllGetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                       jsval *vp);
+                                       JSMutableHandleValue vp);
   static JSBool DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       unsigned flags, JSMutableHandleObject objp);
   static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
   static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
   static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
-                                             JSHandleId id, jsval *vp);
+                                             JSHandleId id, JSMutableHandleValue vp);
   static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
                                             JSHandleId id, unsigned flags,
                                             JSMutableHandleObject objp);
   static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
                                           JSHandleId id, unsigned flags,
                                           JSMutableHandleObject objp);
 
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -590,17 +590,17 @@ class CGAbstractClassHook(CGAbstractStat
         assert(False)
 
 class CGAddPropertyHook(CGAbstractClassHook):
     """
     A hook for addProperty, used to preserve our wrapper from GC.
     """
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
-                Argument('JSHandleId', 'id'), Argument('jsval*', 'vp')]
+                Argument('JSHandleId', 'id'), Argument('JSMutableHandleValue', 'vp')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'JSBool', args)
 
     def generate_code(self):
         # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=774279
         # Using a real trace hook might enable us to deal with non-nsISupports
         # wrappercached things here.
         assert self.descriptor.nativeIsISupports
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -106,37 +106,38 @@ NPClass nsJSObjWrapper::sJSObjWrapperNPC
     nsJSObjWrapper::NP_GetProperty,
     nsJSObjWrapper::NP_SetProperty,
     nsJSObjWrapper::NP_RemoveProperty,
     nsJSObjWrapper::NP_Enumerate,
     nsJSObjWrapper::NP_Construct
   };
 
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+
+static JSBool
+NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
 
 static JSBool
-NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
+                         JSMutableHandleValue vp);
 
 static JSBool
-NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
-
-static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
 
 static JSBool
 NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                           jsval *statep, jsid *idp);
 
 static JSBool
 NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                         JSMutableHandleObject objp);
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
 static void
 NPObjWrapper_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, unsigned argc, jsval *vp);
 
 static JSBool
@@ -167,17 +168,17 @@ static JSClass sNPObjectJSWrapperClass =
 typedef struct NPObjectMemberPrivate {
     JSObject *npobjWrapper;
     jsval fieldValue;
     NPIdentifier methodName;
     NPP   npp;
 } NPObjectMemberPrivate;
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
 static void
 NPObjectMember_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjectMember_Call(JSContext *cx, unsigned argc, jsval *vp);
 
 static void
@@ -1187,17 +1188,17 @@ GetNPObject(JSContext *cx, JSObject *obj
 
   return (NPObject *)::JS_GetPrivate(obj);
 }
 
 
 // Does not actually add a property because this is always followed by a
 // SetProperty call.
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1228,17 +1229,17 @@ NPObjWrapper_AddProperty(JSContext *cx, 
 
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->removeProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1253,23 +1254,24 @@ NPObjWrapper_DelProperty(JSContext *cx, 
     if (!ReportExceptionIfPending(cx))
       return JS_FALSE;
 
     if (!hasProperty)
       return JS_TRUE;
   }
 
   if (!npobj->_class->removeProperty(npobj, identifier))
-    *vp = JSVAL_FALSE;
+    vp.set(JSVAL_FALSE);
 
   return ReportExceptionIfPending(cx);
 }
 
 static JSBool
-NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
+NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
+                         JSMutableHandleValue vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->setProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1297,17 +1299,17 @@ NPObjWrapper_SetProperty(JSContext *cx, 
     if (!hasProperty) {
       ThrowJSException(cx, "Trying to set unsupported property on NPObject!");
 
       return JS_FALSE;
     }
   }
 
   NPVariant npv;
-  if (!JSValToNPVariant(npp, cx, *vp, &npv)) {
+  if (!JSValToNPVariant(npp, cx, vp, &npv)) {
     ThrowJSException(cx, "Error converting jsval to NPVariant!");
 
     return JS_FALSE;
   }
 
   JSBool ok = npobj->_class->setProperty(npobj, identifier, &npv);
   _releasevariantvalue(&npv); // Release the variant
   if (!ReportExceptionIfPending(cx))
@@ -1318,17 +1320,17 @@ NPObjWrapper_SetProperty(JSContext *cx, 
 
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod || !npobj->_class->getProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1366,20 +1368,20 @@ NPObjWrapper_GetProperty(JSContext *cx, 
       if (success)
         _releasevariantvalue(&npv);
       return JS_FALSE;
     }
 
     if (success) {
       // We return NPObject Member class here to support ambiguous members.
       if (hasProperty && hasMethod)
-        return CreateNPObjectMember(npp, cx, obj, npobj, id, &npv, vp);
+        return CreateNPObjectMember(npp, cx, obj, npobj, id, &npv, vp.address());
 
       if (hasProperty) {
-        *vp = NPVariantToJSVal(npp, cx, &npv);
+        vp.set(NPVariantToJSVal(npp, cx, &npv));
         _releasevariantvalue(&npv);
 
         if (!ReportExceptionIfPending(cx))
           return JS_FALSE;
       }
     }
     return JS_TRUE;
   }
@@ -1389,21 +1391,21 @@ NPObjWrapper_GetProperty(JSContext *cx, 
     return JS_FALSE;
 
   hasMethod = npobj->_class->hasMethod(npobj, identifier);
   if (!ReportExceptionIfPending(cx))
     return JS_FALSE;
 
   // We return NPObject Member class here to support ambiguous members.
   if (hasProperty && hasMethod)
-    return CreateNPObjectMember(npp, cx, obj, npobj, id, nsnull, vp);
+    return CreateNPObjectMember(npp, cx, obj, npobj, id, nsnull, vp.address());
 
   if (hasProperty) {
     if (npobj->_class->getProperty(npobj, identifier, &npv))
-      *vp = NPVariantToJSVal(npp, cx, &npv);
+      vp.set(NPVariantToJSVal(npp, cx, &npv));
 
     _releasevariantvalue(&npv);
 
     if (!ReportExceptionIfPending(cx))
       return JS_FALSE;
   }
 
   return JS_TRUE;
@@ -1682,17 +1684,17 @@ NPObjWrapper_NewResolve(JSContext *cx, J
     return fnc != nsnull;
   }
 
   // no property or method
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType hint, jsval *vp)
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType hint, JSMutableHandleValue vp)
 {
   JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
 
   // Plugins do not simply use JS_ConvertStub, and the default [[DefaultValue]]
   // behavior, because that behavior involves calling toString or valueOf on
   // objects which weren't designed to accommodate this.  Usually this wouldn't
   // be a problem, because the absence of either property, or the presence of
   // either property with a value that isn't callable, will cause that property
@@ -1701,19 +1703,19 @@ NPObjWrapper_Convert(JSContext *cx, JSHa
   // methods, none of which are nullary, so the JS-reflected method will behave
   // poorly when called with no arguments.  We work around this problem by
   // giving plugins a [[DefaultValue]] which uses only toString and not valueOf.
 
   jsval v = JSVAL_VOID;
   if (!JS_GetProperty(cx, obj, "toString", &v))
     return false;
   if (!JSVAL_IS_PRIMITIVE(v) && JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(v))) {
-    if (!JS_CallFunctionValue(cx, obj, v, 0, NULL, vp))
+    if (!JS_CallFunctionValue(cx, obj, v, 0, NULL, vp.address()))
       return false;
-    if (JSVAL_IS_PRIMITIVE(*vp))
+    if (JSVAL_IS_PRIMITIVE(vp))
       return true;
   }
 
   JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
                        JS_GetClass(obj)->name,
                        hint == JSTYPE_VOID
                        ? "primitive type"
                        : hint == JSTYPE_NUMBER
@@ -2190,39 +2192,39 @@ CreateNPObjectMember(NPP npp, JSContext 
   memberPrivate->npp = npp;
 
   ::JS_RemoveValueRoot(cx, vp);
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp)
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
 {
   NPObjectMemberPrivate *memberPrivate =
     (NPObjectMemberPrivate *)::JS_GetInstancePrivate(cx, obj,
                                                      &sNPObjectMemberClass,
                                                      nsnull);
   if (!memberPrivate) {
     NS_ERROR("no Ambiguous Member Private data!");
     return JS_FALSE;
   }
 
   switch (type) {
   case JSTYPE_VOID:
   case JSTYPE_STRING:
   case JSTYPE_NUMBER:
-    *vp = memberPrivate->fieldValue;
-    if (!JSVAL_IS_PRIMITIVE(*vp)) {
-      return JS_DefaultValue(cx, JSVAL_TO_OBJECT(*vp), type, vp);
+    vp.set(memberPrivate->fieldValue);
+    if (!JSVAL_IS_PRIMITIVE(vp)) {
+      return JS_DefaultValue(cx, JSVAL_TO_OBJECT(vp), type, vp.address());
     }
     return JS_TRUE;
   case JSTYPE_BOOLEAN:
   case JSTYPE_OBJECT:
-    *vp = memberPrivate->fieldValue;
+    vp.set(memberPrivate->fieldValue);
     return JS_TRUE;
   case JSTYPE_FUNCTION:
     // Leave this to NPObjectMember_Call.
     return JS_TRUE;
   default:
     NS_ERROR("illegal operation on JSObject prototype object");
     return JS_FALSE;
   }
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -493,22 +493,25 @@ nsJSON::LegacyDecodeFromStream(nsIInputS
   return DecodeInternal(cx, aStream, aContentLength, true, aRetval, LEGACY);
 }
 
 NS_IMETHODIMP
 nsJSON::LegacyDecodeToJSVal(const nsAString &str, JSContext *cx, jsval *result)
 {
   JSAutoRequest ar(cx);
 
+  JS::RootedValue reviver(cx, JS::NullValue()), value(cx);
+
   if (!js::ParseJSONWithReviver(cx, static_cast<const jschar*>(PromiseFlatString(str).get()),
-                                str.Length(), JS::NullValue(),
-                                result, LEGACY)) {
+                                str.Length(), reviver,
+                                &value, LEGACY)) {
     return NS_ERROR_UNEXPECTED;
   }
 
+  *result = value;
   return NS_OK;
 }
 
 nsresult
 NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult)
 {
   nsJSON* json = new nsJSON();
   if (!json)
@@ -560,21 +563,25 @@ nsJSONListener::OnStopRequest(nsIRequest
 
   // This can happen with short UTF-8 messages (<4 bytes)
   if (!mSniffBuffer.IsEmpty()) {
     // Just consume mSniffBuffer
     rv = ProcessBytes(nsnull, 0);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  JS::RootedValue reviver(mCx, JS::NullValue()), value(mCx);
+
   const jschar* chars = reinterpret_cast<const jschar*>(mBufferedChars.Elements());
   JSBool ok = js::ParseJSONWithReviver(mCx, chars,
                                        (uint32) mBufferedChars.Length(),
-                                       js::NullValue(), mRootVal,
+                                       reviver, &value,
                                        mDecodingMode);
+
+  *mRootVal = value;
   mBufferedChars.TruncateLength(0);
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsJSONListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
                                 nsIInputStream *aStream,
                                 PRUint32 aOffset, PRUint32 aLength)
--- a/dom/workers/ChromeWorkerScope.cpp
+++ b/dom/workers/ChromeWorkerScope.cpp
@@ -41,17 +41,17 @@ UnicodeToNative(JSContext* aCx, const js
   return result;
 }
 
 JSCTypesCallbacks gCTypesCallbacks = {
   UnicodeToNative
 };
 
 JSBool
-CTypesLazyGetter(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, jsval* aVp)
+CTypesLazyGetter(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, JSMutableHandleValue aVp)
 {
   NS_ASSERTION(JS_GetGlobalObject(aCx) == aObj, "Not a global object!");
   NS_ASSERTION(JSID_IS_STRING(aId), "Bad id!");
   NS_ASSERTION(JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), CTYPES_STR),
                "Bad id!");
 
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   NS_ASSERTION(worker->IsChromeWorker(), "This should always be true!");
@@ -62,17 +62,17 @@ CTypesLazyGetter(JSContext* aCx, JSHandl
 
   jsval ctypes;
   if (!JS_DeletePropertyById(aCx, aObj, aId) ||
       !JS_InitCTypesClass(aCx, aObj) ||
       !JS_GetPropertyById(aCx, aObj, aId, &ctypes)) {
     return false;
   }
   JS_SetCTypesCallbacks(JSVAL_TO_OBJECT(ctypes), &gCTypesCallbacks);
-  return JS_GetPropertyById(aCx, aObj, aId, aVp);
+  return JS_GetPropertyById(aCx, aObj, aId, aVp.address());
 }
 #endif
 
 inline bool
 DefineCTypesLazyGetter(JSContext* aCx, JSObject* aGlobal)
 {
 #ifdef BUILD_CTYPES
   {
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -215,39 +215,39 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<Event>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
     if (!GetInstancePrivate(aCx, aObj, name)) {
       return false;
     }
 
-    *aVp = JS_GetReservedSlot(aObj, slot);
+    aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, jsval* aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
     JS_ASSERT(JSID_TO_INT(idval) >= CAPTURING_PHASE &&
               JSID_TO_INT(idval) <= BUBBLING_PHASE);
 
-    *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
+    aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
     return true;
   }
 
   static JSBool
   StopPropagation(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
@@ -505,17 +505,17 @@ private:
 #ifdef DEBUG
       priv->mData = NULL;
 #endif
       delete priv;
     }
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_data && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
@@ -539,21 +539,21 @@ private:
 
       jsval data;
       if (!buffer.read(aCx, &data,
                        WorkerStructuredCloneCallbacks(event->mMainRuntime))) {
         return false;
       }
       JS_SetReservedSlot(aObj, slot, data);
 
-      *aVp = data;
+      aVp.set(data);
       return true;
     }
 
-    *aVp = JS_GetReservedSlot(aObj, slot);
+    aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
   InitMessageEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
@@ -713,31 +713,31 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<ErrorEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_message && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
     ErrorEvent* event = GetInstancePrivate(aCx, aObj, name);
     if (!event) {
       return false;
     }
 
-    *aVp = JS_GetReservedSlot(aObj, slot);
+    aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
   InitErrorEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
@@ -893,31 +893,31 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete GetJSPrivateSafeish<ProgressEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_lengthComputable && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
     ProgressEvent* event = GetInstancePrivate(aCx, aObj, name);
     if (!event) {
       return false;
     }
 
-    *aVp = JS_GetReservedSlot(aObj, slot);
+    aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
   InitProgressEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -121,40 +121,40 @@ private:
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JSClass* classPtr = JS_GetClass(aObj);
 
     if (classPtr != &sClass || !GetJSPrivateSafeish<DOMException>(aObj)) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name,
                            sProperties[slot].name, classPtr->name);
       return false;
     }
 
-    *aVp = JS_GetReservedSlot(aObj, slot);
+    aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, jsval* aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
-    *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
+    aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
     return true;
   }
 };
 
 JSClass DOMException::sClass = {
   "DOMException",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -110,38 +110,38 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMBlob* blob = GetPrivate(aObj);
     NS_IF_RELEASE(blob);
   }
 
   static JSBool
-  GetSize(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetSize(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "size");
     if (!blob) {
       return false;
     }
 
     PRUint64 size;
     if (NS_FAILED(blob->GetSize(&size))) {
       ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
       return false;
     }
 
-    if (!JS_NewNumberValue(aCx, double(size), aVp)) {
+    if (!JS_NewNumberValue(aCx, double(size), aVp.address())) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetType(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetType(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "type");
     if (!blob) {
       return false;
     }
 
     nsString type;
     if (NS_FAILED(blob->GetType(type))) {
@@ -149,17 +149,17 @@ private:
       return false;
     }
 
     JSString* jsType = JS_NewUCStringCopyN(aCx, type.get(), type.Length());
     if (!jsType) {
       return false;
     }
 
-    *aVp = STRING_TO_JSVAL(jsType);
+    aVp.set(STRING_TO_JSVAL(jsType));
 
     return true;
   }
 
   static JSBool
   Slice(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
@@ -301,17 +301,17 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMFile* file = GetPrivate(aObj);
     NS_IF_RELEASE(file);
   }
 
   static JSBool
-  GetMozFullPath(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetMozFullPath(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "mozFullPath");
     if (!file) {
       return false;
     }
 
     nsString fullPath;
 
@@ -322,39 +322,39 @@ private:
     }
 
     JSString* jsFullPath = JS_NewUCStringCopyN(aCx, fullPath.get(),
                                                fullPath.Length());
     if (!jsFullPath) {
       return false;
     }
 
-    *aVp = STRING_TO_JSVAL(jsFullPath);
+    aVp.set(STRING_TO_JSVAL(jsFullPath));
     return true;
   }
 
   static JSBool
-  GetName(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetName(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "name");
     if (!file) {
       return false;
     }
 
     nsString name;
     if (NS_FAILED(file->GetName(name))) {
       name.Truncate();
     }
 
     JSString* jsName = JS_NewUCStringCopyN(aCx, name.get(), name.Length());
     if (!jsName) {
       return false;
     }
 
-    *aVp = STRING_TO_JSVAL(jsName);
+    aVp.set(STRING_TO_JSVAL(jsName));
     return true;
   }
 };
 
 JSClass File::sClass = {
   "File",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
--- a/dom/workers/ImageData.cpp
+++ b/dom/workers/ImageData.cpp
@@ -109,30 +109,30 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<ImageData*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
 
     MOZ_ASSERT(JSID_IS_INT(aIdval));
     MOZ_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
 
-    *aVp = JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval));
+    aVp.set(JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval)));
     return true;
   }
 };
 
 JSClass ImageData::sClass = {
   "ImageData",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
--- a/dom/workers/Location.cpp
+++ b/dom/workers/Location.cpp
@@ -123,30 +123,30 @@ private:
 
     jsval href = JS_GetReservedSlot(obj, SLOT_href);
 
     JS_SET_RVAL(aCx, aVp, href);
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
 
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
 
-    *aVp = JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval));
+    aVp.set(JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval)));
     return true;
   }
 };
 
 JSClass Location::sClass = {
   "WorkerLocation",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -112,30 +112,30 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<Navigator*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
 
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
 
-    *aVp = JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval));
+    aVp.set(JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval)));
     return true;
   }
 };
 
 JSClass Navigator::sClass = {
   "WorkerNavigator",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -149,17 +149,17 @@ protected:
 private:
   // No instance of this class should ever be created so these are explicitly
   // left without an implementation to prevent linking in case someone tries to
   // make one.
   Worker();
   ~Worker();
 
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
@@ -168,35 +168,35 @@ private:
     NS_ConvertASCIItoUTF16 nameStr(name + 2);
     ErrorResult rv;
     JSObject* listener = worker->GetEventListener(nameStr, rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to get listener!");
     }
 
-    *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
+    aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   jsval* aVp)
+                   JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
     }
 
     JSObject* listener;
-    if (!JS_ValueToObject(aCx, *aVp, &listener)) {
+    if (!JS_ValueToObject(aCx, aVp, &listener)) {
       return false;
     }
 
     NS_ConvertASCIItoUTF16 nameStr(name + 2);
     ErrorResult rv;
     worker->SetEventListener(nameStr, listener, rv);
 
     if (rv.Failed()) {
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -132,17 +132,17 @@ protected:
   virtual void
   _finalize(JSFreeOp* aFop) MOZ_OVERRIDE
   {
     EventTarget::_finalize(aFop);
   }
 
 private:
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -153,41 +153,41 @@ private:
     JSObject* listener =
       scope->GetEventListener(NS_ConvertASCIItoUTF16(name + 2), rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to get event listener!");
       return false;
     }
 
-    *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
+    aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   jsval* aVp)
+                   JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
-    if (JSVAL_IS_PRIMITIVE(*aVp)) {
+    if (JSVAL_IS_PRIMITIVE(aVp)) {
       JS_ReportError(aCx, "Not an event listener!");
       return false;
     }
 
     ErrorResult rv;
     scope->SetEventListener(NS_ConvertASCIItoUTF16(name + 2),
-                            JSVAL_TO_OBJECT(*aVp), rv);
+                            JSVAL_TO_OBJECT(aVp), rv);
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to set event listener!");
       return false;
     }
 
     return true;
   }
 
@@ -198,28 +198,28 @@ private:
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
                          sClass.name);
     return false;
   }
 
   static JSBool
-  GetSelf(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetSelf(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     if (!GetInstancePrivate(aCx, aObj, "self")) {
       return false;
     }
 
-    *aVp = OBJECT_TO_JSVAL(aObj);
+    aVp.set(OBJECT_TO_JSVAL(aObj));
     return true;
   }
 
   static JSBool
-  GetLocation(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetLocation(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_location].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_location])) {
@@ -255,17 +255,17 @@ private:
                                             port, pathname, search, hash);
       if (!location) {
         return false;
       }
 
       scope->mSlots[SLOT_location] = OBJECT_TO_JSVAL(location);
     }
 
-    *aVp = scope->mSlots[SLOT_location];
+    aVp.set(scope->mSlots[SLOT_location]);
     return true;
   }
 
   static JSBool
   UnwrapErrorEvent(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JS_ASSERT(aArgc == 1);
     JS_ASSERT((JS_ARGV(aCx, aVp)[0]).isObject());
@@ -298,17 +298,17 @@ private:
         !JS_CallFunctionName(aCx, event, "preventDefault", 0, NULL, &rval)) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
     ErrorResult rv;
@@ -317,38 +317,38 @@ private:
       scope->GetEventListener(NS_ConvertASCIItoUTF16(name + 2), rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to get event listener!");
       return false;
     }
 
     if (!adaptor) {
-      *aVp = JSVAL_NULL;
+      aVp.setNull();
       return true;
     }
 
-    *aVp = js::GetFunctionNativeReserved(adaptor, SLOT_wrappedFunction);
+    aVp.set(js::GetFunctionNativeReserved(adaptor, SLOT_wrappedFunction));
 
-    JS_ASSERT(!JSVAL_IS_PRIMITIVE(*aVp));
+    JS_ASSERT(!JSVAL_IS_PRIMITIVE(aVp));
 
     return true;
   }
 
   static JSBool
   SetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval,
-                     JSBool aStrict, jsval* aVp)
+                     JSBool aStrict, JSMutableHandleValue aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
-    if (JSVAL_IS_PRIMITIVE(*aVp)) {
+    if (JSVAL_IS_PRIMITIVE(aVp)) {
       JS_ReportError(aCx, "Not an event listener!");
       return false;
     }
 
     JSFunction* adaptor =
       js::NewFunctionWithReserved(aCx, UnwrapErrorEvent, 1, 0,
                                   JS_GetGlobalObject(aCx), "unwrap");
     if (!adaptor) {
@@ -357,49 +357,49 @@ private:
 
     JSObject* listener = JS_GetFunctionObject(adaptor);
     if (!listener) {
       return false;
     }
 
     js::SetFunctionNativeReserved(listener, SLOT_wrappedScope,
                                   OBJECT_TO_JSVAL(aObj));
-    js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, *aVp);
+    js::SetFunctionNativeReserved(listener, SLOT_wrappedFunction, aVp);
 
     ErrorResult rv;
 
     scope->SetEventListener(NS_ConvertASCIItoUTF16(name + 2), listener, rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to set event listener!");
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetNavigator(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetNavigator(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_navigator].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_navigator])) {
       JSObject* navigator = navigator::Create(aCx);
       if (!navigator) {
         return false;
       }
 
       scope->mSlots[SLOT_navigator] = OBJECT_TO_JSVAL(navigator);
     }
 
-    *aVp = scope->mSlots[SLOT_navigator];
+    aVp.set(scope->mSlots[SLOT_navigator]);
     return true;
   }
 
   static JSBool
   Close(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
     if (!obj) {
@@ -702,17 +702,17 @@ protected:
     MOZ_COUNT_DTOR(mozilla::dom::workers::DedicatedWorkerGlobalScope);
   }
 
 private:
   using EventTarget::GetEventListener;
   using EventTarget::SetEventListener;
 
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -723,42 +723,42 @@ private:
     JSObject* listener =
       scope->GetEventListener(NS_ConvertASCIItoUTF16(name + 2), rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to get event listener!");
       return false;
     }
 
-    *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
+    aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   jsval* aVp)
+                   JSMutableHandleValue aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
-    if (JSVAL_IS_PRIMITIVE(*aVp)) {
+    if (JSVAL_IS_PRIMITIVE(aVp)) {
       JS_ReportError(aCx, "Not an event listener!");
       return false;
     }
 
     ErrorResult rv;
 
     scope->SetEventListener(NS_ConvertASCIItoUTF16(name + 2),
-                            JSVAL_TO_OBJECT(*aVp), rv);
+                            JSVAL_TO_OBJECT(aVp), rv);
 
     if (rv.Failed()) {
       JS_ReportError(aCx, "Failed to set event listener!");
       return false;
     }
 
     return true;
   }
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -349,17 +349,17 @@ jsval_to_nsString(JSContext* cx, jsid fr
         *to = chars;
         return true;
     }
     return false;
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      jsval *vp)
+                                      JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
 
@@ -376,17 +376,17 @@ ObjectWrapperParent::CPOW_AddProperty(JS
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallAddProperty(in_id,
                                   aco.StatusPtr()) &&
             aco.Ok());
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      jsval *vp)
+                                      JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
 
@@ -398,51 +398,51 @@ ObjectWrapperParent::CPOW_GetProperty(JS
         return JS_FALSE;
 
     JSVariant out_v;
     
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallGetProperty(in_id,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
-            self->jsval_from_JSVariant(cx, out_v, vp));
+            self->jsval_from_JSVariant(cx, out_v, vp.address()));
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, 
-                                      JSBool strict, jsval *vp)
+                                      JSBool strict, JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
 
     AutoCheckOperation aco(cx, self);
 
     nsString in_id;
     JSVariant in_v;
 
     if (!jsval_to_nsString(cx, id, &in_id) ||
-        !self->jsval_to_JSVariant(cx, *vp, &in_v))
+        !self->jsval_to_JSVariant(cx, vp, &in_v))
         return JS_FALSE;
 
     JSVariant out_v;
 
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallSetProperty(in_id, in_v,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
-            self->jsval_from_JSVariant(cx, out_v, vp));
+            self->jsval_from_JSVariant(cx, out_v, vp.address()));
 }    
     
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      jsval *vp)
+                                      JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_DelProperty");
 
@@ -454,17 +454,17 @@ ObjectWrapperParent::CPOW_DelProperty(JS
         return JS_FALSE;
 
     JSVariant out_v;
     
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallDelProperty(in_id,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
-            jsval_from_JSVariant(cx, out_v, vp));
+            jsval_from_JSVariant(cx, out_v, vp.address()));
 }
 
 JSBool
 ObjectWrapperParent::NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp)
 {
     AutoCheckOperation aco(cx, this);
 
     JSVariant out_state;
@@ -575,26 +575,26 @@ ObjectWrapperParent::CPOW_NewResolve(JSC
         JS_DefinePropertyById(cx, obj2, id, JSVAL_VOID, NULL, NULL,
                               JSPROP_ENUMERATE);
     }
     return JS_TRUE;
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type,
-                                  jsval *vp)
+                                  JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_Convert (to %s)...",
               JS_GetTypeName(cx, type)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
 
-    *vp = OBJECT_TO_JSVAL(obj);
+    vp.set(OBJECT_TO_JSVAL(obj));
 
     return JS_TRUE;
 }
 
 /*static*/ void
 ObjectWrapperParent::CPOW_Finalize(js::FreeOp* fop, JSObject* obj)
 {
     CPOW_LOG(("Calling CPOW_Finalize..."));
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -55,40 +55,40 @@ protected:
 
     ContextWrapperParent* Manager();
 
 private:
 
     mutable JSObject* mObj;
 
     static JSBool
-    CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+    CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
 
     static JSBool
-    CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+    CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
 
     static JSBool
-    CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+    CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
     
     static JSBool
-    CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
+    CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
 
     JSBool NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateDestroy(JSContext* cx, jsval state);
     static JSBool
     CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                       jsval *statep, jsid *idp);
 
     static JSBool
     CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                     JSMutableHandleObject objp);
 
     static JSBool
-    CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
+    CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
     static void
     CPOW_Finalize(js::FreeOp* fop, JSObject* obj);
 
     static JSBool
     CPOW_Call(JSContext* cx, unsigned argc, jsval* vp);
 
     static JSBool
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -162,17 +162,17 @@ EvalKernel(JSContext *cx, const CallArgs
     }
 
     // ES5 15.1.2.1 step 1.
     if (args.length() < 1) {
         args.rval().setUndefined();
         return true;
     }
     if (!args[0].isString()) {
-        args.rval() = args[0];
+        args.rval().set(args[0]);
         return true;
     }
     JSString *str = args[0].toString();
 
     // ES5 15.1.2.1 steps 2-8.
 
     // Per ES5, indirect eval runs in the global scope. (eval is specified this
     // way so that the compiler can make assumptions about what bindings may or
@@ -230,22 +230,22 @@ EvalKernel(JSContext *cx, const CallArgs
         for (const jschar *cp = &chars[1], *end = &chars[length - 2]; ; cp++) {
             if (*cp == 0x2028 || *cp == 0x2029)
                 break;
 
             if (cp == end) {
                 bool isArray = (chars[0] == '[');
                 JSONParser parser(cx, isArray ? chars : chars + 1, isArray ? length : length - 2,
                                   JSONParser::StrictJSON, JSONParser::NoError);
-                Value tmp;
+                RootedValue tmp(cx);
                 if (!parser.parse(&tmp))
                     return false;
                 if (tmp.isUndefined())
                     break;
-                args.rval() = tmp;
+                args.rval().set(tmp);
                 return true;
             }
         }
     }
 
     EvalScriptGuard esg(cx);
 
     JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
@@ -272,17 +272,17 @@ EvalKernel(JSContext *cx, const CallArgs
                                                      staticLevel);
         if (!compiled)
             return false;
 
         esg.setNewScript(compiled);
     }
 
     return ExecuteKernel(cx, esg.script(), *scopeobj, thisv, ExecuteType(evalType),
-                         NULL /* evalInFrame */, &args.rval());
+                         NULL /* evalInFrame */, args.rval().address());
 }
 
 // We once supported a second argument to eval to use as the scope chain
 // when evaluating the code string.  Warn when such uses are seen so that
 // authors will know that support for eval(s, o) has been removed.
 static inline bool
 WarnOnTooManyArgs(JSContext *cx, const CallArgs &args)
 {
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -982,26 +982,26 @@ MapObject::construct(JSContext *cx, unsi
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.hasDefined(0)) {
         ForOfIterator iter(cx, args[0]);
         while (iter.next()) {
             JSObject *pairobj = js_ValueToNonNullObject(cx, iter.value());
             if (!pairobj)
                 return false;
 
-            Value key;
+            RootedValue key(cx);
             if (!pairobj->getElement(cx, 0, &key))
                 return false;
             HashableValue hkey;
             if (!hkey.setValue(cx, key))
                 return false;
 
             HashableValue::AutoRooter hkeyRoot(cx, &hkey);
 
-            Value val;
+            RootedValue val(cx);
             if (!pairobj->getElement(cx, 1, &val))
                 return false;
 
             RelocatableValue rval(val);
             if (!map->put(hkey, rval)) {
                 js_ReportOutOfMemory(cx);
                 return false;
             }
@@ -1053,18 +1053,19 @@ MapObject::size(JSContext *cx, unsigned 
 
 bool
 MapObject::get_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(MapObject::is(args.thisv()));
 
     ValueMap &map = extract(args);
     ARG0_KEY(cx, args, key);
+
     if (ValueMap::Entry *p = map.get(key))
-        args.rval() = p->value;
+        args.rval().set(p->value);
     else
         args.rval().setUndefined();
     return true;
 }
 
 JSBool
 MapObject::get(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1274,17 +1275,17 @@ SetIteratorObject::next_impl(JSContext *
     if (!range)
         return js_ThrowStopIteration(cx);
     if (range->empty()) {
         cx->delete_(range);
         thisobj.setReservedSlot(RangeSlot, PrivateValue(NULL));
         return js_ThrowStopIteration(cx);
     }
 
-    args.rval() = range->front().get();
+    args.rval().set(range->front().get());
     range->popFront();
     return true;
 }
 
 JSBool
 SetIteratorObject::next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -17,39 +17,41 @@
 using namespace js;
 using namespace js::types;
 
 class RegExpMatchBuilder
 {
     JSContext   * const cx;
     RootedObject array;
 
-    bool setProperty(Handle<PropertyName*> name, Value v) {
-        return !!baseops::DefineProperty(cx, array, name, &v,
+    bool setProperty(Handle<PropertyName*> name, HandleValue v) {
+        return !!baseops::DefineProperty(cx, array, name, v,
                                          JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
     }
 
   public:
     RegExpMatchBuilder(JSContext *cx, JSObject *array) : cx(cx), array(cx, array) {}
 
-    bool append(uint32_t index, Value v) {
+    bool append(uint32_t index, HandleValue v) {
         JS_ASSERT(!array->getOps()->getElement);
-        return !!baseops::DefineElement(cx, array, index, &v, JS_PropertyStub, JS_StrictPropertyStub,
+        return !!baseops::DefineElement(cx, array, index, v, JS_PropertyStub, JS_StrictPropertyStub,
                                         JSPROP_ENUMERATE);
     }
 
     bool setIndex(int index) {
         Rooted<PropertyName*> name(cx, cx->runtime->atomState.indexAtom);
-        return setProperty(name, Int32Value(index));
+        RootedValue value(cx, Int32Value(index));
+        return setProperty(name, value);
     }
 
     bool setInput(JSString *str) {
         JS_ASSERT(str);
         Rooted<PropertyName*> name(cx, cx->runtime->atomState.inputAtom);
-        return setProperty(name, StringValue(str));
+        RootedValue value(cx, StringValue(str));
+        return setProperty(name, value);
     }
 };
 
 static bool
 CreateRegExpMatchResult(JSContext *cx, JSString *input_, const jschar *chars, size_t length,
                         MatchPairs *matchPairs, Value *rval)
 {
     RootedString input(cx, input_);
@@ -69,28 +71,30 @@ CreateRegExpMatchResult(JSContext *cx, J
 
     if (!input) {
         input = js_NewStringCopyN(cx, chars, length);
         if (!input)
             return false;
     }
 
     RegExpMatchBuilder builder(cx, array);
+    RootedValue undefinedValue(cx, UndefinedValue());
 
     for (size_t i = 0; i < matchPairs->pairCount(); ++i) {
         MatchPair pair = matchPairs->pair(i);
 
         JSString *captured;
         if (pair.isUndefined()) {
             JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
-            if (!builder.append(i, UndefinedValue()))
+            if (!builder.append(i, undefinedValue))
                 return false;
         } else {
             captured = js_NewDependentString(cx, input, pair.start, pair.length());
-            if (!captured || !builder.append(i, StringValue(captured)))
+            RootedValue value(cx, StringValue(captured));
+            if (!captured || !builder.append(i, value))
                 return false;
         }
     }
 
     if (!builder.setIndex(matchPairs->pair(0).start) || !builder.setInput(input))
         return false;
 
     *rval = ObjectValue(*array);
@@ -194,17 +198,17 @@ static bool
 CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
 {
     if (args.length() == 0) {
         RegExpStatics *res = cx->regExpStatics();
         Rooted<JSAtom*> empty(cx, cx->runtime->emptyString);
         RegExpObject *reobj = builder.build(empty, res->getFlags());
         if (!reobj)
             return false;
-        args.rval() = ObjectValue(*reobj);
+        args.rval().setObject(*reobj);
         return true;
     }
 
     Value sourceValue = args[0];
 
     /*
      * If we get passed in an object whose internal [[Class]] property is
      * "RegExp", return a new object with the same source/flags.
@@ -234,26 +238,26 @@ CompileRegExpObject(JSContext *cx, RegEx
 
             flags = g->getFlags();
         }
 
         /*
          * 'toSource' is a permanent read-only property, so this is equivalent
          * to executing RegExpObject::getSource on the unwrapped object.
          */
-        Value v;
+        RootedValue v(cx);
         if (!sourceObj.getProperty(cx, cx->runtime->atomState.sourceAtom, &v))
             return false;
 
         Rooted<JSAtom*> sourceAtom(cx, &v.toString()->asAtom());
         RegExpObject *reobj = builder.build(sourceAtom, flags);
         if (!reobj)
             return false;
 
-        args.rval() = ObjectValue(*reobj);
+        args.rval().setObject(*reobj);
         return true;
     }
 
     RootedAtom source(cx);
     if (sourceValue.isUndefined()) {
         source = cx->runtime->emptyString;
     } else {
         /* Coerce to string and compile. */
@@ -283,17 +287,17 @@ CompileRegExpObject(JSContext *cx, RegEx
     if (!js::detail::RegExpCode::checkSyntax(cx, NULL, escapedSourceStr))
         return false;
 
     RegExpStatics *res = cx->regExpStatics();
     RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
     if (!reobj)
         return false;
 
-    args.rval() = ObjectValue(*reobj);
+    args.rval().setObject(*reobj);
     return true;
 }
 
 static bool
 IsRegExp(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&RegExpClass);
 }
@@ -323,17 +327,17 @@ regexp_construct(JSContext *cx, unsigned
          * If first arg is regexp and no flags are given, just return the arg.
          * Otherwise, delegate to the standard constructor.
          * See ECMAv5 15.10.3.1.
          */
         if (args.hasDefined(0) &&
             IsObjectWithClass(args[0], ESClass_RegExp, cx) &&
             !args.hasDefined(1))
         {
-            args.rval() = args[0];
+            args.rval().set(args[0]);
             return true;
         }
     }
 
     RegExpObjectBuilder builder(cx);
     return CompileRegExpObject(cx, builder, args);
 }
 
@@ -341,17 +345,17 @@ static bool
 regexp_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsRegExp(args.thisv()));
 
     JSString *str = args.thisv().toObject().asRegExp().toString(cx);
     if (!str)
         return false;
 
-    args.rval() = StringValue(str);
+    args.rval().setString(str);
     return true;
 }
 
 static JSBool
 regexp_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsRegExp, regexp_toString_impl, args);
@@ -378,57 +382,57 @@ static JSFunctionSpec regexp_methods[] =
  *  RegExp.lastMatch            $&
  *  RegExp.lastParen            $+
  *  RegExp.leftContext          $`
  *  RegExp.rightContext         $'
  */
 
 #define DEFINE_STATIC_GETTER(name, code)                                        \
     static JSBool                                                               \
-    name(JSContext *cx, HandleObject obj, HandleId id, jsval *vp)               \
+    name(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)   \
     {                                                                           \
         RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
     }
 
-DEFINE_STATIC_GETTER(static_input_getter,        return res->createPendingInput(cx, vp))
-DEFINE_STATIC_GETTER(static_multiline_getter,    *vp = BOOLEAN_TO_JSVAL(res->multiline());
+DEFINE_STATIC_GETTER(static_input_getter,        return res->createPendingInput(cx, vp.address()))
+DEFINE_STATIC_GETTER(static_multiline_getter,    vp.set(BOOLEAN_TO_JSVAL(res->multiline()));
                                                  return true)
-DEFINE_STATIC_GETTER(static_lastMatch_getter,    return res->createLastMatch(cx, vp))
-DEFINE_STATIC_GETTER(static_lastParen_getter,    return res->createLastParen(cx, vp))
-DEFINE_STATIC_GETTER(static_leftContext_getter,  return res->createLeftContext(cx, vp))
-DEFINE_STATIC_GETTER(static_rightContext_getter, return res->createRightContext(cx, vp))
+DEFINE_STATIC_GETTER(static_lastMatch_getter,    return res->createLastMatch(cx, vp.address()))
+DEFINE_STATIC_GETTER(static_lastParen_getter,    return res->createLastParen(cx, vp.address()))
+DEFINE_STATIC_GETTER(static_leftContext_getter,  return res->createLeftContext(cx, vp.address()))
+DEFINE_STATIC_GETTER(static_rightContext_getter, return res->createRightContext(cx, vp.address()))
 
-DEFINE_STATIC_GETTER(static_paren1_getter,       return res->createParen(cx, 1, vp))
-DEFINE_STATIC_GETTER(static_paren2_getter,       return res->createParen(cx, 2, vp))
-DEFINE_STATIC_GETTER(static_paren3_getter,       return res->createParen(cx, 3, vp))
-DEFINE_STATIC_GETTER(static_paren4_getter,       return res->createParen(cx, 4, vp))
-DEFINE_STATIC_GETTER(static_paren5_getter,       return res->createParen(cx, 5, vp))
-DEFINE_STATIC_GETTER(static_paren6_getter,       return res->createParen(cx, 6, vp))
-DEFINE_STATIC_GETTER(static_paren7_getter,       return res->createParen(cx, 7, vp))
-DEFINE_STATIC_GETTER(static_paren8_getter,       return res->createParen(cx, 8, vp))
-DEFINE_STATIC_GETTER(static_paren9_getter,       return res->createParen(cx, 9, vp))
+DEFINE_STATIC_GETTER(static_paren1_getter,       return res->createParen(cx, 1, vp.address()))
+DEFINE_STATIC_GETTER(static_paren2_getter,       return res->createParen(cx, 2, vp.address()))
+DEFINE_STATIC_GETTER(static_paren3_getter,       return res->createParen(cx, 3, vp.address()))
+DEFINE_STATIC_GETTER(static_paren4_getter,       return res->createParen(cx, 4, vp.address()))
+DEFINE_STATIC_GETTER(static_paren5_getter,       return res->createParen(cx, 5, vp.address()))
+DEFINE_STATIC_GETTER(static_paren6_getter,       return res->createParen(cx, 6, vp.address()))
+DEFINE_STATIC_GETTER(static_paren7_getter,       return res->createParen(cx, 7, vp.address()))
+DEFINE_STATIC_GETTER(static_paren8_getter,       return res->createParen(cx, 8, vp.address()))
+DEFINE_STATIC_GETTER(static_paren9_getter,       return res->createParen(cx, 9, vp.address()))
 
 #define DEFINE_STATIC_SETTER(name, code)                                        \
     static JSBool                                                               \
-    name(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, jsval *vp)\
+    name(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)\
     {                                                                           \
         RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
         return true;                                                            \
     }
 
 DEFINE_STATIC_SETTER(static_input_setter,
-                     if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp))
+                     if (!JSVAL_IS_STRING(vp) && !JS_ConvertValue(cx, vp, JSTYPE_STRING, vp.address()))
                          return false;
-                     res->setPendingInput(JSVAL_TO_STRING(*vp)))
+                     res->setPendingInput(JSVAL_TO_STRING(vp)))
 DEFINE_STATIC_SETTER(static_multiline_setter,
-                     if (!JSVAL_IS_BOOLEAN(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp))
+                     if (!JSVAL_IS_BOOLEAN(vp) && !JS_ConvertValue(cx, vp, JSTYPE_BOOLEAN, vp.address()))
                          return false;
-                     res->setMultiline(cx, !!JSVAL_TO_BOOLEAN(*vp)))
+                     res->setMultiline(cx, !!JSVAL_TO_BOOLEAN(vp)))
 
 const uint8_t REGEXP_STATIC_PROP_ATTRS    = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE;
 const uint8_t RO_REGEXP_STATIC_PROP_ATTRS = REGEXP_STATIC_PROP_ATTRS | JSPROP_READONLY;
 
 const uint8_t HIDDEN_PROP_ATTRS = JSPROP_PERMANENT | JSPROP_SHARED;
 const uint8_t RO_HIDDEN_PROP_ATTRS = HIDDEN_PROP_ATTRS | JSPROP_READONLY;
 
 static JSPropertySpec regexp_static_props[] = {
@@ -586,24 +590,24 @@ ExecuteRegExp(JSContext *cx, RegExpExecT
         i = 0;
 
     const jschar *chars = linearInput->chars();
     size_t length = linearInput->length();
 
     /* Step 9a. */
     if (i < 0 || i > length) {
         reobj->zeroLastIndex();
-        args.rval() = NullValue();
+        args.rval().setNull();
         return true;
     }
 
     /* Steps 8-21. */
     size_t lastIndexInt(i);
     if (!ExecuteRegExp(cx, res, *re, linearInput, chars, length, &lastIndexInt, execType,
-                       &args.rval())) {
+                       args.rval().address())) {
         return false;
     }
 
     /* Step 11 (with sticky extension). */
     if (re->global() || (!args.rval().isNull() && re->sticky())) {
         if (args.rval().isNull())
             reobj->zeroLastIndex();
         else
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -49,22 +49,22 @@ namespace CType {
   static JSBool ConstructData(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructBasic(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static void Trace(JSTracer* trc, JSObject* obj);
   static void Finalize(JSFreeOp *fop, JSObject* obj);
   static void FinalizeProtoClass(JSFreeOp *fop, JSObject* obj);
 
   static JSBool PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
-  static JSBool PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
+    MutableHandleValue vp);
+  static JSBool PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp);
   static JSBool CreateArray(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool HasInstance(JSContext* cx, JSHandleObject obj, const jsval* v, JSBool* bp);
 
 
   /*
    * Get the global "ctypes" object.
@@ -82,99 +82,99 @@ namespace ABI {
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace PointerType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool TargetTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool ContentsGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool ContentsSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool IsNull(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool Increment(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool Decrement(JSContext* cx, unsigned argc, jsval* vp);
   // The following is not an instance function, since we don't want to expose arbitrary
   // pointer arithmetic at this moment.
   static JSBool OffsetBy(JSContext* cx, int offset, jsval* vp);
 }
 
 namespace ArrayType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool LengthGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
-  static JSBool Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
-  static JSBool Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp);
+    MutableHandleValue vp);
+  static JSBool Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp);
+  static JSBool Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp);
   static JSBool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace StructType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict,
-                            jsval* vp);
+                            MutableHandleValue vp);
   static JSBool AddressOfField(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool Define(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace FunctionType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSHandleObject typeObj,
     JSHandleObject dataObj, JSHandleObject fnObj, JSHandleObject thisObj, jsval errVal);
 
   static JSBool Call(JSContext* cx, unsigned argc, jsval* vp);
 
   static JSBool ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
   static JSBool ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
-  static JSBool ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
+    MutableHandleValue vp);
+  static JSBool ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp);
   static JSBool IsVariadicGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-    jsval* vp);
+    MutableHandleValue vp);
 }
 
 namespace CClosure {
   static void Trace(JSTracer* trc, JSObject* obj);
   static void Finalize(JSFreeOp *fop, JSObject* obj);
 
   // libffi callback
   static void ClosureStub(ffi_cif* cif, void* result, void** args,
     void* userData);
 }
 
 namespace CData {
   static void Finalize(JSFreeOp *fop, JSObject* obj);
 
   static JSBool ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-                            jsval* vp);
+                            MutableHandleValue vp);
   static JSBool ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-                            JSBool strict, jsval* vp);
+                            JSBool strict, MutableHandleValue vp);
   static JSBool Address(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ReadString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
   static JSString *GetSourceString(JSContext *cx, JSHandleObject typeObj,
                                    void *data);
   static JSBool ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-                            jsval* vp);
+                            MutableHandleValue vp);
 
 #if defined(XP_WIN)
   static JSBool LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
-                                jsval* vp);
+                                MutableHandleValue vp);
 #endif // defined(XP_WIN)
 }
 
 namespace CDataFinalizer {
   /*
    * Attach a C function as a finalizer to a JS object.
    *
    * This function is available from JS as |ctypes.withFinalizer|.
@@ -3364,72 +3364,72 @@ CType::GetProtoFromType(JSObject* obj, C
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
   return JSVAL_TO_OBJECT(result);
 }
 
 JSBool
-CType::PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+CType::PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!(CType::IsCType(obj) || CType::IsCTypeProto(obj))) {
     JS_ReportError(cx, "not a CType or CTypeProto");
     return JS_FALSE;
   }
 
   unsigned slot = CType::IsCTypeProto(obj) ? (unsigned) SLOT_OURDATAPROTO
                                            : (unsigned) SLOT_PROTO;
-  *vp = JS_GetReservedSlot(obj, slot);
-  JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) || JSVAL_IS_VOID(*vp));
+  vp.set(JS_GetReservedSlot(obj, slot));
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp) || JSVAL_IS_VOID(vp));
   return JS_TRUE;
 }
 
 JSBool
-CType::NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+CType::NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   JSString* name = CType::GetName(cx, obj);
   if (!name)
     return JS_FALSE;
 
-  *vp = STRING_TO_JSVAL(name);
+  vp.set(STRING_TO_JSVAL(name));
   return JS_TRUE;
 }
 
 JSBool
-CType::SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+CType::SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_SIZE);
-  JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
+  vp.set(JS_GetReservedSlot(obj, SLOT_SIZE));
+  JS_ASSERT(JSVAL_IS_NUMBER(vp) || JSVAL_IS_VOID(vp));
   return JS_TRUE;
 }
 
 JSBool
-CType::PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+CType::PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   JSObject* pointerType = PointerType::CreateInternal(cx, obj);
   if (!pointerType)
     return JS_FALSE;
 
-  *vp = OBJECT_TO_JSVAL(pointerType);
+  vp.set(OBJECT_TO_JSVAL(pointerType));
   return JS_TRUE;
 }
 
 JSBool
 CType::CreateArray(JSContext* cx, unsigned argc, jsval* vp)
 {
   JSObject* baseType = JS_THIS_OBJECT(cx, vp);
   if (!baseType)
@@ -3764,25 +3764,25 @@ PointerType::GetBaseType(JSObject* obj)
   JS_ASSERT(!JSVAL_IS_NULL(type));
   return JSVAL_TO_OBJECT(type);
 }
 
 JSBool
 PointerType::TargetTypeGetter(JSContext* cx,
                               JSHandleObject obj,
                               JSHandleId idval,
-                              jsval* vp)
+                              MutableHandleValue vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_TARGET_T);
-  JS_ASSERT(vp->isObject());
+  vp.set(JS_GetReservedSlot(obj, SLOT_TARGET_T));
+  JS_ASSERT(vp.isObject());
   return JS_TRUE;
 }
 
 JSBool
 PointerType::IsNull(JSContext* cx, unsigned argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
@@ -3852,17 +3852,17 @@ PointerType::Decrement(JSContext* cx, un
 {
   return OffsetBy(cx, -1, vp);
 }
 
 JSBool
 PointerType::ContentsGetter(JSContext* cx,
                             JSHandleObject obj,
                             JSHandleId idval,
-                            jsval* vp)
+                            MutableHandleValue vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Get pointer type and base type.
   JSObject* typeObj = CData::GetCType(obj);
@@ -3882,26 +3882,26 @@ PointerType::ContentsGetter(JSContext* c
     JS_ReportError(cx, "cannot read contents of null pointer");
     return JS_FALSE;
   }
 
   jsval result;
   if (!ConvertToJS(cx, baseType, NULL, data, false, false, &result))
     return JS_FALSE;
 
-  JS_SET_RVAL(cx, vp, result);
+  JS_SET_RVAL(cx, vp.address(), result);
   return JS_TRUE;
 }
 
 JSBool
 PointerType::ContentsSetter(JSContext* cx,
                             JSHandleObject obj,
                             JSHandleId idval,
                             JSBool strict,
-                            jsval* vp)
+                            MutableHandleValue vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Get pointer type and base type.
   JSObject* typeObj = CData::GetCType(obj);
@@ -3917,17 +3917,17 @@ PointerType::ContentsSetter(JSContext* c
   }
 
   void* data = *static_cast<void**>(CData::GetData(obj));
   if (data == NULL) {
     JS_ReportError(cx, "cannot write contents to null pointer");
     return JS_FALSE;
   }
 
-  return ImplicitConvert(cx, *vp, baseType, data, false, NULL);
+  return ImplicitConvert(cx, vp, baseType, data, false, NULL);
 }
 
 /*******************************************************************************
 ** ArrayType implementation
 *******************************************************************************/
 
 JSBool
 ArrayType::Create(JSContext* cx, unsigned argc, jsval* vp)
@@ -4211,50 +4211,50 @@ ArrayType::BuildFFIType(JSContext* cx, J
   for (size_t i = 0; i < length; ++i)
     ffiType->elements[i] = ffiBaseType;
   ffiType->elements[length] = NULL;
 
   return ffiType.forget();
 }
 
 JSBool
-ArrayType::ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+ArrayType::ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_ELEMENT_T);
-  JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+  vp.set(JS_GetReservedSlot(obj, SLOT_ELEMENT_T));
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp));
   return JS_TRUE;
 }
 
 JSBool
-ArrayType::LengthGetter(JSContext* cx, JSHandleObject obj_, JSHandleId idval, jsval* vp)
+ArrayType::LengthGetter(JSContext* cx, JSHandleObject obj_, JSHandleId idval, MutableHandleValue vp)
 {
   JSObject *obj = obj_;
 
   // This getter exists for both CTypes and CDatas of the ArrayType persuasion.
   // If we're dealing with a CData, get the CType from it.
   if (CData::IsCData(obj))
     obj = CData::GetCType(obj);
 
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_LENGTH);
-  JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
+  vp.set(JS_GetReservedSlot(obj, SLOT_LENGTH));
+  JS_ASSERT(JSVAL_IS_NUMBER(vp) || JSVAL_IS_VOID(vp));
   return JS_TRUE;
 }
 
 JSBool
-ArrayType::Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+ArrayType::Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   // This should never happen, but we'll check to be safe.
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Bail early if we're not an ArrayType. (This setter is present for all
@@ -4276,21 +4276,21 @@ ArrayType::Getter(JSContext* cx, JSHandl
   if (!ok || index >= length) {
     JS_ReportError(cx, "invalid index");
     return JS_FALSE;
   }
 
   JSObject* baseType = GetBaseType(typeObj);
   size_t elementSize = CType::GetSize(baseType);
   char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
-  return ConvertToJS(cx, baseType, obj, data, false, false, vp);
+  return ConvertToJS(cx, baseType, obj, data, false, false, vp.address());
 }
 
 JSBool
-ArrayType::Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
+ArrayType::Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
   // This should never happen, but we'll check to be safe.
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Bail early if we're not an ArrayType. (This setter is present for all
@@ -4312,17 +4312,17 @@ ArrayType::Setter(JSContext* cx, JSHandl
   if (!ok || index >= length) {
     JS_ReportError(cx, "invalid index");
     return JS_FALSE;
   }
 
   JSObject* baseType = GetBaseType(typeObj);
   size_t elementSize = CType::GetSize(baseType);
   char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
-  return ImplicitConvert(cx, *vp, baseType, data, false, NULL);
+  return ImplicitConvert(cx, vp, baseType, data, false, NULL);
 }
 
 JSBool
 ArrayType::AddressOfElement(JSContext* cx, unsigned argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
@@ -4873,47 +4873,47 @@ StructType::BuildFieldsArray(JSContext* 
   // Seal the fields array.
   if (!JS_FreezeObject(cx, fieldsProp))
     return NULL;
 
   return fieldsProp;
 }
 
 JSBool
-StructType::FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+StructType::FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_struct) {
     JS_ReportError(cx, "not a StructType");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_FIELDS);
+  vp.set(JS_GetReservedSlot(obj, SLOT_FIELDS));
 
   if (!CType::IsSizeDefined(obj)) {
-    JS_ASSERT(JSVAL_IS_VOID(*vp));
+    JS_ASSERT(JSVAL_IS_VOID(vp));
     return JS_TRUE;
   }
 
-  if (JSVAL_IS_VOID(*vp)) {
+  if (JSVAL_IS_VOID(vp)) {
     // Build the 'fields' array lazily.
     JSObject* fields = BuildFieldsArray(cx, obj);
     if (!fields)
       return JS_FALSE;
     JS_SetReservedSlot(obj, SLOT_FIELDS, OBJECT_TO_JSVAL(fields));
 
-    *vp = OBJECT_TO_JSVAL(fields);
-  }
-
-  JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) &&
-            JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*vp)));
+    vp.set(OBJECT_TO_JSVAL(fields));
+  }
+
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp) &&
+            JS_IsArrayObject(cx, JSVAL_TO_OBJECT(vp)));
   return JS_TRUE;
 }
 
 JSBool
-StructType::FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+StructType::FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_struct) {
@@ -4921,21 +4921,21 @@ StructType::FieldGetter(JSContext* cx, J
     return JS_FALSE;
   }
 
   const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_FLAT_STRING(idval));
   if (!field)
     return JS_FALSE;
 
   char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
-  return ConvertToJS(cx, field->mType, obj, data, false, false, vp);
+  return ConvertToJS(cx, field->mType, obj, data, false, false, vp.address());
 }
 
 JSBool
-StructType::FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
+StructType::FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_struct) {
@@ -4943,17 +4943,17 @@ StructType::FieldSetter(JSContext* cx, J
     return JS_FALSE;
   }
 
   const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_FLAT_STRING(idval));
   if (!field)
     return JS_FALSE;
 
   char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
-  return ImplicitConvert(cx, *vp, field->mType, data, false, NULL);
+  return ImplicitConvert(cx, vp, field->mType, data, false, NULL);
 }
 
 JSBool
 StructType::AddressOfField(JSContext* cx, unsigned argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
@@ -5641,24 +5641,24 @@ CheckFunctionType(JSContext* cx, JSObjec
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_function) {
     JS_ReportError(cx, "not a FunctionType");
     return JS_FALSE;
   }
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+FunctionType::ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Check if we have a cached argTypes array.
-  *vp = JS_GetReservedSlot(obj, SLOT_ARGS_T);
-  if (!JSVAL_IS_VOID(*vp))
+  vp.set(JS_GetReservedSlot(obj, SLOT_ARGS_T));
+  if (!JSVAL_IS_VOID(vp))
     return JS_TRUE;
 
   FunctionInfo* fninfo = GetFunctionInfo(obj);
   size_t len = fninfo->mArgTypes.length();
 
   // Prepare a new array.
   Array<jsval, 16> vec;
   if (!vec.resize(len))
@@ -5671,49 +5671,49 @@ FunctionType::ArgTypesGetter(JSContext* 
   if (!argTypes)
     return JS_FALSE;
 
   // Seal and cache it.
   if (!JS_FreezeObject(cx, argTypes))
     return JS_FALSE;
   JS_SetReservedSlot(obj, SLOT_ARGS_T, OBJECT_TO_JSVAL(argTypes));
 
-  *vp = OBJECT_TO_JSVAL(argTypes);
+  vp.set(OBJECT_TO_JSVAL(argTypes));
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+FunctionType::ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Get the returnType object from the FunctionInfo.
-  *vp = OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mReturnType);
+  vp.set(OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mReturnType));
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+FunctionType::ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Get the abi object from the FunctionInfo.
-  *vp = OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mABI);
+  vp.set(OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mABI));
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::IsVariadicGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+FunctionType::IsVariadicGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
-  *vp = BOOLEAN_TO_JSVAL(GetFunctionInfo(obj)->mIsVariadic);
+  vp.set(BOOLEAN_TO_JSVAL(GetFunctionInfo(obj)->mIsVariadic));
   return JS_TRUE;
 }
 
 /*******************************************************************************
 ** CClosure implementation
 *******************************************************************************/
 
 JSObject*
@@ -6147,39 +6147,39 @@ CData::IsCData(JSObject* obj)
 
 bool
 CData::IsCDataProto(JSObject* obj)
 {
   return JS_GetClass(obj) == &sCDataProtoClass;
 }
 
 JSBool
-CData::ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
+CData::ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Convert the value to a primitive; do not create a new CData object.
-  if (!ConvertToJS(cx, GetCType(obj), NULL, GetData(obj), true, false, vp))
+  if (!ConvertToJS(cx, GetCType(obj), NULL, GetData(obj), true, false, vp.address()))
     return JS_FALSE;
 
   return JS_TRUE;
 }
 
 JSBool
-CData::ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
+CData::ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
-  return ImplicitConvert(cx, *vp, GetCType(obj), GetData(obj), false, NULL);
+  return ImplicitConvert(cx, vp, GetCType(obj), GetData(obj), false, NULL);
 }
 
 JSBool
 CData::Address(JSContext* cx, unsigned argc, jsval* vp)
 {
   if (argc != 0) {
     JS_ReportError(cx, "address takes zero arguments");
     return JS_FALSE;
@@ -6427,38 +6427,37 @@ CData::ToSource(JSContext* cx, unsigned 
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CData::ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId, jsval* vp)
+CData::ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId, MutableHandleValue vp)
 {
   if (!IsCTypesGlobal(obj)) {
     JS_ReportError(cx, "this is not not global object ctypes");
     return JS_FALSE;
   }
 
-  *vp = JS_GetReservedSlot(obj, SLOT_ERRNO);
+  vp.set(JS_GetReservedSlot(obj, SLOT_ERRNO));
   return JS_TRUE;
 }
 
 #if defined(XP_WIN)
 JSBool
-CData::LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId, jsval* vp)
+CData::LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId, MutableHandleValue vp)
 {
   if (!IsCTypesGlobal(obj)) {
     JS_ReportError(cx, "not global object ctypes");
     return JS_FALSE;
   }
 
-
-  *vp = JS_GetReservedSlot(obj, SLOT_LASTERROR);
+  vp.set(JS_GetReservedSlot(obj, SLOT_LASTERROR));
   return JS_TRUE;
 }
 #endif // defined(XP_WIN)
 
 JSBool
 CDataFinalizer::Methods::ToSource(JSContext *cx, unsigned argc, jsval *vp)
 {
   RootedObject objThis(cx, JS_THIS_OBJECT(cx, vp));
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3731,19 +3731,19 @@ ParseNode::getConstantValue(JSContext *c
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         RootedObject obj(cx, NewDenseAllocatedArray(cx, pn_count));
         if (!obj)
             return false;
 
         unsigned idx = 0;
         RootedId id(cx);
+        RootedValue value(cx);
         for (ParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) {
-            Value value;
-            if (!pn->getConstantValue(cx, strictChecks, &value))
+            if (!pn->getConstantValue(cx, strictChecks, value.address()))
                 return false;
             id = INT_TO_JSID(idx);
             if (!obj->defineGeneric(cx, id, value, NULL, NULL, JSPROP_ENUMERATE))
                 return false;
         }
         JS_ASSERT(idx == pn_count);
 
         types::FixArrayType(cx, obj);
@@ -3754,18 +3754,18 @@ ParseNode::getConstantValue(JSContext *c
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         gc::AllocKind kind = GuessObjectGCKind(pn_count);
         RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
         if (!obj)
             return false;
 
         for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) {
-            Value value;
-            if (!pn->pn_right->getConstantValue(cx, strictChecks, &value))
+            RootedValue value(cx);
+            if (!pn->pn_right->getConstantValue(cx, strictChecks, value.address()))
                 return false;
 
             ParseNode *pnid = pn->pn_left;
             if (pnid->isKind(PNK_NUMBER)) {
                 Value idvalue = NumberValue(pnid->pn_dval);
                 RootedId id(cx);
                 if (idvalue.isInt32() && INT_FITS_IN_JSID(idvalue.toInt32()))
                     id = INT_TO_JSID(idvalue.toInt32());
@@ -5747,17 +5747,18 @@ EmitObject(JSContext *cx, BytecodeEmitte
              */
             if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
                 obj = NULL;
             op = JSOP_INITPROP;
 
             if (obj) {
                 JS_ASSERT(!obj->inDictionaryMode());
                 Rooted<jsid> id(cx, AtomToId(pn3->pn_atom));
-                if (!DefineNativeProperty(cx, obj, id, UndefinedValue(), NULL, NULL,
+                RootedValue undefinedValue(cx, UndefinedValue());
+                if (!DefineNativeProperty(cx, obj, id, undefinedValue, NULL, NULL,
                                           JSPROP_ENUMERATE, 0, 0))
                 {
                     return false;
                 }
                 if (obj->inDictionaryMode())
                     obj = NULL;
             }
 
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1429,16 +1429,18 @@ TokenStream::getTokenInternal()
     int c, qc;
     Token *tp;
     FirstCharKind c1kind;
     const jschar *numStart;
     bool hasFracOrExp;
     const jschar *identStart;
     bool hadUnicodeEscape;
 
+    SkipRoot skipNum(cx, &numStart), skipIdent(cx, &identStart);
+
 #if JS_HAS_XML_SUPPORT
     /*
      * Look for XML text and tags.
      */
     if (flags & (TSF_XMLTEXTMODE|TSF_XMLTAGMODE)) {
         if (!getXMLTextOrTag(&tt, &tp))
             goto error;
         goto out;
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -57,16 +57,17 @@ namespace JS {
  *   generally use handles for those arguments and avoid any explicit rooting.
  *   This has two benefits. First, when several such functions call each other
  *   then redundant rooting of multiple copies of the GC thing can be avoided.
  *   Second, if the caller does not pass a rooted value a compile error will be
  *   generated, which is quicker and easier to fix than when relying on a
  *   separate rooting analysis.
  */
 
+template <typename T> class MutableHandle;
 template <typename T> class Rooted;
 
 template <typename T>
 struct RootMethods { };
 
 /*
  * Handle provides an implicit constructor for NullPtr so that, given:
  *   foo(Handle<JSObject*> h);
@@ -133,16 +134,22 @@ class Handle : public HandleBase<T>
      * Construct a handle from an explicitly rooted location. This is the
      * normal way to create a handle, and normally happens implicitly.
      */
     template <typename S>
     inline
     Handle(Rooted<S> &root,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
 
+    /* Construct a read only handle from a mutable handle. */
+    template <typename S>
+    inline
+    Handle(MutableHandle<S> &root,
+           typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
+
     const T *address() const { return ptr; }
     T get() const { return *ptr; }
 
     operator T () const { return get(); }
     T operator ->() const { return get(); }
 
   private:
     Handle() {}
@@ -211,16 +218,19 @@ class MutableHandle : public MutableHand
 
     operator T () const { return get(); }
     T operator ->() const { return get(); }
 
   private:
     MutableHandle() {}
 
     T *ptr;
+
+    template <typename S>
+    void operator =(S v) MOZ_DELETE;
 };
 
 typedef MutableHandle<JSObject*>    MutableHandleObject;
 typedef MutableHandle<Value>        MutableHandleValue;
 
 /*
  * By default, pointers should use the inheritance hierarchy to find their
  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
@@ -317,16 +327,24 @@ inline
 Handle<T>::Handle(Rooted<S> &root,
                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
 {
     ptr = reinterpret_cast<const T *>(root.address());
 }
 
 template<typename T> template <typename S>
 inline
+Handle<T>::Handle(MutableHandle<S> &root,
+                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
+{
+    ptr = reinterpret_cast<const T *>(root.address());
+}
+
+template<typename T> template <typename S>
+inline
 MutableHandle<T>::MutableHandle(Rooted<S> *root,
                                 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
 {
     ptr = root->address();
 }
 
 typedef Rooted<JSObject*>    RootedObject;
 typedef Rooted<JSFunction*>  RootedFunction;
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -16,18 +16,20 @@ namespace js {
 namespace analyze {
 
 /////////////////////////////////////////////////////////////////////
 // Bytecode
 /////////////////////////////////////////////////////////////////////
 
 #ifdef DEBUG
 void
-PrintBytecode(JSContext *cx, JSScript *script, jsbytecode *pc)
+PrintBytecode(JSContext *cx, JSScript *scriptArg, jsbytecode *pc)
 {
+    RootedScript script(cx, scriptArg);
+
     printf("#%u:", script->id());
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return;
     js_Disassemble1(cx, script, pc, pc - script->code, true, &sprinter);
     fprintf(stdout, "%s", sprinter.string());
 }
 #endif
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -9,17 +9,17 @@
 #include "tests.h"
 
 /* Do the test a bunch of times, because sometimes we seem to randomly
    miss the propcache */
 static const int expectedCount = 100;
 static int callCount = 0;
 
 static JSBool
-addProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
+addProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
   callCount++;
   return true;
 }
 
 JSClass addPropertyClass = {
     "AddPropertyTester",
     0,
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -25,17 +25,17 @@ IsCustomClass(const Value &v)
 {
   return v.isObject() && JS_GetClass(&v.toObject()) == &CustomClass;
 }
 
 static bool
 CustomMethodImpl(JSContext *cx, CallArgs args)
 {
   JS_ASSERT(IsCustomClass(args.thisv()));
-  args.rval() = JS_GetReservedSlot(&args.thisv().toObject(), CUSTOM_SLOT);
+  args.rval().set(JS_GetReservedSlot(&args.thisv().toObject(), CUSTOM_SLOT));
   return true;
 }
 
 static JSBool
 CustomMethod(JSContext *cx, unsigned argc, Value *vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod(cx, IsCustomClass, CustomMethodImpl, args);
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -8,17 +8,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 int called_test_fn;
 int called_test_prop_get;
 
-static JSBool test_prop_get( JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp )
+static JSBool test_prop_get( JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp )
 {
     called_test_prop_get++;
     return JS_TRUE;
 }
 
 static JSBool
 PTest(JSContext* cx, unsigned argc, jsval *vp);
 
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -6,20 +6,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 static JSBool
-my_convert(JSContext* context, JS::HandleObject obj, JSType type, jsval* rval)
+my_convert(JSContext* context, JS::HandleObject obj, JSType type, JS::MutableHandleValue rval)
 {
     if (type == JSTYPE_VOID || type == JSTYPE_STRING || type == JSTYPE_NUMBER || type == JSTYPE_BOOLEAN)
-        return JS_NewNumberValue(context, 123, rval);
+        return JS_NewNumberValue(context, 123, rval.address());
     return JS_FALSE;
 }
 
 static JSClass myClass = {
     "MyClass",
     0,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, my_convert
--- a/js/src/jsapi-tests/testPropCache.cpp
+++ b/js/src/jsapi-tests/testPropCache.cpp
@@ -6,17 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 static int g_counter;
 
 static JSBool
-CounterAdd(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
+CounterAdd(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
     g_counter++;
     return JS_TRUE;
 }
 
 static JSClass CounterClass = {
     "Counter",  /* name */
     0,  /* flags */
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -4,19 +4,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 static JSBool
-nativeGet(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
+nativeGet(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
-    *vp = INT_TO_JSVAL(17);
+    vp.set(INT_TO_JSVAL(17));
     return JS_TRUE;
 }
 
 BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
 {
     jsvalRoot vobj(cx);
     JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
     CHECK(obj);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1950,17 +1950,18 @@ JS_ResolveStandardClass(JSContext *cx, J
         return true;
 
     idstr = JSID_TO_STRING(id);
 
     /* Check whether we're resolving 'undefined', and define it if so. */
     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
     if (idstr == atom) {
         *resolved = true;
-        return obj->defineProperty(cx, atom->asPropertyName(), UndefinedValue(),
+        RootedValue value(cx, UndefinedValue());
+        return obj->defineProperty(cx, atom->asPropertyName(), value,
                                    JS_PropertyStub, JS_StrictPropertyStub,
                                    JSPROP_PERMANENT | JSPROP_READONLY);
     }
 
     /* Try for class constructors/prototypes named by well-known atoms. */
     stdnm = NULL;
     for (i = 0; standard_class_atoms[i].init; i++) {
         JS_ASSERT(standard_class_atoms[i].clasp);
@@ -2042,18 +2043,19 @@ JS_EnumerateStandardClasses(JSContext *c
     RootedObject obj(cx, obj_);
 
     /*
      * Check whether we need to bind 'undefined' and define it if so.
      * Since ES5 15.1.1.3 undefined can't be deleted.
      */
     RootedPropertyName undefinedName(cx, cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
     RootedId undefinedId(cx, NameToId(undefinedName));
+    RootedValue undefinedValue(cx, UndefinedValue());
     if (!obj->nativeContains(cx, undefinedId) &&
-        !obj->defineProperty(cx, undefinedName, UndefinedValue(),
+        !obj->defineProperty(cx, undefinedName, undefinedValue,
                              JS_PropertyStub, JS_StrictPropertyStub,
                              JSPROP_PERMANENT | JSPROP_READONLY)) {
         return false;
     }
 
     /* Initialize any classes that have not been initialized yet. */
     for (unsigned i = 0; standard_class_atoms[i].init; i++) {
         const JSStdName &stdnm = standard_class_atoms[i];
@@ -3190,27 +3192,33 @@ JS_IdToValue(JSContext *cx, jsid id, jsv
 
 JS_PUBLIC_API(JSBool)
 JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(obj != NULL);
     JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
-    return obj->defaultValue(cx, hint, vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
+
+    RootedValue value(cx);
+    if (!obj->defaultValue(cx, hint, &value))
+        return false;
+
+    *vp = value;
+    return true;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_EnumerateStub(JSContext *cx, JSHandleObject obj)
 {
     return JS_TRUE;
@@ -3218,17 +3226,17 @@ JS_EnumerateStub(JSContext *cx, JSHandle
 
 JS_PUBLIC_API(JSBool)
 JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp)
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
 {
     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
     JS_ASSERT(obj);
     return DefaultValue(cx, obj, type, vp);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj_, JSObject *parent_proto,
@@ -3345,17 +3353,17 @@ JS_SetParent(JSContext *cx, JSObject *ob
     Rooted<JSObject*> obj(cx, obj_);
     Rooted<JSObject*> parent(cx, parent_);
     return JSObject::setParent(cx, obj, parent);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetConstructor(JSContext *cx, JSObject *proto)
 {
-    Value cval;
+    RootedValue cval(cx);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto);
     {
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
         if (!proto->getProperty(cx, cx->runtime->atomState.constructorAtom, &cval))
@@ -4150,25 +4158,38 @@ JS_ForwardGetPropertyTo(JSContext *cx, J
     RootedId id(cx, id_);
     RootedObject onBehalfOf(cx, onBehalfOf_);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     assertSameCompartment(cx, onBehalfOf);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
-    return obj->getGeneric(cx, onBehalfOf, id, vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj_, jsid id_, jsval def, jsval *vp)
+
+    RootedValue value(cx);
+    if (!obj->getGeneric(cx, onBehalfOf, id, &value))
+        return false;
+
+    *vp = value;
+    return true;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj_, jsid id_, jsval def_, jsval *vp)
 {
     Rooted<JSObject*> obj(cx, obj_);
     Rooted<jsid> id(cx, id_);
-    return baseops::GetPropertyDefault(cx, obj, id, def, vp);
+    RootedValue def(cx, def_);
+
+    RootedValue value(cx);
+    if (!baseops::GetPropertyDefault(cx, obj, id, def, &value))
+        return false;
+
+    *vp = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
 {
     return JS_ForwardGetElementTo(cx, obj, index, obj, vp);
 }
 
@@ -4176,31 +4197,41 @@ JS_PUBLIC_API(JSBool)
 JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp)
 {
     RootedObject onBehalfOf(cx, onBehalfOf_);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
-    return obj->getElement(cx, onBehalfOf, index, vp);
+
+    RootedValue value(cx);
+    if (!obj->getElement(cx, onBehalfOf, index, &value))
+        return false;
+
+    *vp = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp, JSBool* present)
 {
     RootedObject onBehalfOf(cx, onBehalfOf_);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+    RootedValue value(cx);
     bool isPresent;
-    if (!obj->getElementIfPresent(cx, onBehalfOf, index, vp, &isPresent))
+    if (!obj->getElementIfPresent(cx, onBehalfOf, index, &value, &isPresent))
         return false;
+
+    *vp = value;
     *present = isPresent;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
 {
     RootedObject obj(cx, obj_);
@@ -4228,18 +4259,22 @@ JS_PUBLIC_API(JSBool)
 JS_GetMethodById(JSContext *cx, JSObject *obj_, jsid id_, JSObject **objp, jsval *vp)
 {
     RootedObject obj(cx, obj_);
     RootedId id(cx, id_);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    if (!GetMethod(cx, obj, id, 0, vp))
+
+    RootedValue value(cx);
+    if (!GetMethod(cx, obj, id, 0, &value))
         return JS_FALSE;
+    *vp = value;
+
     if (objp)
         *objp = obj;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
 {
@@ -4252,29 +4287,41 @@ JS_SetPropertyById(JSContext *cx, JSObje
 {
     RootedId id(cx, id_);
     Rooted<JSObject*> obj(cx, objArg);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
-    return obj->setGeneric(cx, obj, id, vp, false);
+
+    RootedValue value(cx, *vp);
+    if (!obj->setGeneric(cx, obj, id, &value, false))
+        return false;
+
+    *vp = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval *vp)
 {
     RootedObject obj(cx, obj_);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, *vp);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
-    return obj->setElement(cx, obj, index, vp, false);
+
+    RootedValue value(cx, *vp);
+    if (!obj->setElement(cx, obj, index, &value, false))
+        return false;
+
+    *vp = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
 {
     RootedObject obj(cx, obj_);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
@@ -4291,64 +4338,87 @@ JS_SetUCProperty(JSContext *cx, JSObject
 JS_PUBLIC_API(JSBool)
 JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
+    RootedValue value(cx);
+
     if (JSID_IS_SPECIAL(id)) {
         Rooted<SpecialId> sid(cx, JSID_TO_SPECIALID(id));
-        return obj->deleteSpecial(cx, sid, rval, false);
+        if (!obj->deleteSpecial(cx, sid, &value, false))
+            return false;
+    } else {
+        if (!obj->deleteByValue(cx, IdToValue(id), &value, false))
+            return false;
     }
 
-    return obj->deleteByValue(cx, IdToValue(id), rval, false);
+    *rval = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
-    return obj->deleteElement(cx, index, rval, false);
+
+    RootedValue value(cx);
+    if (!obj->deleteElement(cx, index, &value, false))
+        return false;
+
+    *rval = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeleteProperty2(JSContext *cx, JSObject *obj_, const char *name, jsval *rval)
 {
     RootedObject obj(cx, obj_);
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
-    return obj->deleteByValue(cx, StringValue(atom), rval, false);
+    RootedValue value(cx);
+    if (!obj->deleteByValue(cx, StringValue(atom), &value, false))
+        return false;
+
+    *rval = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *rval)
 {
     RootedObject obj(cx, obj_);
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return false;
 
-    return obj->deleteByValue(cx, StringValue(atom), rval, false);
+    RootedValue value(cx);
+    if (!obj->deleteByValue(cx, StringValue(atom), &value, false))
+        return false;
+
+    *rval = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
 {
     jsval junk;
     return JS_DeletePropertyById2(cx, obj, id, &junk);
 }
@@ -5323,17 +5393,18 @@ JS::CompileFunction(JSContext *cx, Handl
     if (!fun)
         return NULL;
 
     if (!frontend::CompileFunctionBody(cx, fun, options, &bindings, chars, length))
         return NULL;
 
     if (obj && funAtom) {
         Rooted<jsid> id(cx, AtomToId(funAtom));
-        if (!obj->defineGeneric(cx, id, ObjectValue(*fun), NULL, NULL, JSPROP_ENUMERATE))
+        RootedValue value(cx, ObjectValue(*fun));
+        if (!obj->defineGeneric(cx, id, value, NULL, NULL, JSPROP_ENUMERATE))
             return NULL;
     }
 
     return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
@@ -5680,21 +5751,21 @@ JS_CallFunctionName(JSContext *cx, JSObj
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj_, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     RootedObject obj(cx, obj_);
 
-    Value v;
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
+    RootedValue v(cx);
     Rooted<jsid> id(cx, AtomToId(atom));
     return GetMethod(cx, obj, id, 0, &v) &&
            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
                      jsval *rval)
@@ -6204,26 +6275,36 @@ JS_Stringify(JSContext *cx, jsval *vp, J
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    return ParseJSONWithReviver(cx, chars, len, NullValue(), vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval reviver, jsval *vp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-
-    return ParseJSONWithReviver(cx, chars, len, reviver, vp);
+    RootedValue reviver(cx, NullValue()), value(cx);
+    if (!ParseJSONWithReviver(cx, chars, len, reviver, &value))
+        return false;
+
+    *vp = value;
+    return true;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval reviverArg, jsval *vp)
+{
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+
+    RootedValue reviver(cx, reviverArg), value(cx);
+    if (!ParseJSONWithReviver(cx, chars, len, reviver, &value))
+        return false;
+
+    *vp = value;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ReadStructuredClone(JSContext *cx, const uint64_t *buf, size_t nbytes,
                        uint32_t version, jsval *vp,
                        const JSStructuredCloneCallbacks *optionalCallbacks,
                        void *closure)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -856,16 +856,19 @@ class ValueOperations
     bool isString() const { return value()->isString(); }
     bool isObject() const { return value()->isObject(); }
     bool isMagic() const { return value()->isMagic(); }
     bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
     bool isMarkable() const { return value()->isMarkable(); }
     bool isPrimitive() const { return value()->isPrimitive(); }
     bool isGCThing() const { return value()->isGCThing(); }
 
+    bool isNullOrUndefined() const { return value()->isNullOrUndefined(); }
+    bool isObjectOrNull() const { return value()->isObjectOrNull(); }
+
     bool toBoolean() const { return value()->toBoolean(); }
     double toNumber() const { return value()->toNumber(); }
     int32_t toInt32() const { return value()->toInt32(); }
     double toDouble() const { return value()->toDouble(); }
     JSString *toString() const { return value()->toString(); }
     JSObject &toObject() const { return value()->toObject(); }
     JSObject *toObjectOrNull() const { return value()->toObjectOrNull(); }
     void *toGCThing() const { return value()->toGCThing(); }
@@ -893,17 +896,17 @@ class MutableValueOperations : public Va
     void setDouble(double d) { value()->setDouble(d); }
     void setString(JSString *str) { value()->setString(str); }
     void setString(const JS::Anchor<JSString *> &str) { value()->setString(str); }
     void setObject(JSObject &obj) { value()->setObject(obj); }
     void setBoolean(bool b) { value()->setBoolean(b); }
     void setMagic(JSWhyMagic why) { value()->setMagic(why); }
     bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
     bool setNumber(double d) { return value()->setNumber(d); }
-    void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(); }
+    void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(arg); }
 };
 
 /*
  * Augment the generic Handle<T> interface when T = Value with type-querying
  * and value-extracting operations.
  */
 template <>
 class HandleBase<Value> : public ValueOperations<Handle<Value> >
@@ -939,17 +942,17 @@ class MutableHandleBase<Value> : public 
 template <>
 class RootedBase<Value> : public MutableValueOperations<Rooted<Value> >
 {
     friend class ValueOperations<Rooted<Value> >;
     const Value * extract() const {
         return static_cast<const Rooted<Value>*>(this)->address();
     }
 
-    friend class MutableValueOperations<Handle<Value> >;
+    friend class MutableValueOperations<Rooted<Value> >;
     Value * extractMutable() {
         return static_cast<Rooted<Value>*>(this)->address();
     }
 };
 
 /************************************************************************/
 
 #ifndef __GNUC__
@@ -1370,19 +1373,19 @@ class CallReceiver
   public:
     friend CallReceiver CallReceiverFromVp(Value *);
     friend CallReceiver CallReceiverFromArgv(Value *);
     Value *base() const { return argv_ - 2; }
     JSObject &callee() const { JS_ASSERT(!usedRval_); return argv_[-2].toObject(); }
     Value &calleev() const { JS_ASSERT(!usedRval_); return argv_[-2]; }
     Value &thisv() const { return argv_[-1]; }
 
-    Value &rval() const {
+    JS::MutableHandleValue rval() const {
         setUsedRval();
-        return argv_[-2];
+        return JS::MutableHandleValue::fromMarkedLocation(&argv_[-2]);
     }
 
     Value *spAfterCall() const {
         setUsedRval();
         return argv_ - 1;
     }
 
     void setCallee(Value calleev) {
@@ -1608,18 +1611,18 @@ typedef JS::MutableHandle<JS::Value> JSM
 /*
  * Handle support for C API users. Handles must be destroyed in the reverse
  * order that they were created (as in a stack).
  */
 
 typedef struct { JSObject **_; } JSHandleObject;
 typedef struct { JSString **_; } JSHandleString;
 typedef struct { JSObject **_; } JSMutableHandleObject;
+typedef struct { jsval *_; } JSMutableHandleValue;
 typedef struct { jsid *_; } JSHandleId;
-typedef struct { jsval *_; } JSMutableHandleValue;
 
 JSBool JS_CreateHandleObject(JSContext *cx, JSObject *obj, JSHandleObject *phandle);
 void JS_DestroyHandleObject(JSContext *cx, JSHandleObject handle);
 
 JSBool JS_CreateMutableHandleObject(JSContext *cx, JSObject *obj, JSMutableHandleObject *phandle);
 void JS_DestroyMutableHandleObject(JSContext *cx, JSMutableHandleObject handle);
 
 JSBool JS_CreateHandleId(JSContext *cx, jsid id, JSHandleId *phandle);
@@ -1632,27 +1635,27 @@ void JS_DestroyHandleId(JSContext *cx, J
 /*
  * Add, delete, or get a property named by id in obj.  Note the jsid id
  * type -- id may be a string (Unicode property identifier) or an int (element
  * index).  The *vp out parameter, on success, is the new property value after
  * an add or get.  After a successful delete, *vp is JSVAL_FALSE iff
  * obj[id] can't be deleted (because it's permanent).
  */
 typedef JSBool
-(* JSPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
+(* JSPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
 
 /*
  * Set a property named by id in obj, treating the assignment as strict
  * mode code if strict is true. Note the jsid id type -- id may be a string
  * (Unicode property identifier) or an int (element index). The *vp out
  * parameter, on success, is the new property value after the
  * set.
  */
 typedef JSBool
-(* JSStrictPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
+(* JSStrictPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
 
 /*
  * This function type is used for callbacks that enumerate the properties of
  * a JSObject.  The behavior depends on the value of enum_op:
  *
  *  JSENUMERATE_INIT
  *    A new, opaque iterator state should be allocated and stored in *statep.
  *    (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
@@ -1725,17 +1728,17 @@ typedef JSBool
 (* JSNewResolveOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                    JSMutableHandleObject objp);
 
 /*
  * Convert obj to the given type, returning true with the resulting value in
  * *vp on success, and returning false on error or exception.
  */
 typedef JSBool
-(* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
+(* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
 /*
  * Delegate typeof to an object so it can cloak a primitive or another object.
  */
 typedef JSType
 (* JSTypeOfOp)(JSContext *cx, JSObject *obj);
 
 typedef struct JSFreeOp JSFreeOp;
@@ -4189,29 +4192,29 @@ JS_IdToValue(JSContext *cx, jsid id, jsv
  * the specified object, computing a primitive default value for the object.
  * The hint must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no hint).  On
  * success the resulting value is stored in *vp.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
-
-extern JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_EnumerateStub(JSContext *cx, JSHandleObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
 struct JSConstDoubleSpec {
     double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -128,21 +128,21 @@ js_GetLengthProperty(JSContext *cx, JSOb
         ArgumentsObject &argsobj = obj->asArguments();
         if (!argsobj.hasOverriddenLength()) {
             *lengthp = argsobj.initialLength();
             return true;
         }
     }
 
     RootedValue value(cx);
-    if (!obj->getProperty(cx, cx->runtime->atomState.lengthAtom, value.address()))
+    if (!obj->getProperty(cx, cx->runtime->atomState.lengthAtom, &value))
         return false;
 
-    if (value.get().isInt32()) {
-        *lengthp = uint32_t(value.get().toInt32()); /* uint32_t cast does ToUint32_t */
+    if (value.isInt32()) {
+        *lengthp = uint32_t(value.toInt32()); /* uint32_t cast does ToUint32_t */
         return true;
     }
 
     return ToUint32(cx, value, (uint32_t *)lengthp);
 }
 
 namespace js {
 
@@ -269,50 +269,49 @@ DoubleIndexToId(JSContext *cx, double in
 
 /*
  * If the property at the given index exists, get its value into location
  * pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
  * to JSVAL_VOID. This function assumes that the location pointed by vp is
  * properly rooted and can be used as GC-protected storage for temporaries.
  */
 static inline bool
-DoGetElement(JSContext *cx, JSObject *obj_, double index, JSBool *hole, Value *vp)
+DoGetElement(JSContext *cx, HandleObject obj, double index, JSBool *hole, MutableHandleValue vp)
 {
-    RootedObject obj(cx, obj_);
     RootedId id(cx);
 
     if (!DoubleIndexToId(cx, index, id.address()))
         return false;
 
     RootedObject obj2(cx);
     RootedShape prop(cx);
     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
         return false;
 
     if (!prop) {
-        vp->setUndefined();
+        vp.setUndefined();
         *hole = true;
     } else {
         if (!obj->getGeneric(cx, id, vp))
             return false;
         *hole = false;
     }
     return true;
 }
 
 static inline bool
-DoGetElement(JSContext *cx, HandleObject obj, uint32_t index, JSBool *hole, Value *vp)
+DoGetElement(JSContext *cx, HandleObject obj, uint32_t index, JSBool *hole, MutableHandleValue vp)
 {
     bool present;
     if (!obj->getElementIfPresent(cx, obj, index, vp, &present))
         return false;
 
     *hole = !present;
     if (*hole)
-        vp->setUndefined();
+        vp.setUndefined();
 
     return true;
 }
 
 template<typename IndexType>
 static void
 AssertGreaterThanZero(IndexType index)
 {
@@ -323,23 +322,25 @@ AssertGreaterThanZero(IndexType index)
 template<>
 void
 AssertGreaterThanZero(uint32_t index)
 {
 }
 
 template<typename IndexType>
 static JSBool
-GetElement(JSContext *cx, JSObject *obj, IndexType index, JSBool *hole, Value *vp)
+GetElement(JSContext *cx, HandleObject obj, IndexType index, JSBool *hole, MutableHandleValue vp)
 {
     AssertGreaterThanZero(index);
-    if (obj->isDenseArray() && index < obj->getDenseArrayInitializedLength() &&
-        !(*vp = obj->getDenseArrayElement(uint32_t(index))).isMagic(JS_ARRAY_HOLE)) {
-        *hole = JS_FALSE;
-        return JS_TRUE;
+    if (obj->isDenseArray() && index < obj->getDenseArrayInitializedLength()) {
+        vp.set(obj->getDenseArrayElement(uint32_t(index)));
+        if (!vp.isMagic(JS_ARRAY_HOLE)) {
+            *hole = JS_FALSE;
+            return JS_TRUE;
+        }
     }
     if (obj->isArguments()) {
         if (obj->asArguments().maybeGetElement(uint32_t(index), vp)) {
             *hole = JS_FALSE;
             return true;
         }
     }
 
@@ -347,17 +348,17 @@ GetElement(JSContext *cx, JSObject *obj,
 }
 
 namespace js {
 
 static bool
 GetElementsSlow(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
 {
     for (uint32_t i = 0; i < length; i++) {
-        if (!aobj->getElement(cx, i, &vp[i]))
+        if (!aobj->getElement(cx, i, MutableHandleValue::fromMarkedLocation(&vp[i])))
             return false;
     }
 
     return true;
 }
 
 bool
 GetElements(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
@@ -385,17 +386,17 @@ GetElements(JSContext *cx, HandleObject 
 }
 
 }
 
 /*
  * Set the value of the property at the given index to v assuming v is rooted.
  */
 static JSBool
-SetArrayElement(JSContext *cx, HandleObject obj, double index, const Value &v)
+SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
 {
     JS_ASSERT(index >= 0);
 
     if (obj->isDenseArray()) {
         /* Predicted/prefetched code should favor the remains-dense case. */
         JSObject::EnsureDenseResult result = JSObject::ED_SPARSE;
         do {
             if (index > uint32_t(-1))
@@ -417,17 +418,17 @@ SetArrayElement(JSContext *cx, HandleObj
             return JS_FALSE;
     }
 
     RootedId id(cx);
     if (!DoubleIndexToId(cx, index, id.address()))
         return false;
 
     RootedValue tmp(cx, v);
-    return obj->setGeneric(cx, obj, id, tmp.address(), true);
+    return obj->setGeneric(cx, obj, id, &tmp, true);
 }
 
 /*
  * Delete the element |index| from |obj|. If |strict|, do a strict
  * deletion: throw if the property is not configurable.
  *
  * - Return 1 if the deletion succeeds (that is, ES5's [[Delete]] would
  *   return true)
@@ -452,17 +453,17 @@ DeleteArrayElement(JSContext *cx, Handle
                 obj->setDenseArrayElement(idx, MagicValue(JS_ARRAY_HOLE));
                 if (!js_SuppressDeletedElement(cx, obj, idx))
                     return -1;
             }
         }
         return 1;
     }
 
-    Value v;
+    RootedValue v(cx);
     if (index <= UINT32_MAX) {
         if (!obj->deleteElement(cx, uint32_t(index), &v, strict))
             return -1;
     } else {
         if (!obj->deleteByValue(cx, DoubleValue(index), &v, strict))
             return -1;
     }
 
@@ -470,80 +471,80 @@ DeleteArrayElement(JSContext *cx, Handle
 }
 
 /*
  * When hole is true, delete the property at the given index. Otherwise set
  * its value to v assuming v is rooted.
  */
 static JSBool
 SetOrDeleteArrayElement(JSContext *cx, HandleObject obj, double index,
-                        JSBool hole, const Value &v)
+                        JSBool hole, HandleValue v)
 {
     if (hole) {
         JS_ASSERT(v.isUndefined());
         return DeleteArrayElement(cx, obj, index, true) >= 0;
     }
     return SetArrayElement(cx, obj, index, v);
 }
 
 JSBool
 js_SetLengthProperty(JSContext *cx, HandleObject obj, double length)
 {
-    Value v = NumberValue(length);
+    RootedValue v(cx, NumberValue(length));
 
     /* We don't support read-only array length yet. */
     return obj->setProperty(cx, obj, cx->runtime->atomState.lengthAtom, &v, false);
 }
 
 /*
  * Since SpiderMonkey supports cross-class prototype-based delegation, we have
  * to be careful about the length getter and setter being called on an object
  * not of Array class. For the getter, we search obj's prototype chain for the
  * array that caused this getter to be invoked. In the setter case to overcome
  * the JSPROP_SHARED attribute, we must define a shadowing length property.
  */
 static JSBool
-array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, Value *vp)
+array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
 {
     JSObject *obj = obj_;
     do {
         if (obj->isArray()) {
-            vp->setNumber(obj->getArrayLength());
+            vp.setNumber(obj->getArrayLength());
             return JS_TRUE;
         }
     } while ((obj = obj->getProto()) != NULL);
     return JS_TRUE;
 }
 
 static JSBool
-array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp)
+array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
 {
     if (!obj->isArray()) {
-        return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, *vp,
+        return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, vp,
                                    NULL, NULL, JSPROP_ENUMERATE);
     }
 
     uint32_t newlen;
-    if (!ToUint32(cx, *vp, &newlen))
+    if (!ToUint32(cx, vp, &newlen))
         return false;
 
     double d;
-    if (!ToNumber(cx, *vp, &d))
+    if (!ToNumber(cx, vp, &d))
         return false;
 
     if (d != newlen) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
         return false;
     }
 
     uint32_t oldlen = obj->getArrayLength();
     if (oldlen == newlen)
         return true;
 
-    vp->setNumber(newlen);
+    vp.setNumber(newlen);
     if (oldlen < newlen) {
         obj->setArrayLength(cx, newlen);
         return true;
     }
 
     if (obj->isDenseArray()) {
         /*
          * Don't reallocate if we're not actually shrinking our slots. If we do
@@ -585,17 +586,17 @@ array_length_setter(JSContext *cx, Handl
         uint32_t gap = oldlen - newlen;
         for (;;) {
             jsid nid;
             if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &nid))
                 return false;
             if (JSID_IS_VOID(nid))
                 break;
             uint32_t index;
-            Value junk;
+            RootedValue junk(cx);
             if (js_IdIsIndex(nid, &index) && index - newlen < gap &&
                 !obj->deleteElement(cx, index, &junk, false)) {
                 return false;
             }
         }
     }
 
     obj->setArrayLength(cx, newlen);
@@ -696,79 +697,83 @@ js_GetDenseArrayElementValue(JSContext *
         vp->setNumber(obj->getArrayLength());
         return JS_TRUE;
     }
     *vp = obj->getDenseArrayElement(i);
     return JS_TRUE;
 }
 
 static JSBool
-array_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp)
+array_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
+                  MutableHandleValue vp)
 {
     if (name == cx->runtime->atomState.lengthAtom) {
-        vp->setNumber(obj->getArrayLength());
+        vp.setNumber(obj->getArrayLength());
         return true;
     }
 
     if (!obj->isDenseArray()) {
         Rooted<jsid> id(cx, NameToId(name));
         return baseops::GetProperty(cx, obj, receiver, id, vp);
     }
 
     JSObject *proto = obj->getProto();
     if (!proto) {
-        vp->setUndefined();
+        vp.setUndefined();
         return true;
     }
 
     return proto->getProperty(cx, receiver, name, vp);
 }
 
 static JSBool
-array_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
+array_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
+                 MutableHandleValue vp)
 {
     if (!obj->isDenseArray())
         return baseops::GetElement(cx, obj, receiver, index, vp);
 
     if (index < obj->getDenseArrayInitializedLength()) {
-        *vp = obj->getDenseArrayElement(index);
-        if (!vp->isMagic(JS_ARRAY_HOLE)) {
+        vp.set(obj->getDenseArrayElement(index));
+        if (!vp.isMagic(JS_ARRAY_HOLE)) {
             /* Type information for dense array elements must be correct. */
             JS_ASSERT_IF(!obj->hasSingletonType(),
-                         js::types::TypeHasProperty(cx, obj->type(), JSID_VOID, *vp));
+                         js::types::TypeHasProperty(cx, obj->type(), JSID_VOID, vp));
 
             return true;
         }
     }
 
     JSObject *proto = obj->getProto();
     if (!proto) {
-        vp->setUndefined();
+        vp.setUndefined();
         return true;
     }
 
     return proto->getElement(cx, receiver, index, vp);
 }
 
 static JSBool
-array_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp)
+array_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
+                 MutableHandleValue vp)
 {
     if (obj->isDenseArray() && !obj->getProto()) {
-        vp->setUndefined();
+        vp.setUndefined();
         return true;
     }
 
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return baseops::GetProperty(cx, obj, receiver, id, vp);
 }
 
 static JSBool
-array_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
+array_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
+                 MutableHandleValue vp)
 {
-    Value idval = IdToValue(id);
+    RootedValue idval(cx, IdToValue(id));
 
     uint32_t index;
     if (IsDefinitelyIndex(idval, &index))
         return array_getElement(cx, obj, receiver, index, vp);
 
     Rooted<SpecialId> sid(cx);
     if (ValueIsSpecial(obj, &idval, sid.address(), cx))
         return array_getSpecial(cx, obj, receiver, sid, vp);
@@ -780,17 +785,18 @@ array_getGeneric(JSContext *cx, HandleOb
     if (atom->isIndex(&index))
         return array_getElement(cx, obj, receiver, index, vp);
 
     Rooted<PropertyName*> name(cx, atom->asPropertyName());
     return array_getProperty(cx, obj, receiver, name, vp);
 }
 
 static JSBool
-slowarray_addProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
+slowarray_addProperty(JSContext *cx, HandleObject obj, HandleId id,
+                      MutableHandleValue vp)
 {
     uint32_t index, length;
 
     if (!js_IdIsIndex(id, &index))
         return JS_TRUE;
     length = obj->getArrayLength();
     if (index >= length)
         obj->setArrayLength(cx, index + 1);
@@ -799,17 +805,18 @@ slowarray_addProperty(JSContext *cx, Han
 
 static JSType
 array_typeOf(JSContext *cx, HandleObject obj)
 {
     return JSTYPE_OBJECT;
 }
 
 static JSBool
-array_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict)
+array_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
+                 MutableHandleValue vp, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return array_length_setter(cx, obj, id, strict, vp);
 
     if (!obj->isDenseArray())
         return baseops::SetPropertyHelper(cx, obj, obj, id, 0, vp, strict);
 
     do {
@@ -824,34 +831,36 @@ array_setGeneric(JSContext *cx, HandleOb
             if (result == JSObject::ED_FAILED)
                 return false;
             JS_ASSERT(result == JSObject::ED_SPARSE);
             break;
         }
 
         if (i >= obj->getArrayLength())
             obj->setDenseArrayLength(i + 1);
-        obj->setDenseArrayElementWithType(cx, i, *vp);
+        obj->setDenseArrayElementWithType(cx, i, vp);
         return true;
     } while (false);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
     return baseops::SetPropertyHelper(cx, obj, obj, id, 0, vp, strict);
 }
 
 static JSBool
-array_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict)
+array_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
+                  MutableHandleValue vp, JSBool strict)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return array_setGeneric(cx, obj, id, vp, strict);
 }
 
 static JSBool
-array_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict)
+array_setElement(JSContext *cx, HandleObject obj, uint32_t index,
+                 MutableHandleValue vp, JSBool strict)
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, id.address()))
         return false;
 
     if (!obj->isDenseArray())
         return baseops::SetPropertyHelper(cx, obj, obj, id, 0, vp, strict);
 
@@ -870,27 +879,28 @@ array_setElement(JSContext *cx, HandleOb
             if (result == JSObject::ED_FAILED)
                 return false;
             JS_ASSERT(result == JSObject::ED_SPARSE);
             break;
         }
 
         if (index >= obj->getArrayLength())
             obj->setDenseArrayLength(index + 1);
-        obj->setDenseArrayElementWithType(cx, index, *vp);
+        obj->setDenseArrayElementWithType(cx, index, vp);
         return true;
     } while (false);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
     return baseops::SetPropertyHelper(cx, obj, obj, id, 0, vp, strict);
 }
 
 static JSBool
-array_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict)
+array_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
+                 MutableHandleValue vp, JSBool strict)
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return array_setGeneric(cx, obj, id, vp, strict);
 }
 
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
@@ -909,17 +919,17 @@ js_PrototypeHasIndexedProperties(JSConte
             return JS_TRUE;
         if (obj->isIndexed())
             return JS_TRUE;
     }
     return JS_FALSE;
 }
 
 static JSBool
-array_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
+array_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                     JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return JS_TRUE;
 
     if (!obj->isDenseArray())
         return baseops::DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 
@@ -934,40 +944,40 @@ array_defineGeneric(JSContext *cx, Handl
             if (result == JSObject::ED_FAILED)
                 return false;
             JS_ASSERT(result == JSObject::ED_SPARSE);
             break;
         }
 
         if (i >= obj->getArrayLength())
             obj->setDenseArrayLength(i + 1);
-        obj->setDenseArrayElementWithType(cx, i, *value);
+        obj->setDenseArrayElementWithType(cx, i, value);
         return true;
     } while (false);
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
     return baseops::DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
-array_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
+array_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
                      JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return array_defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 namespace js {
 
 /* non-static for direct definition of array elements within the engine */
 JSBool
-array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
+array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     if (!obj->isDenseArray())
         return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
 
     do {
         /*
          * UINT32_MAX is not an array index and must not affect the length
@@ -981,31 +991,31 @@ array_defineElement(JSContext *cx, Handl
             if (result == JSObject::ED_FAILED)
                 return false;
             JS_ASSERT(result == JSObject::ED_SPARSE);
             break;
         }
 
         if (index >= obj->getArrayLength())
             obj->setDenseArrayLength(index + 1);
-        obj->setDenseArrayElementWithType(cx, index, *value);
+        obj->setDenseArrayElementWithType(cx, index, value);
         return true;
     } while (false);
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
     return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
 }
 
 } // namespace js
 
 static JSBool
-array_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
+array_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return array_defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
 array_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
@@ -1062,60 +1072,63 @@ array_setElementAttributes(JSContext *cx
 static JSBool
 array_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
-array_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict)
+array_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
+                     MutableHandleValue rval, JSBool strict)
 {
     if (!obj->isDenseArray())
         return baseops::DeleteProperty(cx, obj, name, rval, strict);
 
     if (name == cx->runtime->atomState.lengthAtom) {
-        rval->setBoolean(false);
+        rval.setBoolean(false);
         return true;
     }
 
-    rval->setBoolean(true);
+    rval.setBoolean(true);
     return true;
 }
 
 namespace js {
 
 /* non-static for direct deletion of array elements within the engine */
 JSBool
-array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict)
+array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
+                    MutableHandleValue rval, JSBool strict)
 {
     if (!obj->isDenseArray())
         return baseops::DeleteElement(cx, obj, index, rval, strict);
 
     if (index < obj->getDenseArrayInitializedLength()) {
         obj->markDenseArrayNotPacked(cx);
         obj->setDenseArrayElement(index, MagicValue(JS_ARRAY_HOLE));
     }
 
     if (!js_SuppressDeletedElement(cx, obj, index))
         return false;
 
-    rval->setBoolean(true);
+    rval.setBoolean(true);
     return true;
 }
 
 } // namespace js
 
 static JSBool
-array_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict)
+array_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
+                    MutableHandleValue rval, JSBool strict)
 {
     if (!obj->isDenseArray())
         return baseops::DeleteSpecial(cx, obj, sid, rval, strict);
 
-    rval->setBoolean(true);
+    rval.setBoolean(true);
     return true;
 }
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
@@ -1391,16 +1404,17 @@ IsArray(const Value &v)
 }
 
 static bool
 array_toSource_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArray(args.thisv()));
 
     Rooted<JSObject*> obj(cx, &args.thisv().toObject());
+    RootedValue elt(cx);
 
     ArraySharpDetector detector(cx);
     if (!detector.init(obj))
         return false;
 
     StringBuffer sb(cx);
 
     if (detector.initiallySharp()) {
@@ -1413,17 +1427,16 @@ array_toSource_impl(JSContext *cx, CallA
         return false;
 
     uint32_t length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return false;
 
     for (uint32_t index = 0; index < length; index++) {
         JSBool hole;
-        Value elt;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, index, &hole, &elt)) {
             return false;
         }
 
         /* Get element's character string. */
         JSString *str;
         if (hole) {
@@ -1560,42 +1573,42 @@ array_toString_sub(JSContext *cx, Handle
                 break;
 
             if (!elem->isMagic(JS_ARRAY_HOLE) && !elem->isNullOrUndefined()) {
                 if (!ValueToStringBuffer(cx, *elem, sb))
                     return false;
             }
         }
 
+        RootedValue v(cx);
         for (uint32_t i = uint32_t(PointerRangeSize(start, elem)); i < length; i++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx))
                 return false;
 
             JSBool hole;
-            Value v;
             if (!GetElement(cx, obj, i, &hole, &v))
                 return false;
             if (!hole && !v.isNullOrUndefined()) {
                 if (!ValueToStringBuffer(cx, v, sb))
                     return false;
             }
         }
     } else {
+        RootedValue elt(cx);
         for (uint32_t index = 0; index < length; index++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx))
                 return false;
 
             JSBool hole;
-            Value elt;
             if (!GetElement(cx, obj, index, &hole, &elt))
                 return false;
 
             if (!hole && !elt.isNullOrUndefined()) {
                 if (locale) {
-                    JSObject *robj = ToObject(cx, &elt);
+                    JSObject *robj = ToObject(cx, elt.address());
                     if (!robj)
                         return false;
                     RootedId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom));
                     if (!robj->callMethod(cx, id, 0, NULL, &elt))
                         return false;
                 }
                 if (!ValueToStringBuffer(cx, elt, sb))
                     return false;
@@ -1622,17 +1635,17 @@ array_toString(JSContext *cx, unsigned a
 {
     JS_CHECK_RECURSION(cx, return false);
 
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, ToObject(cx, &args.thisv()));
     if (!obj)
         return false;
 
-    Value join = args.calleev();
+    RootedValue join(cx, args.calleev());
     if (!obj->getProperty(cx, cx->runtime->atomState.joinAtom, &join))
         return false;
 
     if (!js_IsCallable(join)) {
         JSString *str = obj_toStringHelper(cx, obj);
         if (!str)
             return false;
         args.rval().setString(str);
@@ -1644,17 +1657,17 @@ array_toString(JSContext *cx, unsigned a
         return false;
 
     ag.calleev() = join;
     ag.thisv().setObject(*obj);
 
     /* Do the call. */
     if (!Invoke(cx, ag))
         return false;
-    args.rval() = ag.rval();
+    args.rval().set(ag.rval());
     return true;
 }
 
 static JSBool
 array_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
@@ -1692,16 +1705,17 @@ InitArrayTypes(JSContext *cx, TypeObject
 }
 
 enum ShouldUpdateTypes
 {
     UpdateTypes = true,
     DontUpdateTypes = false
 };
 
+/* vector must point to rooted memory. */
 static bool
 InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t count, const Value *vector, ShouldUpdateTypes updateTypes)
 {
     JS_ASSERT(count <= MAX_ARRAY_INDEX);
 
     if (count == 0)
         return true;
 
@@ -1733,17 +1747,17 @@ InitArrayElements(JSContext *cx, HandleO
         obj->copyDenseArrayElements(start, vector, count);
         JS_ASSERT_IF(count != 0, !obj->getDenseArrayElement(newlen - 1).isMagic(JS_ARRAY_HOLE));
         return true;
     } while (false);
 
     const Value* end = vector + count;
     while (vector < end && start <= MAX_ARRAY_INDEX) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-            !SetArrayElement(cx, obj, start++, *vector++)) {
+            !SetArrayElement(cx, obj, start++, HandleValue::fromMarkedLocation(vector++))) {
             return false;
         }
     }
 
     if (vector == end)
         return true;
 
     /* Finish out any remaining elements past the max array index. */
@@ -1752,17 +1766,17 @@ InitArrayElements(JSContext *cx, HandleO
 
     JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
     RootedValue value(cx);
     RootedId id(cx);
     Value idval = DoubleValue(MAX_ARRAY_INDEX + 1);
     do {
         value = *vector++;
         if (!ValueToId(cx, idval, id.address()) ||
-            !obj->setGeneric(cx, obj, id, value.address(), true)) {
+            !obj->setGeneric(cx, obj, id, &value, true)) {
             return false;
         }
         idval.getDoubleRef() += 1;
     } while (vector != end);
 
     return true;
 }
 
@@ -1854,17 +1868,17 @@ array_reverse(JSContext *cx, unsigned ar
          * Per ECMA-262, don't update the length of the array, even if the new
          * array has trailing holes (and thus the original array began with
          * holes).
          */
         args.rval().setObject(*obj);
         return true;
     } while (false);
 
-    Value lowval, hival;
+    RootedValue lowval(cx), hival(cx);
     for (uint32_t i = 0, half = len / 2; i < half; i++) {
         JSBool hole, hole2;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, i, &hole, &lowval) ||
             !GetElement(cx, obj, len - i - 1, &hole2, &hival) ||
             !SetOrDeleteArrayElement(cx, obj, len - i - 1, hole, lowval) ||
             !SetOrDeleteArrayElement(cx, obj, i, hole2, hival)) {
             return false;
@@ -2150,23 +2164,23 @@ js::array_sort(JSContext *cx, unsigned a
          * value undefined and that is always greater than any other property.
          * Thus to sort holes and undefs we simply count them, sort the rest
          * of elements, append undefs after them and then make holes after
          * undefs.
          */
         undefs = 0;
         bool allStrings = true;
         bool allInts = true;
+        RootedValue v(cx);
         for (uint32_t i = 0; i < len; i++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx))
                 return false;
 
             /* Clear vec[newlen] before including it in the rooted set. */
             JSBool hole;
-            Value v;
             if (!GetElement(cx, obj, i, &hole, &v))
                 return false;
             if (hole)
                 continue;
             if (v.isUndefined()) {
                 ++undefs;
                 continue;
             }
@@ -2248,17 +2262,18 @@ js::array_sort(JSContext *cx, unsigned a
 
         if (!InitArrayElements(cx, obj, 0, uint32_t(n), result, DontUpdateTypes))
             return false;
     }
 
     /* Set undefs that sorted after the rest of elements. */
     while (undefs != 0) {
         --undefs;
-        if (!JS_CHECK_OPERATION_LIMIT(cx) || !SetArrayElement(cx, obj, n++, UndefinedValue()))
+        RootedValue undefinedValue(cx);
+        if (!JS_CHECK_OPERATION_LIMIT(cx) || !SetArrayElement(cx, obj, n++, undefinedValue))
             return false;
     }
 
     /* Re-create any holes that sorted to the end of the array. */
     while (len > n) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) || DeleteArrayElement(cx, obj, --len, true) < 0)
             return false;
     }
@@ -2311,18 +2326,19 @@ JS_ALWAYS_INLINE JSBool
 NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
 {
     JS_ASSERT(!v.isMagic());
 
     uint32_t length = obj->getArrayLength();
     if (obj->isSlowArray()) {
         /* This can happen in one evil case. See bug 630377. */
         RootedId id(cx);
+        RootedValue nv(cx, v);
         return IndexToId(cx, length, id.address()) &&
-               baseops::DefineGeneric(cx, obj, id, &v, NULL, NULL, JSPROP_ENUMERATE);
+               baseops::DefineGeneric(cx, obj, id, nv, NULL, NULL, JSPROP_ENUMERATE);
     }
 
     JS_ASSERT(obj->isDenseArray());
     JS_ASSERT(length <= obj->getDenseArrayCapacity());
 
     if (!obj->ensureElements(cx, length + 1))
         return false;
 
@@ -2364,46 +2380,46 @@ array_pop_slowly(JSContext *cx, HandleOb
         args.rval().setUndefined();
         return js_SetLengthProperty(cx, obj, index);
     }
 
     index--;
 
     JSBool hole;
     RootedValue elt(cx);
-    if (!GetElement(cx, obj, index, &hole, elt.address()))
+    if (!GetElement(cx, obj, index, &hole, &elt))
         return false;
 
     if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
         return false;
 
-    args.rval() = elt;
+    args.rval().set(elt);
     return js_SetLengthProperty(cx, obj, index);
 }
 
 static JSBool
 array_pop_dense(JSContext *cx, HandleObject obj, CallArgs &args)
 {
     uint32_t index = obj->getArrayLength();
     if (index == 0) {
         args.rval().setUndefined();
         return true;
     }
 
     index--;
 
     JSBool hole;
     RootedValue elt(cx);
-    if (!GetElement(cx, obj, index, &hole, elt.address()))
+    if (!GetElement(cx, obj, index, &hole, &elt))
         return false;
 
     if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
         return false;
 
-    args.rval() = elt;
+    args.rval().set(elt);
 
     // obj may not be a dense array any more, e.g. if the element was a missing
     // and a getter supplied by the prototype modified the object.
     if (obj->isDenseArray()) {
         if (obj->getDenseArrayInitializedLength() > index)
             obj->setDenseArrayInitializedLength(index);
 
         obj->setArrayLength(cx, index);
@@ -2457,36 +2473,36 @@ js::array_shift(JSContext *cx, unsigned 
     if (length == 0) {
         args.rval().setUndefined();
     } else {
         length--;
 
         if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
             length < obj->getDenseArrayCapacity() &&
             0 < obj->getDenseArrayInitializedLength()) {
-            args.rval() = obj->getDenseArrayElement(0);
+            args.rval().set(obj->getDenseArrayElement(0));
             if (args.rval().isMagic(JS_ARRAY_HOLE))
                 args.rval().setUndefined();
             obj->moveDenseArrayElements(0, 1, obj->getDenseArrayInitializedLength() - 1);
             obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1);
             obj->setArrayLength(cx, length);
             if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length)))
                 return JS_FALSE;
             return JS_TRUE;
         }
 
         JSBool hole;
-        if (!GetElement(cx, obj, 0u, &hole, &args.rval()))
+        if (!GetElement(cx, obj, 0u, &hole, args.rval()))
             return JS_FALSE;
 
         /* Slide down the array above the first element. */
         RootedValue value(cx);
         for (uint32_t i = 0; i < length; i++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-                !GetElement(cx, obj, i + 1, &hole, value.address()) ||
+                !GetElement(cx, obj, i + 1, &hole, &value) ||
                 !SetOrDeleteArrayElement(cx, obj, i, hole, value)) {
                 return JS_FALSE;
             }
         }
 
         /* Delete the only or last element when it exists. */
         if (!hole && DeleteArrayElement(cx, obj, length, true) < 0)
             return JS_FALSE;
@@ -2532,17 +2548,17 @@ array_unshift(JSContext *cx, unsigned ar
             if (!optimized) {
                 double last = length;
                 double upperIndex = last + args.length();
                 RootedValue value(cx);
                 do {
                     --last, --upperIndex;
                     JSBool hole;
                     if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-                        !GetElement(cx, obj, last, &hole, value.address()) ||
+                        !GetElement(cx, obj, last, &hole, &value) ||
                         !SetOrDeleteArrayElement(cx, obj, upperIndex, hole, value)) {
                         return JS_FALSE;
                     }
                 } while (last != 0);
             }
         }
 
         /* Copy from args to the bottom of the array. */
@@ -2667,19 +2683,19 @@ array_splice(JSContext *cx, unsigned arg
             return false;
         TryReuseArrayType(obj, arr);
     } else {
         arr = NewDenseAllocatedArray(cx, actualDeleteCount);
         if (!arr)
             return false;
         TryReuseArrayType(obj, arr);
 
+        RootedValue fromValue(cx);
         for (uint32_t k = 0; k < actualDeleteCount; k++) {
             JSBool hole;
-            Value fromValue;
             if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                 !GetElement(cx, obj, actualStart + k, &hole, &fromValue) ||
                 (!hole && !arr->defineElement(cx, k, fromValue)))
             {
                 return false;
             }
         }
     }
@@ -2714,19 +2730,19 @@ array_splice(JSContext *cx, unsigned arg
             /*
              * This is all very slow if the length is very large. We don't yet
              * have the ability to iterate in sorted order, so we just do the
              * pessimistic thing and let JS_CHECK_OPERATION_LIMIT handle the
              * fallout.
              */
 
             /* Steps 12(a)-(b). */
+            RootedValue fromValue(cx);
             for (uint32_t from = sourceIndex, to = targetIndex; from < len; from++, to++) {
                 JSBool hole;
-                Value fromValue;
                 if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                     !GetElement(cx, obj, from, &hole, &fromValue) ||
                     !SetOrDeleteArrayElement(cx, obj, to, hole, fromValue))
                 {
                     return false;
                 }
             }
 
@@ -2761,38 +2777,38 @@ array_splice(JSContext *cx, unsigned arg
         if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
             obj->moveDenseArrayElements(actualStart + itemCount,
                                         actualStart + actualDeleteCount,
                                         len - (actualStart + actualDeleteCount));
 
             if (cx->typeInferenceEnabled())
                 obj->setDenseArrayInitializedLength(len + itemCount - actualDeleteCount);
         } else {
+            RootedValue fromValue(cx);
             for (double k = len - actualDeleteCount; k > actualStart; k--) {
                 double from = k + actualDeleteCount - 1;
                 double to = k + itemCount - 1;
 
                 JSBool hole;
-                Value fromValue;
                 if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                     !GetElement(cx, obj, from, &hole, &fromValue) ||
                     !SetOrDeleteArrayElement(cx, obj, to, hole, fromValue))
                 {
                     return false;
                 }
             }
         }
     }
 
     /* Step 10. */
     Value *items = args.array() + 2;
 
     /* Steps 14-15. */
     for (uint32_t k = actualStart, i = 0; i < itemCount; i++, k++) {
-        if (!SetArrayElement(cx, obj, k, items[i]))
+        if (!SetArrayElement(cx, obj, k, HandleValue::fromMarkedLocation(&items[i])))
             return false;
     }
 
     /* Step 16. */
     double finalLength = double(len) - actualDeleteCount + itemCount;
     if (!js_SetLengthProperty(cx, obj, finalLength))
         return false;
 
@@ -2870,26 +2886,26 @@ js::array_concat(JSContext *cx, unsigned
         vp->setObject(*nobj);
         length = 0;
     }
 
     /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
     for (unsigned i = 0; i <= argc; i++) {
         if (!JS_CHECK_OPERATION_LIMIT(cx))
             return false;
-        const Value &v = p[i];
+        HandleValue v = HandleValue::fromMarkedLocation(&p[i]);
         if (v.isObject()) {
             RootedObject obj(cx, &v.toObject());
             if (ObjectClassIs(*obj, ESClass_Array, cx)) {
                 uint32_t alength;
                 if (!js_GetLengthProperty(cx, obj, &alength))
                     return false;
+                RootedValue tmp(cx);
                 for (uint32_t slot = 0; slot < alength; slot++) {
                     JSBool hole;
-                    Value tmp;
                     if (!JS_CHECK_OPERATION_LIMIT(cx) || !GetElement(cx, obj, slot, &hole, &tmp))
                         return false;
 
                     /*
                      * Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
                      * properties.
                      */
                     if (!hole && !SetArrayElement(cx, nobj, length + slot, tmp))
@@ -2970,17 +2986,17 @@ array_slice(JSContext *cx, unsigned argc
     nobj = NewDenseAllocatedArray(cx, end - begin);
     if (!nobj)
         return JS_FALSE;
     TryReuseArrayType(obj, nobj);
 
     RootedValue value(cx);
     for (slot = begin; slot < end; slot++) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-            !GetElement(cx, obj, slot, &hole, value.address())) {
+            !GetElement(cx, obj, slot, &hole, &value)) {
             return JS_FALSE;
         }
         if (!hole && !SetArrayElement(cx, nobj, slot - begin, value))
             return JS_FALSE;
     }
 
     args.rval().setObject(*nobj);
     return JS_TRUE;
@@ -2994,17 +3010,19 @@ enum IndexOfKind {
 static JSBool
 array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
 {
     uint32_t length, i, stop;
     Value tosearch;
     int direction;
     JSBool hole;
 
-    JSObject *obj = ToObject(cx, &args.thisv());
+    RootedValue elt(cx);
+
+    RootedObject obj(cx, ToObject(cx, &args.thisv()));
     if (!obj)
         return false;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
     if (length == 0)
         goto not_found;
 
     if (args.length() <= 1) {
@@ -3038,17 +3056,16 @@ array_indexOfHelper(JSContext *cx, Index
         stop = 0;
         direction = -1;
     } else {
         stop = length - 1;
         direction = 1;
     }
 
     for (;;) {
-        Value elt;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, (uint32_t)i, &hole, &elt)) {
             return JS_FALSE;
         }
         if (!hole) {
             bool equal;
             if (!StrictlyEqual(cx, elt, tosearch, &equal))
                 return false;
@@ -3080,41 +3097,41 @@ array_lastIndexOf(JSContext *cx, unsigne
     CallArgs args = CallArgsFromVp(argc, vp);
     return array_indexOfHelper(cx, LastIndexOf, args);
 }
 
 /* ECMA 15.4.4.16-15.4.4.18. */
 class ArrayForEachBehavior
 {
   public:
-    static bool shouldExit(Value &callbackRval, Value *rval) { return false; }
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval) { return false; }
     static Value lateExitValue() { return UndefinedValue(); }
 };
 
 class ArrayEveryBehavior
 {
   public:
-    static bool shouldExit(Value &callbackRval, Value *rval)
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
     {
         if (!ToBoolean(callbackRval)) {
-            *rval = BooleanValue(false);
+            rval.setBoolean(false);
             return true;
         }
         return false;
     }
     static Value lateExitValue() { return BooleanValue(true); }
 };
 
 class ArraySomeBehavior
 {
   public:
-    static bool shouldExit(Value &callbackRval, Value *rval)
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
     {
         if (ToBoolean(callbackRval)) {
-            *rval = BooleanValue(true);
+            rval.setBoolean(true);
             return true;
         }
         return false;
     }
     static Value lateExitValue() { return BooleanValue(false); }
 };
 
 template <class Behavior>
@@ -3142,49 +3159,49 @@ array_readonlyCommon(JSContext *cx, Call
 
     /* Step 5. */
     Value thisv = args.length() >= 2 ? args[1] : UndefinedValue();
 
     /* Step 6. */
     uint32_t k = 0;
 
     /* Step 7. */
+    RootedValue kValue(cx);
     InvokeArgsGuard ag;
     while (k < len) {
         if (!JS_CHECK_OPERATION_LIMIT(cx))
             return false;
 
         /* Step a, b, and c.i. */
-        Value kValue;
         JSBool kNotPresent;
         if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
             return false;
 
         /* Step c.ii-iii. */
         if (!kNotPresent) {
             if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
                 return false;
             ag.setCallee(ObjectValue(*callable));
             ag.thisv() = thisv;
             ag[0] = kValue;
             ag[1] = NumberValue(k);
             ag[2] = ObjectValue(*obj);
             if (!Invoke(cx, ag))
                 return false;
 
-            if (Behavior::shouldExit(ag.rval(), &args.rval()))
+            if (Behavior::shouldExit(ag.rval(), args.rval()))
                 return true;
         }
 
         /* Step d. */
         k++;
     }
 
     /* Step 8. */
-    args.rval() = Behavior::lateExitValue();
+    args.rval().set(Behavior::lateExitValue());
     return true;
  }
 
 /* ES5 15.4.4.16. */
 static JSBool
 array_every(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -3243,39 +3260,40 @@ array_map(JSContext *cx, unsigned argc, 
     if (!newtype)
         return false;
     arr->setType(newtype);
 
     /* Step 7. */
     uint32_t k = 0;
 
     /* Step 8. */
+    RootedValue kValue(cx);
     InvokeArgsGuard ag;
     while (k < len) {
         if (!JS_CHECK_OPERATION_LIMIT(cx))
             return false;
 
         /* Step a, b, and c.i. */
         JSBool kNotPresent;
-        Value kValue;
         if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
             return false;
 
         /* Step c.ii-iii. */
         if (!kNotPresent) {
             if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
                 return false;
             ag.setCallee(ObjectValue(*callable));
             ag.thisv() = thisv;
             ag[0] = kValue;
             ag[1] = NumberValue(k);
             ag[2] = ObjectValue(*obj);
             if (!Invoke(cx, ag))
                 return false;
-            if(!SetArrayElement(cx, arr, k, ag.rval()))
+            kValue = ag.rval();
+            if (!SetArrayElement(cx, arr, k, kValue))
                 return false;
         }
 
         /* Step d. */
         k++;
     }
 
     /* Step 9. */
@@ -3323,23 +3341,23 @@ array_filter(JSContext *cx, unsigned arg
     /* Step 7. */
     uint32_t k = 0;
 
     /* Step 8. */
     uint32_t to = 0;
 
     /* Step 9. */
     InvokeArgsGuard ag;
+    RootedValue kValue(cx);
     while (k < len) {
         if (!JS_CHECK_OPERATION_LIMIT(cx))
             return false;
 
         /* Step a, b, and c.i. */
         JSBool kNotPresent;
-        Value kValue;
         if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
             return false;
 
         /* Step c.ii-iii. */
         if (!kNotPresent) {
             if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
                 return false;
             ag.setCallee(ObjectValue(*callable));
@@ -3393,17 +3411,17 @@ class ArrayReduceRightBehavior
     }
 };
 
 template<class Behavior>
 static inline bool
 array_reduceCommon(JSContext *cx, CallArgs &args)
 {
     /* Step 1. */
-    JSObject *obj = ToObject(cx, &args.thisv());
+    RootedObject obj(cx, ToObject(cx, &args.thisv()));
     if (!obj)
         return false;
 
     /* Step 2-3. */
     uint32_t len;
     if (!js_GetLengthProperty(cx, obj, &len))
         return false;
 
@@ -3423,41 +3441,41 @@ array_reduceCommon(JSContext *cx, CallAr
     }
 
     /* Step 6. */
     uint32_t k, end;
     int32_t step;
     Behavior::initialize(len, &k, &end, &step);
 
     /* Step 7-8. */
-    Value accumulator;
+    RootedValue accumulator(cx);
     if (args.length() >= 2) {
         accumulator = args[1];
     } else {
         JSBool kNotPresent = true;
         while (kNotPresent && k != end) {
             if (!GetElement(cx, obj, k, &kNotPresent, &accumulator))
                 return false;
             k += step;
         }
         if (kNotPresent) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
             return false;
         }
     }
 
     /* Step 9. */
+    RootedValue kValue(cx);
     InvokeArgsGuard ag;
     while (k != end) {
         if (!JS_CHECK_OPERATION_LIMIT(cx))
             return false;
 
         /* Step a, b, and c.i. */
         JSBool kNotPresent;
-        Value kValue;
         if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
             return false;
 
         /* Step c.ii. */
         if (!kNotPresent) {
             if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 4, &ag))
                 return false;
             ag.setCallee(ObjectValue(*callable));
@@ -3471,17 +3489,17 @@ array_reduceCommon(JSContext *cx, CallAr
             accumulator = ag.rval();
         }
 
         /* Step d. */
         k += step;
     }
 
     /* Step 10. */
-    args.rval() = accumulator;
+    args.rval().set(accumulator);
     return true;
 }
 
 /* ES5 15.4.4.21. */
 static JSBool
 array_reduce(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -77,27 +77,28 @@ extern JSBool
 js_GetLengthProperty(JSContext *cx, JSObject *obj, uint32_t *lengthp);
 
 extern JSBool
 js_SetLengthProperty(JSContext *cx, js::HandleObject obj, double length);
 
 namespace js {
 
 extern JSBool
-array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
+array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
 extern JSBool
-array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict);
+array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
+                    MutableHandleValue rval, JSBool strict);
 
 /*
  * Copy 'length' elements from aobj to vp.
  *
  * This function assumes 'length' is effectively the result of calling
- * js_GetLengthProperty on aobj.
+ * js_GetLengthProperty on aobj. vp must point to rooted memory.
  */
 extern bool
 GetElements(JSContext *cx, HandleObject aobj, uint32_t length, js::Value *vp);
 
 /* Natives exposed for optimization by the interpreter and JITs. */
 
 extern JSBool
 array_sort(JSContext *cx, unsigned argc, js::Value *vp);
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -468,47 +468,47 @@ IndexToIdSlow(JSContext *cx, uint32_t in
         return false;
 
     *idp = JSID_FROM_BITS((size_t)atom);
     return true;
 }
 
 bool
 InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
-                      jsid *idp, Value *vp)
+                      jsid *idp, MutableHandleValue vp)
 {
 #if JS_HAS_XML_SUPPORT
     if (idval.isObject()) {
         JSObject *idobj = &idval.toObject();
 
         if (obj && obj->isXML()) {
             *idp = OBJECT_TO_JSID(idobj);
-            *vp = idval;
+            vp.set(idval);
             return true;
         }
 
         if (js_GetLocalNameFromFunctionQName(idobj, idp, cx)) {
-            *vp = IdToValue(*idp);
+            vp.set(IdToValue(*idp));
             return true;
         }
 
         if (!obj && idobj->isXMLId()) {
             *idp = OBJECT_TO_JSID(idobj);
-            *vp = idval;
+            vp.set(idval);
             return JS_TRUE;
         }
     }
 #endif
 
     JSAtom *atom = ToAtom(cx, idval);
     if (!atom)
         return false;
 
     *idp = AtomToId(atom);
-    vp->setString(atom);
+    vp.setString(atom);
     return true;
 }
 
 } /* namespace js */
 
 template<XDRMode mode>
 bool
 js::XDRAtom(XDRState<mode> *xdr, JSAtom **atomp)
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -412,22 +412,22 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
 
 namespace js {
 
 inline JSAtom *
 ToAtom(JSContext *cx, const js::Value &v);
 
 bool
 InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
-                      jsid *idp, Value *vp);
+                      jsid *idp, MutableHandleValue vp);
 
 inline bool
 InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp)
 {
-    Value dummy;
+    RootedValue dummy(cx);
     return InternNonIntElementId(cx, obj, idval, idp, &dummy);
 }
 
 template<XDRMode mode>
 bool
 XDRAtom(XDRState<mode> *xdr, JSAtom **atomp);
 
 } /* namespace js */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -164,17 +164,18 @@ js_InitBooleanClass(JSContext *cx, JSObj
     if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods))
         return NULL;
 
     Rooted<PropertyName*> valueOfName(cx, cx->runtime->atomState.valueOfAtom);
     Rooted<JSFunction*> valueOf(cx,
                                 js_NewFunction(cx, NULL, bool_valueOf, 0, 0, global, valueOfName));
     if (!valueOf)
         return NULL;
-    if (!booleanProto->defineProperty(cx, valueOfName, ObjectValue(*valueOf),
+    RootedValue value(cx, ObjectValue(*valueOf));
+    if (!booleanProto->defineProperty(cx, valueOfName, value,
                                       JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
     global->setBooleanValueOf(valueOf);
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto))
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -156,59 +156,59 @@ typedef JSBool
                  MutableHandleObject objp, MutableHandleShape propp);
 typedef JSBool
 (* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index,
                     MutableHandleObject objp, MutableHandleShape propp);
 typedef JSBool
 (* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                     MutableHandleObject objp, MutableHandleShape propp);
 typedef JSBool
-(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
+(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
+(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
+(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
+(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp);
+(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp);
 typedef JSBool
-(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp);
+(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, MutableHandleValue vp);
 typedef JSBool
-(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp);
+(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp);
 typedef JSBool
-(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool* present);
+(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp, bool* present);
 typedef JSBool
-(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp);
+(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, MutableHandleValue vp);
 typedef JSBool
-(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict);
+(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, JSBool strict);
 typedef JSBool
-(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
+(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp, JSBool strict);
 typedef JSBool
-(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
+(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp, JSBool strict);
 typedef JSBool
-(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
+(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue vp, JSBool strict);
 typedef JSBool
 (* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 typedef JSBool
 (* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp);
 typedef JSBool
 (* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 typedef JSBool
 (* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
 typedef JSBool
-(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
+(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp, JSBool strict);
 typedef JSBool
-(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
+(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp, JSBool strict);
 typedef JSBool
-(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
+(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue vp, JSBool strict);
 typedef JSType
 (* TypeOfOp)(JSContext *cx, HandleObject obj);
 
 typedef JSObject *
 (* ObjectOp)(JSContext *cx, HandleObject obj);
 typedef void
 (* ClearOp)(JSContext *cx, HandleObject obj);
 typedef void
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -565,17 +565,17 @@ JSStructuredCloneWriter::write(const Val
                 RootedObject obj2(context());
                 RootedShape prop(context());
                 if (!js_HasOwnProperty(context(), obj->getOps()->lookupGeneric, obj, id,
                                        &obj2, &prop)) {
                     return false;
                 }
 
                 if (prop) {
-                    Value val;
+                    RootedValue val(context());
                     if (!writeId(id) ||
                         !obj->getGeneric(context(), id, &val) ||
                         !startWrite(val))
                         return false;
                 }
             }
         } else {
             out.writePair(SCTAG_NULL, 0);
@@ -906,18 +906,18 @@ JSStructuredCloneReader::read(Value *vp)
 
         RootedId id(context());
         if (!readId(id.address()))
             return false;
 
         if (JSID_IS_VOID(id)) {
             objs.popBack();
         } else {
-            Value v;
-            if (!startRead(&v) || !obj->defineGeneric(context(), id, v))
+            RootedValue v(context());
+            if (!startRead(v.address()) || !obj->defineGeneric(context(), id, v))
                 return false;
         }
     }
 
     allObjs.clear();
 
     return true;
 }
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -441,39 +441,39 @@ CallJSNativeConstructor(JSContext *cx, N
                  native != js::CallOrConstructBoundFunction &&
                  (!callee->isFunction() || callee->toFunction()->native() != js_Object),
                  !args.rval().isPrimitive() && callee != &args.rval().toObject());
 
     return true;
 }
 
 JS_ALWAYS_INLINE bool
-CallJSPropertyOp(JSContext *cx, PropertyOp op, HandleObject receiver, HandleId id, Value *vp)
+CallJSPropertyOp(JSContext *cx, PropertyOp op, HandleObject receiver, HandleId id, MutableHandleValue vp)
 {
-    assertSameCompartment(cx, receiver, id, *vp);
+    assertSameCompartment(cx, receiver, id, vp);
     JSBool ok = op(cx, receiver, id, vp);
     if (ok)
-        assertSameCompartment(cx, *vp);
+        assertSameCompartment(cx, vp);
     return ok;
 }
 
 JS_ALWAYS_INLINE bool
 CallJSPropertyOpSetter(JSContext *cx, StrictPropertyOp op, HandleObject obj, HandleId id,
-                       JSBool strict, Value *vp)
+                       JSBool strict, MutableHandleValue vp)
 {
-    assertSameCompartment(cx, obj, id, *vp);
+    assertSameCompartment(cx, obj, id, vp);
     return op(cx, obj, id, strict, vp);
 }
 
 inline bool
 CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, unsigned attrs,
-           unsigned shortid, JSBool strict, Value *vp)
+           unsigned shortid, JSBool strict, MutableHandleValue vp)
 {
     if (attrs & JSPROP_SETTER)
-        return InvokeGetterOrSetter(cx, obj, CastAsObjectJsval(op), 1, vp, vp);
+        return InvokeGetterOrSetter(cx, obj, CastAsObjectJsval(op), 1, vp.address(), vp.address());
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx);
 
     if (!(attrs & JSPROP_SHORTID))
         return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
 
     RootedId nid(cx, INT_TO_JSID(shortid));
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -531,17 +531,17 @@ MakeTime(double hour, double min, double
 /* Additional quantities not mentioned in the spec. */
 const double SecondsPerDay = SecondsPerMinute * MinutesPerHour * HoursPerDay;
 
 /**
  * end of ECMA 'support' functions
  */
 
 static JSBool
-date_convert(JSContext *cx, HandleObject obj, JSType hint, Value *vp)
+date_convert(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
     JS_ASSERT(obj->isDate());
 
     return DefaultValue(cx, obj, (hint == JSTYPE_VOID) ? JSTYPE_STRING : hint, vp);
 }
 
 /*
@@ -1448,17 +1448,17 @@ IsDate(const Value &v)
 
 /*
  * See ECMA 15.9.5.4 thru 15.9.5.23
  */
 static bool
 date_getTime_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
-    args.rval() = args.thisv().toObject().getDateUTCTime();
+    args.rval().set(args.thisv().toObject().getDateUTCTime());
     return true;
 }
 
 static JSBool
 date_getTime(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getTime_impl, args);
@@ -1474,17 +1474,17 @@ date_getYear_impl(JSContext *cx, CallArg
         return false;
 
     Value yearVal = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
     if (yearVal.isInt32()) {
         /* Follow ECMA-262 to the letter, contrary to IE JScript. */
         int year = yearVal.toInt32() - 1900;
         args.rval().setInt32(year);
     } else {
-        args.rval() = yearVal;
+        args.rval().set(yearVal);
     }
 
     return true;
 }
 
 static JSBool
 date_getYear(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1496,17 +1496,17 @@ static bool
 date_getFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR));
     return true;
 }
 
 static JSBool
 date_getFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getFullYear_impl, args);
@@ -1536,17 +1536,17 @@ static bool
 date_getMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH));
     return true;
 }
 
 static JSBool
 date_getMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getMonth_impl, args);
@@ -1573,17 +1573,17 @@ static bool
 date_getDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE));
     return true;
 }
 
 static JSBool
 date_getDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getDate_impl, args);
@@ -1613,17 +1613,17 @@ static bool
 date_getDay_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY));
     return true;
 }
 
 static JSBool
 date_getDay(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getDay_impl, args);
@@ -1653,17 +1653,17 @@ static bool
 date_getHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS));
     return true;
 }
 
 static JSBool
 date_getHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getHours_impl, args);
@@ -1693,17 +1693,17 @@ static bool
 date_getMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES));
     return true;
 }
 
 static JSBool
 date_getMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getMinutes_impl, args);
@@ -1735,17 +1735,17 @@ static bool
 date_getUTCSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
-    args.rval() = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS);
+    args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS));
     return true;
 }
 
 static JSBool
 date_getUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_getUTCSeconds_impl, args);
@@ -1804,25 +1804,25 @@ date_getTimezoneOffset(JSContext *cx, un
 
 static bool
 date_setTime_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (args.length() == 0) {
-        SetDateToNaN(cx, thisObj, &args.rval());
+        SetDateToNaN(cx, thisObj, args.rval().address());
         return true;
     }
 
     double result;
     if (!ToNumber(cx, args[0], &result))
         return false;
 
-    return SetUTCTime(cx, thisObj, TimeClip(result), &args.rval());
+    return SetUTCTime(cx, thisObj, TimeClip(result), args.rval().address());
 }
 
 static JSBool
 date_setTime(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setTime_impl, args);
 }
@@ -1873,17 +1873,17 @@ date_setMilliseconds_impl(JSContext *cx,
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &milli))
         return false;
     double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
 
     /* Step 3. */
     double u = TimeClip(UTC(MakeDate(Day(t), time), cx));
 
     /* Steps 4-5. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setMilliseconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setMilliseconds_impl, args);
 }
@@ -1904,17 +1904,17 @@ date_setUTCMilliseconds_impl(JSContext *
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &milli))
         return false;
     double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
 
     /* Step 3. */
     double v = TimeClip(MakeDate(Day(t), time));
 
     /* Steps 4-5. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCMilliseconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCMilliseconds_impl, args);
 }
@@ -1942,17 +1942,17 @@ date_setSeconds_impl(JSContext *cx, Call
 
     /* Step 4. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
 
     /* Step 5. */
     double u = TimeClip(UTC(date, cx));
 
     /* Steps 6-7. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.31. */
 static JSBool
 date_setSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setSeconds_impl, args);
@@ -1980,17 +1980,17 @@ date_setUTCSeconds_impl(JSContext *cx, C
 
     /* Step 4. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
 
     /* Step 5. */
     double v = TimeClip(date);
 
     /* Steps 6-7. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.32. */
 static JSBool
 date_setUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCSeconds_impl, args);
@@ -2023,17 +2023,17 @@ date_setMinutes_impl(JSContext *cx, Call
 
     /* Step 5. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
 
     /* Step 6. */
     double u = TimeClip(UTC(date, cx));
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.33. */
 static JSBool
 date_setMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setMinutes_impl, args);
@@ -2066,17 +2066,17 @@ date_setUTCMinutes_impl(JSContext *cx, C
 
     /* Step 5. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
 
     /* Step 6. */
     double v = TimeClip(date);
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.34. */
 static JSBool
 date_setUTCMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCMinutes_impl, args);
@@ -2114,17 +2114,17 @@ date_setHours_impl(JSContext *cx, CallAr
 
     /* Step 6. */
     double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
 
     /* Step 6. */
     double u = TimeClip(UTC(date, cx));
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.35. */
 static JSBool
 date_setHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setHours_impl, args);
@@ -2162,17 +2162,17 @@ date_setUTCHours_impl(JSContext *cx, Cal
 
     /* Step 6. */
     double newDate = MakeDate(Day(t), MakeTime(h, m, s, milli));
 
     /* Step 7. */
     double v = TimeClip(newDate);
 
     /* Steps 8-9. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.36. */
 static JSBool
 date_setUTCHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCHours_impl, args);
@@ -2195,17 +2195,17 @@ date_setDate_impl(JSContext *cx, CallArg
 
     /* Step 3. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t));
 
     /* Step 4. */
     double u = TimeClip(UTC(newDate, cx));
 
     /* Steps 5-6. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.37. */
 static JSBool
 date_setDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setDate_impl, args);
@@ -2228,17 +2228,17 @@ date_setUTCDate_impl(JSContext *cx, Call
 
     /* Step 3. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t));
 
     /* Step 4. */
     double v = TimeClip(newDate);
 
     /* Steps 5-6. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCDate_impl, args);
 }
@@ -2286,17 +2286,17 @@ date_setMonth_impl(JSContext *cx, CallAr
 
     /* Step 4. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
 
     /* Step 5. */
     double u = TimeClip(UTC(newDate, cx));
 
     /* Steps 6-7. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setMonth_impl, args);
 }
@@ -2324,17 +2324,17 @@ date_setUTCMonth_impl(JSContext *cx, Cal
 
     /* Step 4. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
 
     /* Step 5. */
     double v = TimeClip(newDate);
 
     /* Steps 6-7. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCMonth_impl, args);
 }
@@ -2383,17 +2383,17 @@ date_setFullYear_impl(JSContext *cx, Cal
 
     /* Step 5. */
     double newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
 
     /* Step 6. */
     double u = TimeClip(UTC(newDate, cx));
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, u, &args.rval());
+    return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setFullYear_impl, args);
 }
@@ -2426,17 +2426,17 @@ date_setUTCFullYear_impl(JSContext *cx, 
 
     /* Step 5. */
     double newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
 
     /* Step 6. */
     double v = TimeClip(newDate);
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, v, &args.rval());
+    return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setUTCFullYear_impl, args);
 }
@@ -2454,33 +2454,33 @@ date_setYear_impl(JSContext *cx, CallArg
 
     /* Step 2. */
     double y;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &y))
         return false;
 
     /* Step 3. */
     if (MOZ_DOUBLE_IS_NaN(y)) {
-        SetDateToNaN(cx, thisObj, &args.rval());
+        SetDateToNaN(cx, thisObj, args.rval().address());
         return true;
     }
 
     /* Step 4. */
     double yint = ToInteger(y);
     if (0 <= yint && yint <= 99)
         yint += 1900;
 
     /* Step 5. */
     double day = MakeDay(yint, MonthFromTime(t), DateFromTime(t));
 
     /* Step 6. */
     double u = UTC(MakeDate(day, TimeWithinDay(t)), cx);
 
     /* Steps 7-8. */
-    return SetUTCTime(cx, thisObj, TimeClip(u), &args.rval());
+    return SetUTCTime(cx, thisObj, TimeClip(u), args.rval().address());
 }
 
 static JSBool
 date_setYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_setYear_impl, args);
 }
@@ -2601,17 +2601,17 @@ date_toJSON(JSContext *cx, unsigned argc
 
     /* Step 3. */
     if (tv.isDouble() && !MOZ_DOUBLE_IS_FINITE(tv.toDouble())) {
         vp->setNull();
         return true;
     }
 
     /* Step 4. */
-    Value &toISO = vp[0];
+    RootedValue toISO(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.toISOStringAtom, &toISO))
         return false;
 
     /* Step 5. */
     if (!js_IsCallable(toISO)) {
         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                      JSMSG_BAD_TOISOSTRING_PROP);
         return false;
@@ -2805,17 +2805,17 @@ ToLocaleHelper(JSContext *cx, CallReceiv
               isdigit(buf[2]) && isdigit(buf[3]))) {
             JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
                         "%d", js_DateGetYear(cx, obj));
         }
 
     }
 
     if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
-        return cx->localeCallbacks->localeToUnicode(cx, buf, &call.rval());
+        return cx->localeCallbacks->localeToUnicode(cx, buf, call.rval().address());
 
     JSString *str = JS_NewStringCopyZ(cx, buf);
     if (!str)
         return false;
     call.rval().setString(str);
     return true;
 }
 
@@ -3007,17 +3007,17 @@ date_toString(JSContext *cx, unsigned ar
 
 static bool
 date_valueOf_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
-    args.rval() = thisObj->getDateUTCTime();
+    args.rval().set(thisObj->getDateUTCTime());
     return true;
 }
 
 static JSBool
 date_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsDate, date_valueOf_impl, args);
@@ -3170,21 +3170,21 @@ js_InitDateClass(JSContext *cx, JSObject
 
     /*
      * Define all Date.prototype.* functions, then brand for trace-jitted code.
      * Date.prototype.toGMTString has the same initial value as
      * Date.prototype.toUTCString.
      */
     if (!JS_DefineFunctions(cx, dateProto, date_methods))
         return NULL;
-    Value toUTCStringFun;
+    RootedValue toUTCStringFun(cx);
     RootedId toUTCStringId(cx, NameToId(cx->runtime->atomState.toUTCStringAtom));
     RootedId toGMTStringId(cx, NameToId(cx->runtime->atomState.toGMTStringAtom));
     if (!baseops::GetProperty(cx, dateProto, toUTCStringId, &toUTCStringFun) ||
-        !baseops::DefineGeneric(cx, dateProto, toGMTStringId, &toUTCStringFun,
+        !baseops::DefineGeneric(cx, dateProto, toGMTStringId, toUTCStringFun,
                                 JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Date, ctor, dateProto))
         return NULL;
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -796,26 +796,28 @@ GetPropertyDesc(JSContext *cx, JSObject 
 
     JSBool wasThrowing = cx->isExceptionPending();
     Value lastException = UndefinedValue();
     if (wasThrowing)
         lastException = cx->getPendingException();
     cx->clearPendingException();
 
     Rooted<jsid> id(cx, shape->propid());
-    if (!baseops::GetProperty(cx, obj, id, &pd->value)) {
+    RootedValue value(cx);
+    if (!baseops::GetProperty(cx, obj, id, &value)) {
         if (!cx->isExceptionPending()) {
             pd->flags = JSPD_ERROR;
             pd->value = JSVAL_VOID;
         } else {
             pd->flags = JSPD_EXCEPTION;
             pd->value = cx->getPendingException();
         }
     } else {
         pd->flags = 0;
+        pd->value = value;
     }
 
     if (wasThrowing)
         cx->setPendingException(lastException);
 
     pd->flags |= (shape->enumerable() ? JSPD_ENUMERATE : 0)
               |  (!shape->writable()  ? JSPD_READONLY  : 0)
               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
@@ -1723,34 +1725,37 @@ JSBool js_StopPerf()
 
     perfPid = 0;
     return true;
 }
 
 #endif /* __linux__ */
 
 JS_PUBLIC_API(void)
-JS_DumpBytecode(JSContext *cx, JSScript *script)
+JS_DumpBytecode(JSContext *cx, JSScript *scriptArg)
 {
 #if defined(DEBUG)
+    Rooted<JSScript*> script(cx, scriptArg);
+
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return;
 
     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
     js_Disassemble(cx, script, true, &sprinter);
     fputs(sprinter.string(), stdout);
     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
 #endif
 }
 
 extern JS_PUBLIC_API(void)
-JS_DumpPCCounts(JSContext *cx, JSScript *script)
+JS_DumpPCCounts(JSContext *cx, JSScript *scriptArg)
 {
 #if defined(DEBUG)
+    Rooted<JSScript*> script(cx, scriptArg);
     JS_ASSERT(script->hasScriptCounts);
 
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return;
 
     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
     js_DumpPCCounts(cx, script, &sprinter);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -529,17 +529,17 @@ Exception(JSContext *cx, unsigned argc, 
 
     /*
      * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
      * called as functions, without operator new.  But as we do not give
      * each constructor a distinct JSClass, whose .name member is used by
      * NewNativeClassInstance to find the class prototype, we must get the
      * class prototype ourselves.
      */
-    Value protov;
+    RootedValue protov(cx);
     if (!args.callee().getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &protov))
         return false;
 
     if (!protov.isObject()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error");
         return false;
     }
 
@@ -612,32 +612,32 @@ exn_toString(JSContext *cx, unsigned arg
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error");
         return false;
     }
 
     /* Step 1. */
     RootedObject obj(cx, &args.thisv().toObject());
 
     /* Step 3. */
-    Value nameVal;
+    RootedValue nameVal(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.nameAtom, &nameVal))
         return false;
 
     /* Step 4. */
     RootedString name(cx);
     if (nameVal.isUndefined()) {
         name = CLASS_NAME(cx, Error);
     } else {
         name = ToString(cx, nameVal);
         if (!name)
             return false;
     }
 
     /* Step 5. */
-    Value msgVal;
+    RootedValue msgVal(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.messageAtom, &msgVal))
         return false;
 
     /* Step 6. */
     JSString *message;
     if (msgVal.isUndefined()) {
         message = cx->runtime->emptyString;
     } else {
@@ -685,41 +685,41 @@ exn_toSource(JSContext *cx, unsigned arg
 {
     JS_CHECK_RECURSION(cx, return false);
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject obj(cx, ToObject(cx, &args.thisv()));
     if (!obj)
         return false;
 
-    Value nameVal;
+    RootedValue nameVal(cx);
     RootedString name(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.nameAtom, &nameVal) ||
         !(name = ToString(cx, nameVal)))
     {
         return false;
     }
 
-    Value messageVal;
+    RootedValue messageVal(cx);
     RootedString message(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.messageAtom, &messageVal) ||
         !(message = js_ValueToSource(cx, messageVal)))
     {
         return false;
     }
 
-    Value filenameVal;
+    RootedValue filenameVal(cx);
     RootedString filename(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.fileNameAtom, &filenameVal) ||
         !(filename = js_ValueToSource(cx, filenameVal)))
     {
         return false;
     }
 
-    Value linenoVal;
+    RootedValue linenoVal(cx);
     uint32_t lineno;
     if (!obj->getProperty(cx, cx->runtime->atomState.lineNumberAtom, &linenoVal) ||
         !ToUint32(cx, linenoVal, &lineno))
     {
         return false;
     }
 
     StringBuffer sb(cx);
@@ -778,28 +778,30 @@ static JSObject *
 InitErrorClass(JSContext *cx, Handle<GlobalObject*> global, int type, HandleObject proto)
 {
     JSProtoKey key = GetExceptionProtoKey(type);
     RootedAtom name(cx, cx->runtime->atomState.classAtoms[key]);
     RootedObject errorProto(cx, global->createBlankPrototypeInheriting(cx, &ErrorClass, *proto));
     if (!errorProto)
         return NULL;
 
+    RootedValue nameValue(cx, StringValue(name));
+    RootedValue zeroValue(cx, Int32Value(0));
     RootedValue empty(cx, StringValue(cx->runtime->emptyString));
     RootedId nameId(cx, NameToId(cx->runtime->atomState.nameAtom));
     RootedId messageId(cx, NameToId(cx->runtime->atomState.messageAtom));
     RootedId fileNameId(cx, NameToId(cx->runtime->atomState.fileNameAtom));
     RootedId lineNumberId(cx, NameToId(cx->runtime->atomState.lineNumberAtom));
-    if (!DefineNativeProperty(cx, errorProto, nameId, StringValue(name),
+    if (!DefineNativeProperty(cx, errorProto, nameId, nameValue,
                               JS_PropertyStub, JS_StrictPropertyStub, 0, 0, 0) ||
         !DefineNativeProperty(cx, errorProto, messageId, empty,
                               JS_PropertyStub, JS_StrictPropertyStub, 0, 0, 0) ||
         !DefineNativeProperty(cx, errorProto, fileNameId, empty,
                               JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE, 0, 0) ||
-        !DefineNativeProperty(cx, errorProto, lineNumberId, Int32Value(0),
+        !DefineNativeProperty(cx, errorProto, lineNumberId, zeroValue,
                               JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE, 0, 0))
     {
         return NULL;
     }
 
     /* Create the corresponding constructor. */
     RootedFunction ctor(cx, global->createConstructor(cx, Exception, name, 1,
                                                       JSFunction::ExtendedFinalizeKind));
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -440,17 +440,21 @@ js::SetReservedSlotWithBarrier(JSObject 
 }
 
 JS_FRIEND_API(bool)
 js::GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver_, jsid id_,
                Value *vp)
 {
     RootedObject receiver(cx, receiver_);
     RootedId id(cx, id_);
-    return obj->getGeneric(cx, receiver, id, vp);
+    RootedValue value(cx);
+    if (!obj->getGeneric(cx, receiver, id, &value))
+        return false;
+    *vp = value;
+    return true;
 }
 
 void
 js::SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback)
 {
     rt->preserveWrapperCallback = callback;
 }
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -109,17 +109,17 @@ JS_ObjectToInnerObject(JSContext *cx, JS
 /* Requires obj != NULL. */
 extern JS_FRIEND_API(JSObject *)
 JS_ObjectToOuterObject(JSContext *cx, JSObject *obj);
 
 extern JS_FRIEND_API(JSObject *)
 JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
 
 JS_FRIEND_API(void)
 js_ReportOverRecursed(JSContext *maybecx);
 
 #ifdef DEBUG
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -60,17 +60,17 @@
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::frontend;
 
 static JSBool
-fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, Value *vp)
+fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
 {
     JSObject *obj = obj_;
     while (!obj->isFunction()) {
         obj = obj->getProto();
         if (!obj)
             return true;
     }
     JSFunction *fun = obj->toFunction();
@@ -82,17 +82,17 @@ fun_getProperty(JSContext *cx, HandleObj
      * check any calls that were inlined.
      */
     if (fun->isInterpreted()) {
         fun->script()->uninlineable = true;
         MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
     }
 
     /* Set to early to null in case of error */
-    vp->setNull();
+    vp.setNull();
 
     /* Find fun's top-most activation record. */
     StackIter iter(cx);
     for (; !iter.done(); ++iter) {
         if (!iter.isFunctionFrame() || iter.isEvalFrame())
             continue;
         if (iter.callee() == fun)
             break;
@@ -112,17 +112,17 @@ fun_getProperty(JSContext *cx, HandleObj
                                           NULL, JSMSG_DEPRECATED_USAGE, js_arguments_str)) {
             return false;
         }
 
         ArgumentsObject *argsobj = ArgumentsObject::createUnexpected(cx, fp);
         if (!argsobj)
             return false;
 
-        *vp = ObjectValue(*argsobj);
+        vp.setObject(*argsobj);
         return true;
     }
 
 #ifdef JS_METHODJIT
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
         /*
          * If the frame was called from within an inlined frame, mark the
          * innermost function as uninlineable to expand its frame and allow us
@@ -137,26 +137,26 @@ fun_getProperty(JSContext *cx, HandleObj
             MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
         }
     }
 #endif
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
         ++iter;
         if (iter.done() || !iter.isFunctionFrame()) {
-            JS_ASSERT(vp->isNull());
+            JS_ASSERT(vp.isNull());
             return true;
         }
 
-        *vp = iter.calleev();
+        vp.set(iter.calleev());
 
         /* Censor the caller if it is from another compartment. */
-        JSObject &caller = vp->toObject();
+        JSObject &caller = vp.toObject();
         if (caller.compartment() != cx->compartment) {
-            vp->setNull();
+            vp.setNull();
         } else if (caller.isFunction()) {
             JSFunction *callerFun = caller.toFunction();
             if (callerFun->isInterpreted() && callerFun->inStrictMode()) {
                 JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                              JSMSG_CALLER_IS_STRICT);
                 return false;
             }
         }
@@ -238,21 +238,23 @@ ResolveInterpretedFunctionPrototype(JSCo
         return NULL;
 
     /*
      * Per ES5 15.3.5.2 a user-defined function's .prototype property is
      * initially non-configurable, non-enumerable, and writable.  Per ES5 13.2
      * the prototype's .constructor property is configurable, non-enumerable,
      * and writable.
      */
+    RootedValue protoVal(cx, ObjectValue(*proto));
+    RootedValue objVal(cx, ObjectValue(*obj));
     if (!obj->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom,
-                             ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub,
+                             protoVal, JS_PropertyStub, JS_StrictPropertyStub,
                              JSPROP_PERMANENT) ||
         !proto->defineProperty(cx, cx->runtime->atomState.constructorAtom,
-                               ObjectValue(*obj), JS_PropertyStub, JS_StrictPropertyStub, 0))
+                               objVal, JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
        return NULL;
     }
 
     return proto;
 }
 
 static JSBool
@@ -285,17 +287,17 @@ fun_resolve(JSContext *cx, HandleObject 
         objp.set(fun);
         return true;
     }
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
         JSID_IS_ATOM(id, cx->runtime->atomState.nameAtom)) {
         JS_ASSERT(!IsInternalFunctionObject(obj));
 
-        Value v;
+        RootedValue v(cx);
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             v.setInt32(fun->nargs - fun->hasRest());
         else
             v.setString(fun->atom ? fun->atom : cx->runtime->emptyString);
 
         if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
             return false;
@@ -319,17 +321,18 @@ fun_resolve(JSContext *cx, HandleObject 
                 getter = CastAsPropertyOp(throwTypeError);
                 setter = CastAsStrictPropertyOp(throwTypeError);
                 attrs |= JSPROP_GETTER | JSPROP_SETTER;
             } else {
                 getter = fun_getProperty;
                 setter = JS_StrictPropertyStub;
             }
 
-            if (!DefineNativeProperty(cx, fun, id, UndefinedValue(), getter, setter,
+            RootedValue value(cx, UndefinedValue());
+            if (!DefineNativeProperty(cx, fun, id, value, getter, setter,
                                       attrs, 0, 0)) {
                 return false;
             }
             objp.set(fun);
             return true;
         }
     }
 
@@ -452,17 +455,17 @@ fun_hasInstance(JSContext *cx, HandleObj
     RootedObject obj(cx, obj_);
 
     while (obj->isFunction()) {
         if (!obj->isBoundFunction())
             break;
         obj = obj->toFunction()->getBoundFunctionTarget();
     }
 
-    Value pval;
+    RootedValue pval(cx);
     if (!obj->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &pval))
         return JS_FALSE;
 
     if (pval.isPrimitive()) {
         /*
          * Throw a runtime error if instanceof is called on a function that
          * has a non-object as its .prototype value.
          */
@@ -1496,17 +1499,18 @@ js_DefineFunction(JSContext *cx, HandleO
     fun = js_NewFunction(cx, NULL, native, nargs,
                          attrs & (JSFUN_FLAGS_MASK),
                          obj,
                          JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL,
                          kind);
     if (!fun)
         return NULL;
 
-    if (!obj->defineGeneric(cx, id, ObjectValue(*fun), gop, sop, attrs & ~JSFUN_FLAGS_MASK))
+    RootedValue funVal(cx, ObjectValue(*fun));
+    if (!obj->defineGeneric(cx, id, funVal, gop, sop, attrs & ~JSFUN_FLAGS_MASK))
         return NULL;
 
     return fun;
 }
 
 void
 js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
 {
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -4307,17 +4307,18 @@ AnalyzePoppedThis(JSContext *cx, Vector<
                 TypeSet *parentTypes = parentObject->getProperty(cx, id, false);
                 if (!parentTypes || parentTypes->isOwnProperty(true))
                     return false;
                 parentTypes->add(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSetter>(type));
                 parent = parent->getProto();
             }
 
             unsigned slotSpan = obj->slotSpan();
-            if (!DefineNativeProperty(cx, obj, id, UndefinedValue(), NULL, NULL,
+            RootedValue value(cx, UndefinedValue());
+            if (!DefineNativeProperty(cx, obj, id, value, NULL, NULL,
                                       JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
                 cx->compartment->types.setPendingNukeTypes(cx);
                 *pbaseobj = NULL;
                 return false;
             }
 
             if (obj->inDictionaryMode()) {
                 *pbaseobj = NULL;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -155,45 +155,45 @@ Class js_NoSuchMethodClass = {
  *
  *   this.__noSuchMethod__(id, args)
  *
  * where id is the name of the method that this invocation attempted to
  * call by name, and args is an Array containing this invocation's actual
  * parameters.
  */
 bool
-js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, Value *vp)
+js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, MutableHandleValue vp)
 {
     RootedValue idval(cx, idval_);
 
     RootedId id(cx, NameToId(cx->runtime->atomState.noSuchMethodAtom));
     RootedValue value(cx);
-    if (!GetMethod(cx, obj, id, 0, value.address()))
+    if (!GetMethod(cx, obj, id, 0, &value))
         return false;
     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
 
     if (value.get().isPrimitive()) {
-        *vp = value;
+        vp.set(value);
     } else {
 #if JS_HAS_XML_SUPPORT
         /* Extract the function name from function::name qname. */
         if (idval.get().isObject()) {
             JSObject *obj = &idval.get().toObject();
             if (js_GetLocalNameFromFunctionQName(obj, id.address(), cx))
                 idval = IdToValue(id);
         }
 #endif
 
         JSObject *obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
         if (!obj)
             return false;
 
         obj->setSlot(JSSLOT_FOUND_FUNCTION, value);
         obj->setSlot(JSSLOT_SAVED_ID, idval);
-        vp->setObject(*obj);
+        vp.setObject(*obj);
     }
     return true;
 }
 
 static JSBool
 NoSuchMethod(JSContext *cx, unsigned argc, Value *vp)
 {
     InvokeArgsGuard args;
@@ -351,17 +351,17 @@ js::InvokeKernel(JSContext *cx, CallArgs
     InvokeFrameGuard ifg;
     if (!cx->stack.pushInvokeFrame(cx, args, initial, &ifg))
         return false;
 
     /* Run function until JSOP_STOP, JSOP_RETURN or error. */
     JSBool ok = RunScript(cx, fun->script(), ifg.fp());
 
     /* Propagate the return value out. */
-    args.rval() = ifg.fp()->returnValue();
+    args.rval().set(ifg.fp()->returnValue());
     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     return ok;
 }
 
 bool
 js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, Value *argv,
            Value *rval)
 {
@@ -987,40 +987,40 @@ JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == 
 JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
 JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
 
 /*
  * Inline fast paths for iteration. js_IteratorMore and js_IteratorNext handle
  * all cases, but we inline the most frequently taken paths here.
  */
 static inline bool
-IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
+IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, MutableHandleValue rval)
 {
     if (iterobj->isPropertyIterator()) {
         NativeIterator *ni = iterobj->asPropertyIterator().getNativeIterator();
         if (ni->isKeyIter()) {
             *cond = (ni->props_cursor < ni->props_end);
             return true;
         }
     }
     Rooted<JSObject*> iobj(cx, iterobj);
     if (!js_IteratorMore(cx, iobj, rval))
         return false;
-    *cond = rval->isTrue();
+    *cond = rval.isTrue();
     return true;
 }
 
 static inline bool
-IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
+IteratorNext(JSContext *cx, JSObject *iterobj, MutableHandleValue rval)
 {
     if (iterobj->isPropertyIterator()) {
         NativeIterator *ni = iterobj->asPropertyIterator().getNativeIterator();
         if (ni->isKeyIter()) {
             JS_ASSERT(ni->props_cursor < ni->props_end);
-            rval->setString(*ni->current());
+            rval.setString(*ni->current());
             ni->incCursor();
             return true;
         }
     }
     return js_IteratorNext(cx, iterobj, rval);
 }
 
 /*
@@ -1698,41 +1698,44 @@ BEGIN_CASE(JSOP_IN)
     regs.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_IN)
 
 BEGIN_CASE(JSOP_ITER)
 {
     JS_ASSERT(regs.stackDepth() >= 1);
     uint8_t flags = GET_UINT8(regs.pc);
-    if (!ValueToIterator(cx, flags, &regs.sp[-1]))
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+    if (!ValueToIterator(cx, flags, res))
         goto error;
-    JS_ASSERT(!regs.sp[-1].isPrimitive());
+    JS_ASSERT(!res.isPrimitive());
 }
 END_CASE(JSOP_ITER)
 
 BEGIN_CASE(JSOP_MOREITER)
 {
     JS_ASSERT(regs.stackDepth() >= 1);
     JS_ASSERT(regs.sp[-1].isObject());
     PUSH_NULL();
     bool cond;
-    if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, &regs.sp[-1]))
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+    if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, res))
         goto error;
     regs.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_MOREITER)
 
 BEGIN_CASE(JSOP_ITERNEXT)
 {
     JS_ASSERT(regs.stackDepth() >= unsigned(GET_INT8(regs.pc)));
     Value *itervp = regs.sp - GET_INT8(regs.pc);
     JS_ASSERT(itervp->isObject());
     PUSH_NULL();
-    if (!IteratorNext(cx, &itervp->toObject(), &regs.sp[-1]))
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+    if (!IteratorNext(cx, &itervp->toObject(), res))
         goto error;
 }
 END_CASE(JSOP_ITERNEXT)
 
 BEGIN_CASE(JSOP_ENDITER)
 {
     JS_ASSERT(regs.stackDepth() >= 1);
     bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
@@ -1779,35 +1782,39 @@ BEGIN_CASE(JSOP_PICK)
 }
 END_CASE(JSOP_PICK)
 
 BEGIN_CASE(JSOP_SETCONST)
 {
     RootedPropertyName &name = rootName0;
     name = script->getName(regs.pc);
 
+    RootedValue &rval = rootValue0;
+    rval = regs.sp[-1];
+
     JSObject &obj = regs.fp()->varObj();
-    const Value &ref = regs.sp[-1];
-    if (!obj.defineProperty(cx, name, ref,
+    if (!obj.defineProperty(cx, name, rval,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
         goto error;
     }
 }
 END_CASE(JSOP_SETCONST);
 
 #if JS_HAS_DESTRUCTURING
 BEGIN_CASE(JSOP_ENUMCONSTELEM)
 {
-    const Value &ref = regs.sp[-3];
+    RootedValue &rval = rootValue0;
+    rval = regs.sp[-3];
+
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -1, id);
-    if (!obj->defineGeneric(cx, id, ref,
+    if (!obj->defineGeneric(cx, id, rval,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
         goto error;
     }
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMCONSTELEM)
 #endif
@@ -2152,66 +2159,67 @@ BEGIN_CASE(JSOP_DELNAME)
         goto error;
 
     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
     JS_ASSERT(!script->strictModeCode);
 
     /* ECMA says to return true if name is undefined or inherited. */
     PUSH_BOOLEAN(true);
     if (prop) {
-        if (!obj->deleteProperty(cx, name, &regs.sp[-1], false))
+        MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+        if (!obj->deleteProperty(cx, name, res, false))
             goto error;
     }
 }
 END_CASE(JSOP_DELNAME)
 
 BEGIN_CASE(JSOP_DELPROP)
 {
     RootedPropertyName &name = rootName0;
     name = script->getName(regs.pc);
 
     JSObject *obj;
     FETCH_OBJECT(cx, -1, obj);
 
-    RootedValue &rval = rootValue0;
-    if (!obj->deleteProperty(cx, name, rval.address(), script->strictModeCode))
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+    if (!obj->deleteProperty(cx, name, res, script->strictModeCode))
         goto error;
-
-    regs.sp[-1] = rval;
 }
 END_CASE(JSOP_DELPROP)
 
 BEGIN_CASE(JSOP_DELELEM)
 {
     /* Fetch the left part and resolve it to a non-null object. */
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
 
     RootedValue &propval = rootValue0;
     propval = regs.sp[-1];
-    Value &rval = regs.sp[-2];
-
-    if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
+
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-2]);
+    if (!obj->deleteByValue(cx, propval, res, script->strictModeCode))
         goto error;
 
     regs.sp--;
 }
 END_CASE(JSOP_DELELEM)
 
 BEGIN_CASE(JSOP_TOID)
 {
     /*
      * Increment or decrement requires use to lookup the same property twice, but we need to avoid
      * the oberservable stringification the second time.
      * There must be an object value below the id, which will not be popped
      * but is necessary in interning the id for XML.
      */
     Value objval = regs.sp[-2];
     Value idval = regs.sp[-1];
-    if (!ToIdOperation(cx, objval, idval, &regs.sp[-1]))
+
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
+    if (!ToIdOperation(cx, objval, idval, res))
         goto error;
 }
 END_CASE(JSOP_TOID)
 
 BEGIN_CASE(JSOP_TYPEOFEXPR)
 BEGIN_CASE(JSOP_TYPEOF)
 {
     const Value &ref = regs.sp[-1];
@@ -2324,19 +2332,20 @@ BEGIN_CASE(JSOP_SETPROP)
 }
 END_CASE(JSOP_SETPROP)
 
 BEGIN_CASE(JSOP_GETELEM)
 BEGIN_CASE(JSOP_CALLELEM)
 {
     Value &lref = regs.sp[-2];
     Value &rref = regs.sp[-1];
-    if (!GetElementOperation(cx, op, lref, rref, &regs.sp[-2]))
+    MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-2]);
+    if (!GetElementOperation(cx, op, lref, rref, res))
         goto error;
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
+    TypeScript::Monitor(cx, script, regs.pc, res);
     regs.sp--;
 }
 END_CASE(JSOP_GETELEM)
 
 BEGIN_CASE(JSOP_SETELEM)
 {
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -3, obj);
@@ -2355,17 +2364,17 @@ BEGIN_CASE(JSOP_ENUMELEM)
     RootedObject &obj = rootObject0;
     RootedValue &rval = rootValue0;
 
     /* Funky: the value to set is under the [obj, id] pair. */
     FETCH_OBJECT(cx, -2, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -1, id);
     rval = regs.sp[-3];
-    if (!obj->setGeneric(cx, obj, id, rval.address(), script->strictModeCode))
+    if (!obj->setGeneric(cx, obj, id, &rval, script->strictModeCode))
         goto error;
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
 BEGIN_CASE(JSOP_EVAL)
 {
     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
@@ -2895,17 +2904,17 @@ BEGIN_CASE(JSOP_DEFFUN)
         /*
          * Non-global properties, and global properties which we aren't simply
          * redefining, must be set.  First, this preserves their attributes.
          * Second, this will produce warnings and/or errors as necessary if the
          * specified Call object property is not writable (const).
          */
 
         /* Step 5f. */
-        if (!parent->setProperty(cx, parent, name, rval.address(), script->strictModeCode))
+        if (!parent->setProperty(cx, parent, name, &rval, script->strictModeCode))
             goto error;
     } while (false);
 }
 END_CASE(JSOP_DEFFUN)
 
 BEGIN_CASE(JSOP_LAMBDA)
 {
     /* Load the specified function object literal. */
@@ -2926,18 +2935,18 @@ BEGIN_CASE(JSOP_CALLEE)
     PUSH_COPY(regs.fp()->calleev());
 END_CASE(JSOP_CALLEE)
 
 BEGIN_CASE(JSOP_GETTER)
 BEGIN_CASE(JSOP_SETTER)
 {
     JSOp op2 = JSOp(*++regs.pc);
     RootedId &id = rootId0;
-    RootedValue &rval_ = rootValue0;
-    Value &rval = rval_.get();
+    RootedValue &rval = rootValue0;
+    RootedValue &scratch = rootValue1;
     int i;
 
     RootedObject &obj = rootObject0;
     switch (op2) {
       case JSOP_SETNAME:
       case JSOP_SETPROP:
         id = NameToId(script->getName(regs.pc));
         rval = regs.sp[-1];
@@ -2999,17 +3008,18 @@ BEGIN_CASE(JSOP_SETTER)
         attrs = JSPROP_GETTER;
     } else {
         getter = JS_PropertyStub;
         setter = CastAsStrictPropertyOp(&rval.toObject());
         attrs = JSPROP_SETTER;
     }
     attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
 
-    if (!obj->defineGeneric(cx, id, UndefinedValue(), getter, setter, attrs))
+    scratch.setUndefined();
+    if (!obj->defineGeneric(cx, id, scratch, getter, setter, attrs))
         goto error;
 
     regs.sp += i;
     if (js_CodeSpec[op2].ndefs > js_CodeSpec[op2].nuses) {
         JS_ASSERT(js_CodeSpec[op2].ndefs == js_CodeSpec[op2].nuses + 1);
         regs.sp[-1] = rval;
         assertSameCompartment(cx, regs.sp[-1]);
     }
@@ -3090,32 +3100,32 @@ BEGIN_CASE(JSOP_INITPROP)
     JS_ASSERT(obj->isObject());
 
     PropertyName *name = script->getName(regs.pc);
 
     RootedId &id = rootId0;
     id = NameToId(name);
 
     if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
-        ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, rval.address(), script->strictModeCode)
+        ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, script->strictModeCode)
         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
                                 JSPROP_ENUMERATE, 0, 0, 0)) {
         goto error;
     }
 
     regs.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
 BEGIN_CASE(JSOP_INITELEM_INC)
 BEGIN_CASE(JSOP_INITELEM)
 {
     /* Pop the element's value into rval. */
     JS_ASSERT(regs.stackDepth() >= 3);
-    const Value &rref = regs.sp[-1];
+    HandleValue rref = HandleValue::fromMarkedLocation(&regs.sp[-1]);
 
     RootedObject &obj = rootObject0;
 
     /* Find the object being initialized at top of stack. */
     const Value &lref = regs.sp[-3];
     JS_ASSERT(lref.isObject());
     obj = &lref.toObject();
 
@@ -3156,23 +3166,25 @@ BEGIN_CASE(JSOP_INITELEM)
 END_CASE(JSOP_INITELEM)
 
 BEGIN_CASE(JSOP_SPREAD)
 {
     int32_t count = regs.sp[-2].toInt32();
     RootedObject arr(cx, &regs.sp[-3].toObject());
     const Value iterable = regs.sp[-1];
     ForOfIterator iter(cx, iterable);
+    RootedValue &iterVal = rootValue0;
     while (iter.next()) {
         if (count == INT32_MAX) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_SPREAD_TOO_LARGE);
             goto error;
         }
-        if (!arr->defineElement(cx, count++, iter.value(), NULL, NULL, JSPROP_ENUMERATE))
+        iterVal = iter.value();
+        if (!arr->defineElement(cx, count++, iterVal, NULL, NULL, JSPROP_ENUMERATE))
             goto error;
     }
     if (!iter.close())
         goto error;
     regs.sp[-2].setInt32(count);
     regs.sp--;
 }
 END_CASE(JSOP_SPREAD)
@@ -3401,17 +3413,18 @@ BEGIN_CASE(JSOP_BINDXMLNAME)
 }
 END_CASE(JSOP_BINDXMLNAME)
 
 BEGIN_CASE(JSOP_SETXMLNAME)
 {
     JS_ASSERT(!script->strictModeCode);
 
     Rooted<JSObject*> obj(cx, &regs.sp[-3].toObject());
-    Value rval = regs.sp[-1];
+    RootedValue &rval = rootValue0;
+    rval = regs.sp[-1];
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -2, id);
     if (!obj->setGeneric(cx, obj, id, &rval, script->strictModeCode))
         goto error;
     rval = regs.sp[-1];
     regs.sp -= 2;
     regs.sp[-1] = rval;
 }
@@ -3422,17 +3435,17 @@ BEGIN_CASE(JSOP_XMLNAME)
 {
     JS_ASSERT(!script->strictModeCode);
 
     Value lval = regs.sp[-1];
     RootedObject &obj = rootObject0;
     RootedId &id = rootId0;
     if (!js_FindXMLProperty(cx, lval, &obj, id.address()))
         goto error;
-    Value rval;
+    RootedValue &rval = rootValue0;
     if (!obj->getGeneric(cx, id, &rval))
         goto error;
     regs.sp[-1] = rval;
     if (op == JSOP_CALLXMLNAME) {
         Value v;
         if (!ComputeImplicitThis(cx, obj, &v))
             goto error;
         PUSH_COPY(v);
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -262,17 +262,17 @@ UnwindScope(JSContext *cx, uint32_t stac
 /*
  * Unwind for an uncatchable exception. This means not running finalizers, etc;
  * just preserving the basic engine stack invariants.
  */
 extern void
 UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs);
 
 extern bool
-OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, Value *vp);
+OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, MutableHandleValue vp);
 
 class TryNoteIter
 {
     const FrameRegs &regs;
     JSScript *script;
     uint32_t pcOffset;
     JSTryNote *tn, *tnEnd;
     void settle();
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -184,17 +184,17 @@ AssertValidPropertyCacheHit(JSContext *c
 #else
 inline void
 AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
                             PropertyCacheEntry *entry)
 {}
 #endif
 
 inline bool
-GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleId id, Value *vp)
+GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
     /*
      * Various XML properties behave differently when accessed in a
      * call vs. normal context, and getGeneric will not work right.
      */
 #if JS_HAS_XML_SUPPORT
     if (op == JSOP_CALLPROP && obj->isXML())
         return js_GetXMLMethod(cx, obj, id, vp);
@@ -256,35 +256,37 @@ GetPropertyOperation(JSContext *cx, JSSc
     if (!name) {
         AssertValidPropertyCacheHit(cx, obj, obj2, entry);
         if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp))
             return false;
         return true;
     }
 
     RootedId id(cx, NameToId(name));
+    RootedValue value(cx);
 
     if (obj->getOps()->getProperty) {
-        if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp))
+        if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, &value))
             return false;
     } else {
-        if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp))
+        if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, &value))
             return false;
     }
 
 #if JS_HAS_NO_SUCH_METHOD
     if (op == JSOP_CALLPROP &&
-        JS_UNLIKELY(vp->isPrimitive()) &&
+        JS_UNLIKELY(value.isPrimitive()) &&
         lval.isObject())
     {
-        if (!OnUnknownMethod(cx, obj, IdToValue(id), vp))
+        if (!OnUnknownMethod(cx, obj, IdToValue(id), &value))
             return false;
     }
 #endif
 
+    *vp = value;
     return true;
 }
 
 inline bool
 SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Value &rval)
 {
     RootedObject obj(cx, ValueToObject(cx, lval));
     if (!obj)
@@ -342,20 +344,20 @@ SetPropertyOperation(JSContext *cx, jsby
 
     JSOp op = JSOp(*pc);
 
     RootedId id(cx, NameToId(name));
     if (JS_LIKELY(!obj->getOps()->setProperty)) {
         unsigned defineHow = (op == JSOP_SETNAME)
                              ? DNP_CACHE_RESULT | DNP_UNQUALIFIED
                              : DNP_CACHE_RESULT;
-        if (!baseops::SetPropertyHelper(cx, obj, obj, id, defineHow, rref.address(), strict))
+        if (!baseops::SetPropertyHelper(cx, obj, obj, id, defineHow, &rref, strict))
             return false;
     } else {
-        if (!obj->setGeneric(cx, obj, id, rref.address(), strict))
+        if (!obj->setGeneric(cx, obj, id, &rref, strict))
             return false;
     }
 
     return true;
 }
 
 inline bool
 NameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value *vp)
@@ -399,18 +401,20 @@ NameOperation(JSContext *cx, JSScript *s
         if (js_AtomToPrintableString(cx, name, &printable))
             js_ReportIsNotDefined(cx, printable.ptr());
         return false;
     }
 
     /* Take the slow path if shape was not found in a native object. */
     if (!obj->isNative() || !obj2->isNative()) {
         Rooted<jsid> id(cx, NameToId(name));
-        if (!obj->getGeneric(cx, id, vp))
+        RootedValue value(cx);
+        if (!obj->getGeneric(cx, id, &value))
             return false;
+        *vp = value;
     } else {
         Rooted<JSObject*> normalized(cx, obj);
         if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
             normalized = &normalized->asWith().object();
         if (!NativeGet(cx, normalized, obj2, shape, 0, vp))
             return false;
     }
 
@@ -425,17 +429,18 @@ DefVarOrConstOperation(JSContext *cx, Ha
 
     RootedShape prop(cx);
     RootedObject obj2(cx);
     if (!varobj->lookupProperty(cx, dn, &obj2, &prop))
         return false;
 
     /* Steps 8c, 8d. */
     if (!prop || (obj2 != varobj && varobj->isGlobal())) {
-        if (!varobj->defineProperty(cx, dn, UndefinedValue(), JS_PropertyStub,
+        RootedValue value(cx, UndefinedValue());
+        if (!varobj->defineProperty(cx, dn, value, JS_PropertyStub,
                                     JS_StrictPropertyStub, attrs)) {
             return false;
         }
     } else {
         /*
          * Extension: ordinarily we'd be done here -- but for |const|.  If we
          * see a redeclaration that's |const|, we consider it a conflict.
          */
@@ -596,66 +601,66 @@ ModOperation(JSContext *cx, HandleValue 
         res->setDouble(js_NaN);
     else
         res->setDouble(js_fmod(d1, d2));
     types::TypeScript::MonitorOverflow(cx);
     return true;
 }
 
 static inline bool
-FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp, Value *vp)
+FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp, MutableHandleValue vp)
 {
     int32_t i_;
     if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
         *idp = INT_TO_JSID(i_);
         return true;
     }
     return !!InternNonIntElementId(cx, obj, idval, idp, vp);
 }
 
 static JS_ALWAYS_INLINE bool
-ToIdOperation(JSContext *cx, const Value &objval, const Value &idval, Value *res)
+ToIdOperation(JSContext *cx, const Value &objval, const Value &idval, MutableHandleValue res)
 {
     if (idval.isInt32()) {
-        *res = idval;
+        res.set(idval);
         return true;
     }
 
     JSObject *obj = ValueToObject(cx, objval);
     if (!obj)
         return false;
 
     jsid dummy;
     if (!InternNonIntElementId(cx, obj, idval, &dummy, res))
         return false;
 
-    if (!res->isInt32())
+    if (!res.isInt32())
         types::TypeScript::MonitorUnknown(cx);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value &rref, Value *res)
+GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value &rref, MutableHandleValue res)
 {
 #if JS_HAS_XML_SUPPORT
     if (op == JSOP_CALLELEM && JS_UNLIKELY(obj->isXML())) {
         jsid id;
         if (!FetchElementId(cx, obj, rref, &id, res))
             return false;
         return js_GetXMLMethod(cx, obj, id, res);
     }
 #endif
 
     uint32_t index;
     if (IsDefinitelyIndex(rref, &index)) {
         do {
             if (obj->isDenseArray()) {
                 if (index < obj->getDenseArrayInitializedLength()) {
-                    *res = obj->getDenseArrayElement(index);
-                    if (!res->isMagic())
+                    res.set(obj->getDenseArrayElement(index));
+                    if (!res.isMagic())
                         break;
                 }
             } else if (obj->isArguments()) {
                 if (obj->asArguments().maybeGetElement(index, res))
                     break;
             }
             if (!obj->getElement(cx, index, res))
                 return false;
@@ -664,62 +669,62 @@ GetObjectElementOperation(JSContext *cx,
         JSScript *script;
         jsbytecode *pc;
         types::TypeScript::GetPcScript(cx, &script, &pc);
 
         if (script->hasAnalysis())
             script->analysis()->getCode(pc).getStringElement = true;
 
         SpecialId special;
-        *res = rref;
+        res.set(rref);
         if (ValueIsSpecial(obj, res, &special, cx)) {
             if (!obj->getSpecial(cx, obj, special, res))
                 return false;
         } else {
-            JSAtom *name = ToAtom(cx, *res);
+            JSAtom *name = ToAtom(cx, res);
             if (!name)
                 return false;
 
             if (name->isIndex(&index)) {
                 if (!obj->getElement(cx, index, res))
                     return false;
             } else {
                 if (!obj->getProperty(cx, name->asPropertyName(), res))
                     return false;
             }
         }
     }
 
-    assertSameCompartment(cx, *res);
+    assertSameCompartment(cx, res);
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-GetElementOperation(JSContext *cx, JSOp op, Value &lref, const Value &rref, Value *res)
+GetElementOperation(JSContext *cx, JSOp op, Value &lref, const Value &rref, MutableHandleValue res)
 {
     JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
     if (lref.isString() && rref.isInt32()) {
         JSString *str = lref.toString();
         int32_t i = rref.toInt32();
         if (size_t(i) < str->length()) {
             str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
             if (!str)
                 return false;
-            res->setString(str);
+            res.setString(str);
             return true;
         }
     }
 
     StackFrame *fp = cx->fp();
     if (IsOptimizedArguments(fp, &lref)) {
         if (rref.isInt32()) {
             int32_t i = rref.toInt32();
             if (i >= 0 && uint32_t(i) < fp->numActualArgs()) {
-                *res = fp->unaliasedActual(i);
+                res.set(fp->unaliasedActual(i));
                 return true;
             }
         }
 
         if (!JSScript::argumentsOptimizationFailed(cx, fp->script()))
             return false;
 
         lref = ObjectValue(fp->argsObj());
@@ -728,17 +733,17 @@ GetElementOperation(JSContext *cx, JSOp 
     bool isObject = lref.isObject();
     RootedObject obj(cx, ValueToObject(cx, lref));
     if (!obj)
         return false;
     if (!GetObjectElementOperation(cx, op, obj, rref, res))
         return false;
 
 #if JS_HAS_NO_SUCH_METHOD
-    if (op == JSOP_CALLELEM && JS_UNLIKELY(res->isPrimitive()) && isObject) {
+    if (op == JSOP_CALLELEM && JS_UNLIKELY(res.isPrimitive()) && isObject) {
         if (!OnUnknownMethod(cx, obj, rref, res))
             return false;
     }
 #endif
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
@@ -766,17 +771,17 @@ SetObjectElementOperation(JSContext *cx,
 
                 if (script->hasAnalysis())
                     script->analysis()->getCode(pc).arrayWriteHole = true;
             }
         }
     } while (0);
 
     RootedValue tmp(cx, value);
-    return obj->setGeneric(cx, obj, id, tmp.address(), strict);
+    return obj->setGeneric(cx, obj, id, &tmp, strict);
 }
 
 #define RELATIONAL_OP(OP)                                                     \
     JS_BEGIN_MACRO                                                            \
         RootedValue lvalRoot(cx, lhs), rvalRoot(cx, rhs);                     \
         Value &lval = lvalRoot.get();                                         \
         Value &rval = rvalRoot.get();                                         \
         /* Optimize for two int-tagged operands (typical loop control). */    \
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -70,25 +70,25 @@ struct IdHashPolicy {
     static bool match(jsid id1, jsid id2) {
         return id1 == id2;
     }
 };
 
 typedef HashSet<jsid, IdHashPolicy> IdSet;
 
 static inline bool
-NewKeyValuePair(JSContext *cx, jsid id, const Value &val, Value *rval)
+NewKeyValuePair(JSContext *cx, jsid id, const Value &val, MutableHandleValue rval)
 {
     Value vec[2] = { IdToValue(id), val };
     AutoArrayRooter tvr(cx, ArrayLength(vec), vec);
 
     JSObject *aobj = NewDenseCopiedArray(cx, 2, vec);
     if (!aobj)
         return false;
-    rval->setObject(*aobj);
+    rval.setObject(*aobj);
     return true;
 }
 
 static inline bool
 Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
           bool enumerable, unsigned flags, IdSet& ht, AutoIdVector *props)
 {
     JS_ASSERT_IF(flags & JSITER_OWNONLY, obj == pobj);
@@ -292,17 +292,17 @@ Snapshot(JSContext *cx, JSObject *obj_, 
      * follow the order in which properties are added, in certain cases.
      * Since ECMA does not specify an enumeration order for objects, both
      * behaviors are technically correct to do.
      */
 
     jsid *ids = props->begin();
     size_t n = props->length();
 
-    Vector<jsid> tmp(cx);
+    AutoIdVector tmp(cx);
     if (!tmp.resizeUninitialized(n))
         return false;
 
     if (!MergeSort(ids, n, tmp.begin(), SortComparatorIds(cx)))
         return false;
 
 #endif /* JS_MORE_DETERMINISTIC */
 
@@ -332,39 +332,39 @@ JS_FRIEND_API(bool)
 js::GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector *props)
 {
     return Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), props);
 }
 
 size_t sCustomIteratorCount = 0;
 
 static inline bool
-GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
+GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     /* Check whether we have a valid __iterator__ method. */
     PropertyName *name = cx->runtime->atomState.iteratorIntrinsicAtom;
     if (!GetMethod(cx, obj, name, 0, vp))
         return false;
 
     /* If there is no custom __iterator__ method, we are done here. */
-    if (!vp->isObject()) {
-        vp->setUndefined();
+    if (!vp.isObject()) {
+        vp.setUndefined();
         return true;
     }
 
     if (!cx->runningWithTrustedPrincipals())
         ++sCustomIteratorCount;
 
     /* Otherwise call it and return that object. */
     Value arg = BooleanValue((flags & JSITER_FOREACH) == 0);
-    if (!Invoke(cx, ObjectValue(*obj), *vp, 1, &arg, vp))
+    if (!Invoke(cx, ObjectValue(*obj), vp, 1, &arg, vp.address()))
         return false;
-    if (vp->isPrimitive()) {
+    if (vp.isPrimitive()) {
         /*
          * We are always coming from js::ValueToIterator, and we are no longer on
          * trace, so the object we are iterating over is on top of the stack (-1).
          */
         JSAutoByteString bytes;
         if (!js_AtomToPrintableString(cx, name, &bytes))
             return false;
         js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
@@ -461,17 +461,17 @@ RegisterEnumerator(JSContext *cx, Proper
 
         JS_ASSERT(!(ni->flags & JSITER_ACTIVE));
         ni->flags |= JSITER_ACTIVE;
     }
 }
 
 static inline bool
 VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &keys,
-                    uint32_t slength, uint32_t key, Value *vp)
+                    uint32_t slength, uint32_t key, MutableHandleValue vp)
 {
     JS_ASSERT(!(flags & JSITER_FOREACH));
 
     if (obj) {
         if (obj->hasSingletonType() && !obj->setIteratedSingleton(cx))
             return false;
         types::MarkTypeObjectFlags(cx, obj, types::OBJECT_FLAG_ITERATED);
     }
@@ -498,33 +498,34 @@ VectorToKeyIterator(JSContext *cx, Handl
         do {
             ni->shapes_array[ind++] = pobj->lastProperty();
             pobj = pobj->getProto();
         } while (pobj);
         JS_ASSERT(ind == slength);
     }
 
     iterobj->setNativeIterator(ni);
-    vp->setObject(*iterobj);
+    vp.setObject(*iterobj);
 
     RegisterEnumerator(cx, iterobj, ni);
     return true;
 }
 
 namespace js {
 
 bool
-VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp)
+VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props,
+                    MutableHandleValue vp)
 {
     return VectorToKeyIterator(cx, obj, flags, props, 0, 0, vp);
 }
 
 bool
 VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &keys,
-                      Value *vp)
+                      MutableHandleValue vp)
 {
     JS_ASSERT(flags & JSITER_FOREACH);
 
     if (obj) {
         if (obj->hasSingletonType() && !obj->setIteratedSingleton(cx))
             return false;
         types::MarkTypeObjectFlags(cx, obj, types::OBJECT_FLAG_ITERATED);
     }
@@ -534,79 +535,80 @@ VectorToValueIterator(JSContext *cx, Han
         return false;
 
     NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, keys);
     if (!ni)
         return false;
     ni->init(obj, flags, 0, 0);
 
     iterobj->setNativeIterator(ni);
-    vp->setObject(*iterobj);
+    vp.setObject(*iterobj);
 
     RegisterEnumerator(cx, iterobj, ni);
     return true;
 }
 
 bool
-EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp)
+EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props,
+                             MutableHandleValue vp)
 {
     if (!(flags & JSITER_FOREACH))
         return VectorToKeyIterator(cx, obj, flags, props, vp);
 
     return VectorToValueIterator(cx, obj, flags, props, vp);
 }
 
 static inline void
 UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
 {
     // Update the object for which the native iterator is associated, so
     // SuppressDeletedPropertyHelper will recognize the iterator as a match.
     ni->obj = obj;
 }
 
 bool
-GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
+GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
 {
     if (flags == JSITER_FOR_OF) {
         // for-of loop. The iterator is simply |obj.iterator()|.
-        Value method;
+        RootedValue method(cx);
         if (!obj->getProperty(cx, obj, cx->runtime->atomState.iteratorAtom, &method))
             return false;
 
         // Throw if obj.iterator isn't callable. js::Invoke is about to check
         // for this kind of error anyway, but it would throw an inscrutable
         // error message about |method| rather than this nice one about |obj|.
         if (!method.isObject() || !method.toObject().isCallable()) {
             char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, ObjectOrNullValue(obj), NULL);
             if (!bytes)
                 return false;
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_ITERABLE, bytes);
             cx->free_(bytes);
             return false;
         }
 
-        if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, NULL, vp))
+        if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, NULL, vp.address()))
             return false;
 
-        if (!ToObject(cx, vp))
+        if (!ToObject(cx, vp.address()))
             return false;
         return true;
     }
 
     Vector<Shape *, 8> shapes(cx);
     uint32_t key = 0;
 
     bool keysOnly = (flags == JSITER_ENUMERATE);
 
     if (obj) {
         if (JSIteratorOp op = obj->getClass()->ext.iteratorObject) {
             JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
             if (!iterobj)
                 return false;
-            vp->setObject(*iterobj);
+            vp.setObject(*iterobj);
             types::MarkIteratorUnknown(cx);
             return true;
         }
 
         if (keysOnly) {
             /*
              * Check to see if this is the same as the most recent object which
              * was iterated over.  We don't explicitly check for shapeless
@@ -618,17 +620,17 @@ GetIterator(JSContext *cx, HandleObject 
             if (last) {
                 NativeIterator *lastni = last->getNativeIterator();
                 if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     obj->isNative() &&
                     obj->lastProperty() == lastni->shapes_array[0] &&
                     proto && proto->isNative() &&
                     proto->lastProperty() == lastni->shapes_array[1] &&
                     !proto->getProto()) {
-                    vp->setObject(*last);
+                    vp.setObject(*last);
                     UpdateNativeIterator(lastni, obj);
                     RegisterEnumerator(cx, last, lastni);
                     return true;
                 }
             }
 
             /*
              * The iterator object for JSITER_ENUMERATE never escapes, so we
@@ -654,35 +656,35 @@ GetIterator(JSContext *cx, HandleObject 
 
             PropertyIteratorObject *iterobj = cx->runtime->nativeIterCache.get(key);
             if (iterobj) {
                 NativeIterator *ni = iterobj->getNativeIterator();
                 if (!(ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     ni->shapes_key == key &&
                     ni->shapes_length == shapes.length() &&
                     Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
-                    vp->setObject(*iterobj);
+                    vp.setObject(*iterobj);
 
                     UpdateNativeIterator(ni, obj);
                     RegisterEnumerator(cx, iterobj, ni);
                     if (shapes.length() == 2)
                         cx->runtime->nativeIterCache.last = iterobj;
                     return true;
                 }
             }
         }
 
       miss:
         if (obj->isProxy()) {
             types::MarkIteratorUnknown(cx);
-            return Proxy::iterate(cx, obj, flags, vp);
+            return Proxy::iterate(cx, obj, flags, vp.address());
         }
         if (!GetCustomIterator(cx, obj, flags, vp))
             return false;
-        if (!vp->isUndefined()) {
+        if (!vp.isUndefined()) {
             types::MarkIteratorUnknown(cx);
             return true;
         }
     }
 
     /* NB: for (var p in null) succeeds by iterating over no properties. */
 
     AutoIdVector keys(cx);
@@ -694,17 +696,17 @@ GetIterator(JSContext *cx, HandleObject 
             return false;
     } else {
         if (JS_LIKELY(obj != NULL) && !Snapshot(cx, obj, flags, &keys))
             return false;
         if (!VectorToKeyIterator(cx, obj, flags, keys, shapes.length(), key, vp))
             return false;
     }
 
-    PropertyIteratorObject *iterobj = &vp->toObject().asPropertyIterator();
+    PropertyIteratorObject *iterobj = &vp.toObject().asPropertyIterator();
 
     /* Cache the iterator object if possible. */
     if (shapes.length())
         cx->runtime->nativeIterCache.set(key, iterobj);
 
     if (shapes.length() == 2)
         cx->runtime->nativeIterCache.last = iterobj;
     return true;
@@ -733,51 +735,51 @@ Iterator(JSContext *cx, unsigned argc, V
         return false;
     }
 
     bool keyonly = false;
     if (args.length() >= 2)
         keyonly = ToBoolean(args[1]);
     unsigned flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
 
-    if (!ValueToIterator(cx, flags, &args[0]))
+    if (!ValueToIterator(cx, flags, MutableHandleValue::fromMarkedLocation(&args[0])))
         return false;
-    args.rval() = args[0];
+    args.rval().set(args[0]);
     return true;
 }
 
 static bool
 IsIterator(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&PropertyIteratorObject::class_);
 }
 
 static bool
 iterator_next_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsIterator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
-    if (!js_IteratorMore(cx, thisObj, &args.rval()))
+    if (!js_IteratorMore(cx, thisObj, args.rval()))
         return false;
 
     if (!args.rval().toBoolean()) {
         js_ThrowStopIteration(cx);
         return false;
     }
 
-    return js_IteratorNext(cx, thisObj, &args.rval());
+    return js_IteratorNext(cx, thisObj, args.rval());
 }
 
 static JSBool
 iterator_iterator(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval() = args.thisv();
+    args.rval().set(args.thisv());
     return true;
 }
 
 static JSBool
 iterator_next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsIterator, iterator_next_impl, args);
@@ -897,17 +899,17 @@ ElementIteratorObject::next_impl(JSConte
     // Get target[i].
     JS_ASSERT(i + 1 > i);
     if (target.isString()) {
         JSString *c = cx->runtime->staticStrings.getUnitStringForElement(cx, target.toString(), i);
         if (!c)
             goto close;
         args.rval().setString(c);
     } else {
-        if (!obj->getElement(cx, obj, i, &args.rval()))
+        if (!obj->getElement(cx, obj, i, args.rval()))
             goto close;
     }
 
     // On success, bump the index.
     iterobj->setReservedSlot(IndexSlot, Int32Value(int32_t(i + 1)));
     return true;
 
   close:
@@ -938,46 +940,46 @@ JSFunctionSpec ElementIteratorObject::me
 };
 
 #if JS_HAS_GENERATORS
 static JSBool
 CloseGenerator(JSContext *cx, JSObject *genobj);
 #endif
 
 bool
-js::ValueToIterator(JSContext *cx, unsigned flags, Value *vp)
+js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp)
 {
     /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
     JS_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
 
     /*
      * Make sure the more/next state machine doesn't get stuck. A value might be
      * left in iterValue when a trace is left due to an operation time-out after
      * JSOP_MOREITER but before the value is picked up by FOR*.
      */
     cx->iterValue.setMagic(JS_NO_ITER_VALUE);
 
     RootedObject obj(cx);
-    if (vp->isObject()) {
+    if (vp.isObject()) {
         /* Common case. */
-        obj = &vp->toObject();
+        obj = &vp.toObject();
     } else {
         /*
          * Enumerating over null and undefined gives an empty enumerator.
          * This is contrary to ECMA-262 9.9 ToObject, invoked from step 3 of
          * the first production in 12.6.4 and step 4 of the second production,
          * but it's "web JS" compatible. ES5 fixed for-in to match this de-facto
          * standard.
          */
         if (flags & JSITER_ENUMERATE) {
-            if (!js_ValueToObjectOrNull(cx, *vp, obj.address()))
+            if (!js_ValueToObjectOrNull(cx, vp, obj.address()))
                 return false;
             /* fall through */
         } else {
-            obj = js_ValueToNonNullObject(cx, *vp);
+            obj = js_ValueToNonNullObject(cx, vp);
             if (!obj)
                 return false;
         }
     }
 
     return GetIterator(cx, obj, flags, vp);
 }
 
@@ -1175,108 +1177,93 @@ class IndexRangePredicate {
 
 bool
 js_SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end)
 {
     return SuppressDeletedPropertyHelper(cx, obj, IndexRangePredicate(begin, end));
 }
 
 JSBool
-js_IteratorMore(JSContext *cx, HandleObject iterobj, Value *rval)
+js_IteratorMore(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
 {
     /* Fast path for native iterators */
     NativeIterator *ni = NULL;
     if (iterobj->isPropertyIterator()) {
         /* Key iterators are handled by fast-paths. */
         ni = iterobj->asPropertyIterator().getNativeIterator();
         bool more = ni->props_cursor < ni->props_end;
         if (ni->isKeyIter() || !more) {
-            rval->setBoolean(more);
+            rval.setBoolean(more);
             return true;
         }
     }
 
     /* We might still have a pending value. */
     if (!cx->iterValue.isMagic(JS_NO_ITER_VALUE)) {
-        rval->setBoolean(true);
+        rval.setBoolean(true);
         return true;
     }
 
     /* We're reentering below and can call anything. */
     JS_CHECK_RECURSION(cx, return false);
 
     /* Fetch and cache the next value from the iterator. */
     if (ni) {
         JS_ASSERT(!ni->isKeyIter());
         RootedId id(cx);
         if (!ValueToId(cx, StringValue(*ni->current()), id.address()))
             return false;
         ni->incCursor();
         if (!ni->obj->getGeneric(cx, id, rval))
             return false;
-        if ((ni->flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, *rval, rval))
+        if ((ni->flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, rval, rval))
             return false;
     } else {
         /* Call the iterator object's .next method. */
         if (!GetMethod(cx, iterobj, cx->runtime->atomState.nextAtom, 0, rval))
             return false;
-        if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) {
+        if (!Invoke(cx, ObjectValue(*iterobj), rval, 0, NULL, rval.address())) {
             /* Check for StopIteration. */
             if (!cx->isExceptionPending() || !IsStopIteration(cx->getPendingException()))
                 return false;
 
             cx->clearPendingException();
             cx->iterValue.setMagic(JS_NO_ITER_VALUE);
-            rval->setBoolean(false);
+            rval.setBoolean(false);
             return true;
         }
     }
 
     /* Cache the value returned by iterobj.next() so js_IteratorNext() can find it. */
-    JS_ASSERT(!rval->isMagic(JS_NO_ITER_VALUE));
-    cx->iterValue = *rval;
-    rval->setBoolean(true);
+    JS_ASSERT(!rval.isMagic(JS_NO_ITER_VALUE));
+    cx->iterValue = rval;
+    rval.setBoolean(true);
     return true;
 }
 
 JSBool
-js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
+js_IteratorNext(JSContext *cx, JSObject *iterobj, MutableHandleValue rval)
 {
     /* Fast path for native iterators */
     if (iterobj->isPropertyIterator()) {
         /*
          * Implement next directly as all the methods of the native iterator are
          * read-only and permanent.
          */
         NativeIterator *ni = iterobj->asPropertyIterator().getNativeIterator();
         if (ni->isKeyIter()) {
             JS_ASSERT(ni->props_cursor < ni->props_end);
-            *rval = StringValue(*ni->current());
+            rval.setString(*ni->current());
             ni->incCursor();
-
-            if (rval->isString())
-                return true;
-
-            JSString *str;
-            int i;
-            if (rval->isInt32() && StaticStrings::hasInt(i = rval->toInt32())) {
-                str = cx->runtime->staticStrings.getInt(i);
-            } else {
-                str = ToString(cx, *rval);
-                if (!str)
-                    return false;
-            }
-
-            rval->setString(str);
             return true;
         }
     }
 
     JS_ASSERT(!cx->iterValue.isMagic(JS_NO_ITER_VALUE));
-    *rval = cx->iterValue;
+    rval.set(cx->iterValue);
     cx->iterValue.setMagic(JS_NO_ITER_VALUE);
 
     return true;
 }
 
 static JSBool
 stopiter_hasInstance(JSContext *cx, HandleObject obj, const Value *v, JSBool *bp)
 {
@@ -1623,19 +1610,18 @@ generator_send_impl(JSContext *cx, CallA
     }
 
     if (!SendToGenerator(cx, JSGENOP_SEND, thisObj, gen,
                          args.length() > 0 ? args[0] : UndefinedValue()))
     {
         return false;
     }
 
-    args.rval() = gen->fp->returnValue();
+    args.rval().set(gen->fp->returnValue());
     return true;
-
 }
 
 static JSBool
 generator_send(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsGenerator, generator_send_impl, args);
 }
@@ -1651,17 +1637,17 @@ generator_next_impl(JSContext *cx, CallA
     if (!gen || gen->state == JSGEN_CLOSED) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         return js_ThrowStopIteration(cx);
     }
 
     if (!SendToGenerator(cx, JSGENOP_NEXT, thisObj, gen, UndefinedValue()))
         return false;
 
-    args.rval() = gen->fp->returnValue();
+    args.rval().set(gen->fp->returnValue());
     return true;
 }
 
 static JSBool
 generator_next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsGenerator, generator_next_impl, args);
@@ -1682,19 +1668,18 @@ generator_throw_impl(JSContext *cx, Call
     }
 
     if (!SendToGenerator(cx, JSGENOP_THROW, thisObj, gen,
                          args.length() > 0 ? args[0] : UndefinedValue()))
     {
         return false;
     }
 
-    args.rval() = gen->fp->returnValue();
+    args.rval().set(gen->fp->returnValue());
     return true;
-
 }
 
 static JSBool
 generator_throw(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsGenerator, generator_throw_impl, args);
 }
@@ -1717,17 +1702,17 @@ generator_close_impl(JSContext *cx, Call
         SetGeneratorClosed(cx, gen);
         args.rval().setUndefined();
         return true;
     }
 
     if (!SendToGenerator(cx, JSGENOP_CLOSE, thisObj, gen, UndefinedValue()))
         return false;
 
-    args.rval() = gen->fp->returnValue();
+    args.rval().set(gen->fp->returnValue());
     return true;
 }
 
 static JSBool
 generator_close(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsGenerator, generator_close_impl, args);
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -109,39 +109,42 @@ class ElementIteratorObject : public JSO
     static JSBool next(JSContext *cx, unsigned argc, Value *vp);
     static bool next_impl(JSContext *cx, JS::CallArgs args);
 };
 
 bool
 VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap);
 
 bool
-GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp);
+GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp);
 
 bool
-VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
+VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props,
+                    MutableHandleValue vp);
 
 bool
-VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
+VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props,
+                      MutableHandleValue vp);
 
 /*
  * Creates either a key or value iterator, depending on flags. For a value
  * iterator, performs value-lookup to convert the given list of jsids.
  */
 bool
-EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, Value *vp);
+EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props,
+                             MutableHandleValue vp);
 
 /*
  * Convert the value stored in *vp to its iteration object. The flags should
  * contain JSITER_ENUMERATE if js::ValueToIterator is called when enumerating
  * for-in semantics are required, and when the caller can guarantee that the
  * iterator will never be exposed to scripts.
  */
 bool
-ValueToIterator(JSContext *cx, unsigned flags, Value *vp);
+ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp);
 
 bool
 CloseIterator(JSContext *cx, JSObject *iterObj);
 
 bool
 UnwindIteratorForException(JSContext *cx, JSObject *obj);
 
 void
@@ -159,40 +162,40 @@ extern bool
 js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, uint32_t end);
 
 /*
  * IteratorMore() indicates whether another value is available. It might
  * internally call iterobj.next() and then cache the value until its
  * picked up by IteratorNext(). The value is cached in the current context.
  */
 extern JSBool
-js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::Value *rval);
+js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval);
 
 extern JSBool
-js_IteratorNext(JSContext *cx, JSObject *iterobj, js::Value *rval);
+js_IteratorNext(JSContext *cx, JSObject *iterobj, js::MutableHandleValue rval);
 
 extern JSBool
 js_ThrowStopIteration(JSContext *cx);
 
 namespace js {
 
 /*
  * Get the next value from an iterator object.
  *
  * On success, store the next value in *vp and return true; if there are no
  * more values, store the magic value JS_NO_ITER_VALUE in *vp and return true.
  */
 inline bool
-Next(JSContext *cx, HandleObject iter, Value *vp)
+Next(JSContext *cx, HandleObject iter, MutableHandleValue vp)
 {
     if (!js_IteratorMore(cx, iter, vp))
         return false;
-    if (vp->toBoolean())
+    if (vp.toBoolean())
         return js_IteratorNext(cx, iter, vp);
-    vp->setMagic(JS_NO_ITER_VALUE);
+    vp.setMagic(JS_NO_ITER_VALUE);
     return true;
 }
 
 /*
  * Convenience class for imitating a JS level for-of loop. Typical usage:
  *
  *     ForOfIterator it(cx, iterable);
  *     while (it.next()) {
@@ -221,28 +224,28 @@ class ForOfIterator
     ForOfIterator(const ForOfIterator &) MOZ_DELETE;
     ForOfIterator &operator=(const ForOfIterator &) MOZ_DELETE;
 
   public:
     ForOfIterator(JSContext *cx, const Value &iterable)
         : cx(cx), iterator(cx, NULL), currentValue(cx), closed(false)
     {
         RootedValue iterv(cx, iterable);
-        ok = ValueToIterator(cx, JSITER_FOR_OF, iterv.address());
+        ok = ValueToIterator(cx, JSITER_FOR_OF, &iterv);
         iterator = ok ? &iterv.get().toObject() : NULL;
     }
 
     ~ForOfIterator() {
         if (!closed)
             close();
     }
 
     bool next() {
         JS_ASSERT(!closed);
-        ok = ok && Next(cx, iterator, currentValue.address());
+        ok = ok && Next(cx, iterator, &currentValue);
         return ok && !currentValue.get().isMagic(JS_NO_ITER_VALUE);
     }
 
     Value &value() {
         JS_ASSERT(ok);
         JS_ASSERT(!closed);
         return currentValue.get();
     }
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -346,17 +346,17 @@ js::num_parseInt(JSContext *cx, unsigned
     if (args.length() == 0) {
         args.rval().setDouble(js_NaN);
         return true;
     }
 
     if (args.length() == 1 ||
         (args[1].isInt32() && (args[1].toInt32() == 0 || args[1].toInt32() == 10))) {
         if (args[0].isInt32()) {
-            args.rval() = args[0];
+            args.rval().set(args[0]);
             return true;
         }
         /*
          * Step 1 is |inputString = ToString(string)|. When string >=
          * 1e21, ToString(string) is in the form "NeM". 'e' marks the end of
          * the word, which would mean the result of parseInt(string) should be |N|.
          *
          * To preserve this behaviour, we can't use the fast-path when string >
@@ -660,17 +660,17 @@ num_toLocaleString_impl(JSContext *cx, C
     const char *nint = num;
     if (*nint == '-')
         nint++;
     while (*nint >= '0' && *nint <= '9')
         nint++;
     int digits = nint - num;
     const char *end = num + digits;
     if (!digits) {
-        args.rval() = StringValue(str);
+        args.rval().setString(str);
         return true;
     }
 
     JSRuntime *rt = cx->runtime;
     size_t thousandsLength = strlen(rt->thousandsSeparator);
     size_t decimalLength = strlen(rt->decimalSeparator);
 
     /* Figure out how long resulting string will be. */
@@ -736,27 +736,27 @@ num_toLocaleString_impl(JSContext *cx, C
         JS_ASSERT(tmpDest - buf + ptrdiff_t(strlen(nint)) <= buflen);
         strcpy(tmpDest, nint);
     }
 
     if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode) {
         Rooted<Value> v(cx, StringValue(str));
         bool ok = !!cx->localeCallbacks->localeToUnicode(cx, buf, v.address());
         if (ok)
-            args.rval() = v;
+            args.rval().set(v);
         cx->free_(buf);
         return ok;
     }
 
     str = js_NewStringCopyN(cx, buf, buflen);
     cx->free_(buf);
     if (!str)
         return false;
 
-    args.rval() = StringValue(str);
+    args.rval().setString(str);
     return true;
 }
 
 static JSBool
 num_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, IsNumber, num_toLocaleString_impl, args);
@@ -805,17 +805,17 @@ DToStrResult(JSContext *cx, double d, JS
     char *numStr = js_dtostr(cx->runtime->dtoaState, buf, sizeof buf, mode, precision, d);
     if (!numStr) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
     JSString *str = js_NewStringCopyZ(cx, numStr);
     if (!str)
         return false;
-    args.rval() = StringValue(str);
+    args.rval().setString(str);
     return true;
 }
 
 /*
  * In the following three implementations, we allow a larger range of precision
  * than ECMA requires; this is permitted by ECMA-262.
  */
 static bool
@@ -1153,22 +1153,24 @@ js_InitNumberClass(JSContext *cx, JSObje
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, numberProto, NULL, number_methods))
         return NULL;
 
     if (!JS_DefineFunctions(cx, global, number_functions))
         return NULL;
 
+    RootedValue valueNaN(cx, cx->runtime->NaNValue);
+    RootedValue valueInfinity(cx, cx->runtime->positiveInfinityValue);
+
     /* ES5 15.1.1.1, 15.1.1.2 */
-    if (!DefineNativeProperty(cx, global, cx->runtime->atomState.NaNAtom,
-                              cx->runtime->NaNValue, JS_PropertyStub, JS_StrictPropertyStub,
+    if (!DefineNativeProperty(cx, global, cx->runtime->atomState.NaNAtom, valueNaN,
+                              JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0) ||
-        !DefineNativeProperty(cx, global, cx->runtime->atomState.InfinityAtom,
-                              cx->runtime->positiveInfinityValue,
+        !DefineNativeProperty(cx, global, cx->runtime->atomState.InfinityAtom, valueInfinity,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Number, ctor, numberProto))
         return NULL;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -130,19 +130,17 @@ MarkSharpObjects(JSContext *cx, HandleOb
             RootedObject obj2(cx);
             RootedShape prop(cx);
             ok = obj->lookupGeneric(cx, id, &obj2, &prop);
             if (!ok)
                 break;
             if (!prop)
                 continue;
             bool hasGetter, hasSetter;
-            RootedValue valueRoot(cx), setterRoot(cx);
-            Value &value = valueRoot.get();
-            Value &setter = setterRoot.get();
+            RootedValue value(cx), setter(cx);
             if (obj2->isNative()) {
                 Shape *shape = (Shape *) prop;
                 hasGetter = shape->hasGetterValue();
                 hasSetter = shape->hasSetterValue();
                 if (hasGetter)
                     value = shape->getterValue();
                 if (hasSetter)
                     setter = shape->setterValue();
@@ -438,17 +436,17 @@ obj_toSource(JSContext *cx, unsigned arg
                     val[valcnt] = shape->setterValue();
                     gsop[valcnt] = cx->runtime->atomState.setAtom;
                     valcnt++;
                 }
             }
             if (doGet) {
                 valcnt = 1;
                 gsop[0] = NULL;
-                if (!obj->getGeneric(cx, id, &val[0]))
+                if (!obj->getGeneric(cx, id, MutableHandleValue::fromMarkedLocation(&val[0])))
                     return false;
             }
         }
 
         /*
          * If id is a string that's not an identifier, or if it's a negative
          * integer, then it must be quoted.
          */
@@ -624,24 +622,26 @@ obj_toString(JSContext *cx, unsigned arg
 }
 
 /* ES5 15.2.4.3. */
 static JSBool
 obj_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     /* Step 1. */
-    JSObject *obj = ToObject(cx, &vp[1]);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     /* Steps 2-4. */
     RootedId id(cx, NameToId(cx->runtime->atomState.toStringAtom));
-    return obj->callMethod(cx, id, 0, NULL, vp);
+    return obj->callMethod(cx, id, 0, NULL, args.rval());
 }
 
 static JSBool
 obj_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
@@ -895,27 +895,30 @@ DefineAccessor(JSContext *cx, unsigned a
     if (!ValueToId(cx, args[0], id.address()))
         return false;
 
     RootedObject descObj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!descObj)
         return false;
 
     JSAtomState &state = cx->runtime->atomState;
+    RootedValue trueVal(cx, BooleanValue(true));
+
     /* enumerable: true */
-    if (!descObj->defineProperty(cx, state.enumerableAtom, BooleanValue(true)))
+    if (!descObj->defineProperty(cx, state.enumerableAtom, trueVal))
         return false;
 
     /* configurable: true */
-    if (!descObj->defineProperty(cx, state.configurableAtom, BooleanValue(true)))
+    if (!descObj->defineProperty(cx, state.configurableAtom, trueVal))
         return false;
 
     /* enumerable: true */
     PropertyName *acc = (Type == Getter) ? state.getAtom : state.setAtom;
-    if (!descObj->defineProperty(cx, acc, args[1]))
+    RootedValue accessorVal(cx, args[1]);
+    if (!descObj->defineProperty(cx, acc, accessorVal))
         return false;
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSBool dummy;
     if (!js_DefineOwnProperty(cx, thisObj, id, ObjectValue(*descObj), &dummy)) {
         return false;
     }
@@ -1034,17 +1037,17 @@ obj_getPrototypeOf(JSContext *cx, unsign
      */
     InvokeArgsGuard nested;
     if (!cx->stack.pushInvokeArgs(cx, 0, &nested))
         return false;
     nested.calleev() = cx->global()->protoGetter();
     nested.thisv() = args[0];
     if (!Invoke(cx, nested))
         return false;
-    args.rval() = nested.rval();
+    args.rval().set(nested.rval());
     return true;
 }
 
 namespace js {
 
 bool
 NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp)
 {
@@ -1101,31 +1104,31 @@ PropDesc::makeObject(JSContext *cx)
 {
     MOZ_ASSERT(!isUndefined());
 
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!obj)
         return false;
 
     const JSAtomState &atomState = cx->runtime->atomState;
+    RootedValue configurableVal(cx, BooleanValue((attrs & JSPROP_PERMANENT) == 0));
+    RootedValue enumerableVal(cx, BooleanValue((attrs & JSPROP_ENUMERATE) != 0));
+    RootedValue writableVal(cx, BooleanValue((attrs & JSPROP_READONLY) == 0));
     if ((hasConfigurable() &&
-         !obj->defineProperty(cx, atomState.configurableAtom,
-                              BooleanValue((attrs & JSPROP_PERMANENT) == 0))) ||
+         !obj->defineProperty(cx, atomState.configurableAtom, configurableVal)) ||
         (hasEnumerable() &&
-         !obj->defineProperty(cx, atomState.enumerableAtom,
-                              BooleanValue((attrs & JSPROP_ENUMERATE) != 0))) ||
+         !obj->defineProperty(cx, atomState.enumerableAtom, enumerableVal)) ||
         (hasGet() &&
          !obj->defineProperty(cx, atomState.getAtom, getterValue())) ||
         (hasSet() &&
          !obj->defineProperty(cx, atomState.setAtom, setterValue())) ||
         (hasValue() &&
          !obj->defineProperty(cx, atomState.valueAtom, value())) ||
         (hasWritable() &&
-         !obj->defineProperty(cx, atomState.writableAtom,
-                              BooleanValue((attrs & JSPROP_READONLY) == 0))))
+         !obj->defineProperty(cx, atomState.writableAtom, writableVal)))
     {
         return false;
     }
 
     pd_.setObject(*obj);
     return true;
 }
 
@@ -1154,19 +1157,21 @@ GetOwnPropertyDescriptor(JSContext *cx, 
             if (desc->attrs & JSPROP_SETTER)
                 desc->setter = CastAsStrictPropertyOp(shape->setterObject());
         }
     } else {
         if (!pobj->getGenericAttributes(cx, id, &desc->attrs))
             return false;
     }
 
-    if (doGet && !obj->getGeneric(cx, id, &desc->value))
+    RootedValue value(cx);
+    if (doGet && !obj->getGeneric(cx, id, &value))
         return false;
 
+    desc->value = value;
     desc->obj = obj;
     return true;
 }
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     AutoPropertyDescriptorRooter desc(cx);
@@ -1246,38 +1251,38 @@ obj_keys(JSContext *cx, unsigned argc, V
     if (!aobj)
         return false;
     vp->setObject(*aobj);
 
     return true;
 }
 
 static bool
-HasProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp, bool *foundp)
+HasProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, bool *foundp)
 {
     if (!obj->hasProperty(cx, id, foundp, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING))
         return false;
     if (!*foundp) {
-        vp->setUndefined();
+        vp.setUndefined();
         return true;
     }
 
     /*
      * We must go through the method read barrier in case id is 'get' or 'set'.
      * There is no obvious way to defer cloning a joined function object whose
      * identity will be used by DefinePropertyOnObject, e.g., or reflected via
      * js::GetOwnPropertyDescriptor, as the getter or setter callable object.
      */
     return !!obj->getGeneric(cx, id, vp);
 }
 
 bool
 PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
 {
-    Value v = origval;
+    RootedValue v(cx, origval);
 
     /* 8.10.5 step 1 */
     if (v.isPrimitive()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
         return false;
     }
     RootedObject desc(cx, &v.toObject());
 
@@ -1485,40 +1490,40 @@ DefinePropertyOnObject(JSContext *cx, Ha
     if (!shape) {
         if (!obj->isExtensible())
             return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
 
         *rval = true;
 
         if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
             JS_ASSERT(!obj->getOps()->defineProperty);
-            Value v = desc.hasValue() ? desc.value() : UndefinedValue();
-            return baseops::DefineGeneric(cx, obj, id, &v,
+            RootedValue v(cx, desc.hasValue() ? desc.value() : UndefinedValue());
+            return baseops::DefineGeneric(cx, obj, id, v,
                                           JS_PropertyStub, JS_StrictPropertyStub,
                                           desc.attributes());
         }
 
         JS_ASSERT(desc.isAccessorDescriptor());
 
         /*
          * Getters and setters are just like watchpoints from an access
          * control point of view.
          */
         Value dummy;
         unsigned dummyAttrs;
         if (!CheckAccess(cx, obj, id, JSACC_WATCH, &dummy, &dummyAttrs))
             return JS_FALSE;
 
-        Value tmp = UndefinedValue();
-        return baseops::DefineGeneric(cx, obj, id, &tmp,
+        RootedValue tmp(cx, UndefinedValue());
+        return baseops::DefineGeneric(cx, obj, id, tmp,
                                       desc.getter(), desc.setter(), desc.attributes());
     }
 
     /* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
-    Value v = UndefinedValue();
+    RootedValue v(cx, UndefinedValue());
 
     JS_ASSERT(obj == obj2);
 
     do {
         if (desc.isAccessorDescriptor()) {
             if (!shape->isAccessorDescriptor())
                 break;
 
@@ -1559,17 +1564,17 @@ DefinePropertyOnObject(JSContext *cx, Ha
                 if (!shape->configurable() &&
                     (!shape->hasDefaultGetter() || !shape->hasDefaultSetter()) &&
                     desc.isDataDescriptor() &&
                     (desc.hasWritable() ? desc.writable() : shape->writable()))
                 {
                     return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
                 }
 
-                if (!js_NativeGet(cx, obj, obj2, shape, 0, &v))
+                if (!js_NativeGet(cx, obj, obj2, shape, 0, v.address()))
                     return JS_FALSE;
             }
 
             if (desc.isDataDescriptor()) {
                 if (!shape->isDataDescriptor())
                     break;
 
                 bool same;
@@ -1748,22 +1753,22 @@ DefinePropertyOnObject(JSContext *cx, Ha
      * side effects during setting, we must make them aware that they have been
      * "assigned"; deleting the property before redefining it does the trick.
      * See bug 539766, where we ran into problems when we redefined
      * arguments.length without making the property aware that its value had
      * been changed (which would have happened if we had deleted it before
      * redefining it or we had invoked its setter to change its value).
      */
     if (callDelProperty) {
-        Value dummy = UndefinedValue();
+        RootedValue dummy(cx, UndefinedValue());
         if (!CallJSPropertyOp(cx, obj2->getClass()->delProperty, obj2, id, &dummy))
             return false;
     }
 
-    return baseops::DefineGeneric(cx, obj, id, &v, getter, setter, attrs);
+    return baseops::DefineGeneric(cx, obj, id, v, getter, setter, attrs);
 }
 
 static JSBool
 DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
                       bool throwError, bool *rval)
 {
     /*
      * We probably should optimize dense array property definitions where
@@ -1878,17 +1883,17 @@ ReadPropertyDescriptors(JSContext *cx, H
 {
     if (!GetPropertyNames(cx, props, JSITER_OWNONLY, ids))
         return false;
 
     RootedId id(cx);
     for (size_t i = 0, len = ids->length(); i < len; i++) {
         id = (*ids)[i];
         PropDesc* desc = descs->append();
-        Value v;
+        RootedValue v(cx);
         if (!desc || !props->getGeneric(cx, id, &v) || !desc->initialize(cx, v, checkAccessors))
             return false;
     }
     return true;
 }
 
 } /* namespace js */
 
@@ -2493,32 +2498,33 @@ js::NewReshapedObject(JSContext *cx, Han
     js::Shape *nshape = shape;
     while (!nshape->isEmptyShape()) {
         ids[nshape->slot()] = nshape->propid();
         nshape = nshape->previous();
     }
 
     /* Construct the new shape. */
     RootedId id(cx);
+    RootedValue undefinedValue(cx, UndefinedValue());
     for (unsigned i = 0; i < ids.length(); i++) {
         id = ids[i];
-        if (!DefineNativeProperty(cx, res, id, js::UndefinedValue(), NULL, NULL,
+        if (!DefineNativeProperty(cx, res, id, undefinedValue, NULL, NULL,
                                   JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
             return NULL;
         }
     }
     JS_ASSERT(!res->inDictionaryMode());
 
     return res;
 }
 
 JSObject*
 js_CreateThis(JSContext *cx, Class *newclasp, HandleObject callee)
 {
-    Value protov;
+    RootedValue protov(cx);
     if (!callee->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &protov))
         return NULL;
 
     JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : NULL;
     JSObject *parent = callee->getParent();
     gc::AllocKind kind = NewObjectGCKind(cx, newclasp);
     return NewObjectWithClassProto(cx, newclasp, proto, parent, kind);
 }
@@ -2562,17 +2568,17 @@ js_CreateThisForFunctionWithProto(JSCont
         TypeScript::SetThis(cx, callee->toFunction()->script(), types::Type::ObjectType(res));
 
     return res;
 }
 
 JSObject *
 js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
 {
-    Value protov;
+    RootedValue protov(cx);
     if (!callee->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &protov))
         return NULL;
     JSObject *proto;
     if (protov.isObject())
         proto = &protov.toObject();
     else
         proto = NULL;
     JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
@@ -2671,51 +2677,51 @@ js_InferFlags(JSContext *cx, unsigned de
         pc += cs->length;
         if (pc < script->code + script->length && Detecting(cx, pc))
             flags |= JSRESOLVE_DETECTING;
     }
     return flags;
 }
 
 JSBool
-JSObject::nonNativeSetProperty(JSContext *cx, HandleId id, js::Value *vp, JSBool strict)
+JSObject::nonNativeSetProperty(JSContext *cx, HandleId id, MutableHandleValue vp, JSBool strict)
 {
     RootedObject self(cx, this);
     if (JS_UNLIKELY(watched())) {
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, self, id, vp))
             return false;
     }
     return self->getOps()->setGeneric(cx, self, id, vp, strict);
 }
 
 JSBool
-JSObject::nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict)
+JSObject::nonNativeSetElement(JSContext *cx, uint32_t index, MutableHandleValue vp, JSBool strict)
 {
     RootedObject self(cx, this);
     if (JS_UNLIKELY(watched())) {
         RootedId id(cx);
         if (!IndexToId(cx, index, id.address()))
             return false;
 
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, self, id, vp))
             return false;
     }
     return self->getOps()->setElement(cx, self, index, vp, strict);
 }
 
 bool
-JSObject::deleteByValue(JSContext *cx, const Value &property, Value *rval, bool strict)
+JSObject::deleteByValue(JSContext *cx, const Value &property, MutableHandleValue rval, bool strict)
 {
     uint32_t index;
     if (IsDefinitelyIndex(property, &index))
         return deleteElement(cx, index, rval, strict);
 
-    Value propval = property;
+    RootedValue propval(cx, property);
     Rooted<SpecialId> sid(cx);
     if (ValueIsSpecial(this, &propval, sid.address(), cx))
         return deleteSpecial(cx, sid, rval, strict);
 
     RootedObject self(cx, this);
 
     JSAtom *name = ToAtom(cx, propval);
     if (!name)
@@ -2748,18 +2754,18 @@ JS_CopyPropertiesFrom(JSContext *cx, JSO
         unsigned attrs = shape->attributes();
         PropertyOp getter = shape->getter();
         StrictPropertyOp setter = shape->setter();
         AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
         if ((attrs & JSPROP_GETTER) && !cx->compartment->wrap(cx, &getter))
             return false;
         if ((attrs & JSPROP_SETTER) && !cx->compartment->wrap(cx, &setter))
             return false;
-        Value v = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
-        if (!cx->compartment->wrap(cx, &v))
+        RootedValue v(cx, shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue());
+        if (!cx->compartment->wrap(cx, v.address()))
             return false;
         Rooted<jsid> id(cx, shape->propid());
         if (!target->defineGeneric(cx, id, v, getter, setter, attrs))
             return false;
     }
     return true;
 }
 
@@ -3134,17 +3140,17 @@ JSObject::swap(JSContext *cx, JSObject *
     TradeGuts(cx, this, otherClone, reservedThis);
     TradeGuts(cx, other, thisClone, reservedOther);
 
     return true;
 }
 
 static bool
 DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
-                   const Value &v, uint32_t attrs, bool &named)
+                   HandleValue v, uint32_t attrs, bool &named)
 {
     RootedId id(cx, AtomToId(atom));
 
     if (key != JSProto_Null) {
         /*
          * Initializing an actual standard class on a global object. If the
          * property is not yet present, force it into a new one bound to a
          * reserved slot. Otherwise, go through the normal property path.
@@ -3250,17 +3256,18 @@ DefineConstructorAndPrototype(JSContext 
          * class (a) is anonymous, i.e. for internal use only; (b) the class
          * of obj (the global object) is has a reserved slot indexed by key;
          * and (c) key is not the null key.
          */
         if (!(clasp->flags & JSCLASS_IS_ANONYMOUS) || !obj->isGlobal() || key == JSProto_Null) {
             uint32_t attrs = (clasp->flags & JSCLASS_IS_ANONYMOUS)
                            ? JSPROP_READONLY | JSPROP_PERMANENT
                            : 0;
-            if (!DefineStandardSlot(cx, obj, key, atom, ObjectValue(*proto), attrs, named))
+            RootedValue value(cx, ObjectValue(*proto));
+            if (!DefineStandardSlot(cx, obj, key, atom, value, attrs, named))
                 goto bad;
         }
 
         ctor = proto;
     } else {
         /*
          * Create the constructor, not using GlobalObject::createConstructor
          * because the constructor currently must have |obj| as its parent.
@@ -3277,17 +3284,18 @@ DefineConstructorAndPrototype(JSContext 
          * inference may need to access these, and js_GetClassPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
          */
         if (key != JSProto_Null) {
             SetClassObject(obj, key, fun, proto);
             cached = true;
         }
 
-        if (!DefineStandardSlot(cx, obj, key, atom, ObjectValue(*fun), 0, named))
+        RootedValue value(cx, ObjectValue(*fun));
+        if (!DefineStandardSlot(cx, obj, key, atom, value, 0, named))
             goto bad;
 
         /*
          * Optionally construct the prototype object, before the class has
          * been fully initialized.  Allow the ctor to replace proto with a
          * different object, as is done for operator new -- and as at least
          * XML support requires.
          */
@@ -3319,17 +3327,17 @@ DefineConstructorAndPrototype(JSContext 
         SetClassObject(obj, key, ctor, proto);
 
     if (ctorp)
         *ctorp = ctor;
     return proto;
 
 bad:
     if (named) {
-        Value rval;
+        RootedValue rval(cx);
         obj->deleteByValue(cx, StringValue(atom), &rval, false);
     }
     if (cached)
         ClearClassObject(cx, obj, key);
     return NULL;
 }
 
 /*
@@ -4036,79 +4044,78 @@ js_AddNativeProperty(JSContext *cx, Hand
      */
     if (!js_PurgeScopeChain(cx, obj, id))
         return NULL;
 
     return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid);
 }
 
 JSBool
-baseops::DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
-                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
+baseops::DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
+                       PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+{
+    return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
 }
 
 JSBool
-baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
+baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     Rooted<jsid> id(cx);
     if (index <= JSID_INT_MAX) {
         id = INT_TO_JSID(index);
-        return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
+        return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
     }
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     if (!IndexToId(cx, index, id.address()))
         return false;
 
-    return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
+    return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
 }
 
 /*
  * Backward compatibility requires allowing addProperty hooks to mutate the
  * nominal initial value of a slotful property, while GC safety wants that
  * value to be stored before the call-out through the hook.  Optimize to do
  * both while saving cycles for classes that stub their addProperty hook.
  */
 static inline bool
-CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape shape, Value *vp)
+CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape shape,
+                    HandleValue nominal)
 {
     if (clasp->addProperty != JS_PropertyStub) {
-        Value nominal = *vp;
+        /* Make a local copy of value so addProperty can mutate its inout parameter. */
+        RootedValue value(cx, nominal);
 
         Rooted<jsid> id(cx, shape->propid());
-        if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, vp))
+        if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value))
             return false;
-        if (*vp != nominal) {
+        if (value.get() != nominal) {
             if (shape->hasSlot())
-                obj->nativeSetSlotWithType(cx, shape, *vp);
+                obj->nativeSetSlotWithType(cx, shape, value);
         }
     }
     return true;
 }
 
 namespace js {
 
 Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &valueArg,
+DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow /* = 0 */)
 {
     JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE |
                              DNP_SKIP_TYPE)) == 0);
     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
-    /* Make a local copy of value so addProperty can mutate its inout parameter. */
-    RootedValue value(cx, valueArg);
-
     /*
      * If defining a getter or setter, we must check for its counterpart and
      * update the attributes and property ops.  A getter or setter is really
      * only half of a property.
      */
     RootedShape shape(cx);
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
         /* Type information for getter/setter properties is unknown. */
@@ -4176,17 +4183,17 @@ DefineNativeProperty(JSContext *cx, Hand
         if (!shape)
             return NULL;
     }
 
     /* Store valueCopy before calling addProperty, in case the latter GC's. */
     if (shape->hasSlot())
         obj->nativeSetSlot(shape->slot(), value);
 
-    if (!CallAddPropertyHook(cx, clasp, obj, shape, value.address())) {
+    if (!CallAddPropertyHook(cx, clasp, obj, shape, value)) {
         obj->removeProperty(cx, id);
         return NULL;
     }
 
     return shape;
 }
 
 } /* namespace js */
@@ -4553,24 +4560,26 @@ js_NativeGetInline(JSContext *cx, Handle
     if (script && script->hasAnalysis()) {
         analyze::Bytecode *code = script->analysis()->maybeCode(pc);
         if (code)
             code->accessGetter = true;
     }
 
     Rooted<Shape*> shapeRoot(cx, shape);
     RootedObject pobjRoot(cx, pobj);
-
-    if (!shape->get(cx, receiver, obj, pobj, vp))
+    RootedValue nvp(cx, *vp);
+
+    if (!shape->get(cx, receiver, obj, pobj, &nvp))
         return false;
 
     /* Update slotful shapes according to the value produced by the getter. */
     if (shapeRoot->hasSlot() && pobjRoot->nativeContains(cx, shapeRoot))
-        pobjRoot->nativeSetSlot(shapeRoot->slot(), *vp);
-
+        pobjRoot->nativeSetSlot(shapeRoot->slot(), nvp);
+
+    *vp = nvp;
     return true;
 }
 
 JSBool
 js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shape,
              unsigned getHow, Value *vp)
 {
     return js_NativeGetInline(cx, obj, obj, pobj, shape, getHow, vp);
@@ -4599,62 +4608,64 @@ js_NativeSet(JSContext *cx, Handle<JSObj
          * not writable, so attempting to set such a property should do nothing
          * or throw if we're in strict mode.
          */
         if (!shape->hasGetterValue() && shape->hasDefaultSetter())
             return js_ReportGetterOnlyAssignment(cx);
     }
 
     Rooted<Shape *> shapeRoot(cx, shape);
+    RootedValue nvp(cx, *vp);
 
     int32_t sample = cx->runtime->propertyRemovals;
-    if (!shapeRoot->set(cx, obj, receiver, strict, vp))
+    if (!shapeRoot->set(cx, obj, receiver, strict, &nvp))
         return false;
 
     /*
      * Update any slot for the shape with the value produced by the setter,
      * unless the setter deleted the shape.
      */
     if (shapeRoot->hasSlot() &&
         (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
          obj->nativeContains(cx, shapeRoot))) {
-        obj->setSlot(shapeRoot->slot(), *vp);
-    }
-
+        obj->setSlot(shapeRoot->slot(), nvp);
+    }
+
+    *vp = nvp;
     return true;
 }
 
 static JS_ALWAYS_INLINE JSBool
 js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id_,
-                           uint32_t getHow, Value *vp)
+                           uint32_t getHow, MutableHandleValue vp)
 {
     RootedId id(cx, id_);
 
     /* This call site is hot -- use the always-inlined variant of LookupPropertyWithFlags(). */
     RootedObject obj2(cx);
     RootedShape shape(cx);
     if (!LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, &obj2, &shape))
         return false;
 
     if (!shape) {
-        vp->setUndefined();
+        vp.setUndefined();
 
         if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp))
             return JS_FALSE;
 
         /* Record non-undefined values produced by the class getter hook. */
-        if (!vp->isUndefined())
-            AddTypePropertyId(cx, obj, id, *vp);
+        if (!vp.isUndefined())
+            AddTypePropertyId(cx, obj, id, vp);
 
         /*
          * Give a strict warning if foo.bar is evaluated by a script for an
          * object foo with no property named 'bar'.
          */
         jsbytecode *pc;
-        if (vp->isUndefined() && ((pc = js_GetCurrentBytecodePC(cx)) != NULL)) {
+        if (vp.isUndefined() && ((pc = js_GetCurrentBytecodePC(cx)) != NULL)) {
             JSOp op = (JSOp) *pc;
 
             if (op == JSOP_GETXPROP) {
                 /* Undefined property during a name lookup, report an error. */
                 JSAutoByteString printable;
                 if (js_ValueToPrintable(cx, IdToValue(id), &printable))
                     js_ReportIsNotDefined(cx, printable.ptr());
                 return false;
@@ -4693,72 +4704,74 @@ js_GetPropertyHelperInline(JSContext *cx
                 return false;
             }
         }
         return JS_TRUE;
     }
 
     if (!obj2->isNative()) {
         return obj2->isProxy()
-               ? Proxy::get(cx, obj2, receiver, id, vp)
+               ? Proxy::get(cx, obj2, receiver, id, vp.address())
                : obj2->getGeneric(cx, id, vp);
     }
 
     if (getHow & JSGET_CACHE_RESULT)
         JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj2, shape);
 
     /* This call site is hot -- use the always-inlined variant of js_NativeGet(). */
-    if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp))
+    if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp.address()))
         return JS_FALSE;
 
     return JS_TRUE;
 }
 
 bool
-js::GetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, uint32_t getHow, Value *vp)
+js::GetPropertyHelper(JSContext *cx, HandleObject obj, HandleId id, uint32_t getHow, MutableHandleValue vp)
 {
     return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
 }
 
 JSBool
-baseops::GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
+baseops::GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp)
 {
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
     return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
-baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
+baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
+                    MutableHandleValue vp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
 
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
     return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
-baseops::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp)
+baseops::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, HandleValue def,
+                            MutableHandleValue vp)
 {
     RootedShape prop(cx);
     RootedObject obj2(cx);
     if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
         return false;
 
     if (!prop) {
-        *vp = def;
+        vp.set(def);
         return true;
     }
 
     return baseops::GetProperty(cx, obj2, id, vp);
 }
 
 JSBool
-js::GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, Value *vp)
+js::GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, MutableHandleValue vp)
 {
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     GenericIdOp op = obj->getOps()->getGeneric;
     if (!op) {
 #if JS_HAS_XML_SUPPORT
         JS_ASSERT(!obj->isXML());
 #endif
@@ -4813,27 +4826,27 @@ bool
 JSObject::reportNotExtensible(JSContext *cx, unsigned report)
 {
     return js_ReportValueErrorFlags(cx, report, JSMSG_OBJECT_NOT_EXTENSIBLE,
                                     JSDVG_IGNORE_STACK, ObjectValue(*this),
                                     NULL, NULL, NULL);
 }
 
 bool
-JSObject::callMethod(JSContext *cx, HandleId id, unsigned argc, Value *argv, Value *vp)
-{
-    Value fval;
+JSObject::callMethod(JSContext *cx, HandleId id, unsigned argc, Value *argv, MutableHandleValue vp)
+{
+    RootedValue fval(cx);
     Rooted<JSObject*> obj(cx, this);
     return GetMethod(cx, obj, id, 0, &fval) &&
-           Invoke(cx, ObjectValue(*obj), fval, argc, argv, vp);
+           Invoke(cx, ObjectValue(*obj), fval, argc, argv, vp.address());
 }
 
 JSBool
 baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
-                           unsigned defineHow, Value *vp, JSBool strict)
+                           unsigned defineHow, MutableHandleValue vp, JSBool strict)
 {
     unsigned attrs, flags;
     int shortid;
     Class *clasp;
     PropertyOp getter;
     StrictPropertyOp setter;
     bool added;
 
@@ -5002,22 +5015,22 @@ baseops::SetPropertyHelper(JSContext *cx
             return JS_FALSE;
         }
         added = true;
     }
 
     if ((defineHow & DNP_CACHE_RESULT) && !added)
         JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj, shape);
 
-    return js_NativeSet(cx, obj, receiver, shape, added, strict, vp);
+    return js_NativeSet(cx, obj, receiver, shape, added, strict, vp.address());
 }
 
 JSBool
 baseops::SetElementHelper(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
-                          unsigned defineHow, Value *vp, JSBool strict)
+                          unsigned defineHow, MutableHandleValue vp, JSBool strict)
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, id.address()))
         return false;
     return baseops::SetPropertyHelper(cx, obj, receiver, id, defineHow, vp, strict);
 }
 
 JSBool
@@ -5080,74 +5093,77 @@ baseops::SetElementAttributes(JSContext 
     if (!shape)
         return true;
     return nobj->isNative()
            ? nobj->changePropertyAttributes(cx, shape, *attrsp)
            : nobj->setElementAttributes(cx, index, attrsp);
 }
 
 JSBool
-baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict)
-{
-    rval->setBoolean(true);
+baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue rval, JSBool strict)
+{
+    rval.setBoolean(true);
 
     RootedObject proto(cx);
     RootedShape shape(cx);
     if (!baseops::LookupProperty(cx, obj, id, &proto, &shape))
         return false;
     if (!shape || proto != obj) {
         /*
          * If no property, or the property comes from a prototype, call the
          * class's delProperty hook, passing rval as the result parameter.
          */
         return CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval);
     }
 
     if (!shape->configurable()) {
         if (strict)
             return obj->reportNotConfigurable(cx, id);
-        rval->setBoolean(false);
+        rval.setBoolean(false);
         return true;
     }
 
     if (shape->hasSlot()) {
         const Value &v = obj->nativeGetSlot(shape->slot());
         GCPoke(cx->runtime, v);
     }
 
     RootedId userid(cx);
     if (!shape->getUserId(cx, userid.address()))
         return false;
 
     if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, userid, rval))
         return false;
-    if (rval->isFalse())
+    if (rval.isFalse())
         return true;
 
     return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
 }
 
 JSBool
-baseops::DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict)
+baseops::DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
+                        MutableHandleValue rval, JSBool strict)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return baseops::DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 JSBool
-baseops::DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict)
+baseops::DeleteElement(JSContext *cx, HandleObject obj, uint32_t index,
+                       MutableHandleValue rval, JSBool strict)
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, id.address()))
         return false;
     return baseops::DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 JSBool
-baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict)
+baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
+                       MutableHandleValue rval, JSBool strict)
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return baseops::DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 namespace js {
 
 bool
@@ -5167,89 +5183,89 @@ HasDataProperty(JSContext *cx, HandleObj
  * Gets |obj[id]|.  If that value's not callable, returns true and stores a
  * non-primitive value in *vp.  If it's callable, calls it with no arguments
  * and |obj| as |this|, returning the result in *vp.
  *
  * This is a mini-abstraction for ES5 8.12.8 [[DefaultValue]], either steps 1-2
  * or steps 3-4.
  */
 static bool
-MaybeCallMethod(JSContext *cx, HandleObject obj, Handle<jsid> id, Value *vp)
+MaybeCallMethod(JSContext *cx, HandleObject obj, Handle<jsid> id, MutableHandleValue vp)
 {
     if (!GetMethod(cx, obj, id, 0, vp))
         return false;
-    if (!js_IsCallable(*vp)) {
-        *vp = ObjectValue(*obj);
+    if (!js_IsCallable(vp)) {
+        vp.setObject(*obj);
         return true;
     }
-    return Invoke(cx, ObjectValue(*obj), *vp, 0, NULL, vp);
+    return Invoke(cx, ObjectValue(*obj), vp, 0, NULL, vp.address());
 }
 
 JSBool
-DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp)
+DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
 #if JS_HAS_XML_SUPPORT
     JS_ASSERT(!obj->isXML());
 #endif
 
     Rooted<jsid> id(cx);
 
     Class *clasp = obj->getClass();
     if (hint == JSTYPE_STRING) {
         id = NameToId(cx->runtime->atomState.toStringAtom);
 
         /* Optimize (new String(...)).toString(). */
         if (clasp == &StringClass) {
             if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) {
-                *vp = StringValue(obj->asString().unbox());
+                vp.setString(obj->asString().unbox());
                 return true;
             }
         }
 
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
-        if (vp->isPrimitive())
+        if (vp.isPrimitive())
             return true;
 
         id = NameToId(cx->runtime->atomState.valueOfAtom);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
-        if (vp->isPrimitive())
+        if (vp.isPrimitive())
             return true;
     } else {
 
         /* Optimize new String(...).valueOf(). */
         if (clasp == &StringClass) {
             id = NameToId(cx->runtime->atomState.valueOfAtom);
             if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) {
-                *vp = StringValue(obj->asString().unbox());
+                vp.setString(obj->asString().unbox());
                 return true;
             }
         }
 
         /* Optimize new Number(...).valueOf(). */
         if (clasp == &NumberClass) {
             id = NameToId(cx->runtime->atomState.valueOfAtom);
             if (ClassMethodIsNative(cx, obj, &NumberClass, id, js_num_valueOf)) {
-                *vp = NumberValue(obj->asNumber().unbox());
+                vp.setNumber(obj->asNumber().unbox());
                 return true;
             }
         }
 
         id = NameToId(cx->runtime->atomState.valueOfAtom);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
-        if (vp->isPrimitive())
+        if (vp.isPrimitive())
             return true;
 
         id = NameToId(cx->runtime->atomState.toStringAtom);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
-        if (vp->isPrimitive())
+        if (vp.isPrimitive())
             return true;
     }
 
     /* Avoid recursive death when decompiling in js_ReportValueError. */
     JSString *str;
     if (hint == JSTYPE_STRING) {
         str = JS_InternString(cx, clasp->name);
         if (!str)
@@ -5381,17 +5397,17 @@ js::FindClassPrototype(JSContext *cx, Ha
                        MutableHandleObject protop, Class *clasp)
 {
     RootedValue v(cx);
     if (!js_FindClassObject(cx, scopeobj, protoKey, &v, clasp))
         return false;
 
     if (IsFunctionObject(v)) {
         JSObject *ctor = &v.get().toObject();
-        if (!ctor->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, v.address()))
+        if (!ctor->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &v))
             return false;
     }
 
     protop.set(v.get().isObject() ? &v.get().toObject() : NULL);
     return true;
 }
 
 /*
@@ -5585,17 +5601,17 @@ js_ReportGetterOnlyAssignment(JSContext 
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
                                         js_GetErrorMessage, NULL,
                                         JSMSG_GETTER_ONLY);
 }
 
 JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_GETTER_ONLY);
     return JS_FALSE;
 }
 
 #ifdef DEBUG
 
 /*
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -109,67 +109,67 @@ LookupProperty(JSContext *cx, HandleObje
     return LookupProperty(cx, obj, id, objp, propp);
 }
 
 extern JS_FRIEND_API(JSBool)
 LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
               MutableHandleObject objp, MutableHandleShape propp);
 
 extern JSBool
-DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, const js::Value *value,
+DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 inline JSBool
-DefineProperty(JSContext *cx, HandleObject obj, PropertyName *name, const js::Value *value,
+DefineProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
                JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 extern JSBool
-DefineElement(JSContext *cx, HandleObject obj, uint32_t index, const js::Value *value,
+DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
               JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JSBool
-GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, js::Value *vp);
+GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp);
 
 extern JSBool
-GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, js::Value *vp);
+GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp);
 
 inline JSBool
-GetProperty(JSContext *cx, HandleObject obj, HandleId id, js::Value *vp)
+GetProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
     return GetProperty(cx, obj, obj, id, vp);
 }
 
 inline JSBool
-GetElement(JSContext *cx, HandleObject obj, uint32_t index, js::Value *vp)
+GetElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
 {
     return GetElement(cx, obj, obj, index, vp);
 }
 
 extern JSBool
-GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp);
+GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, HandleValue def, MutableHandleValue vp);
 
 extern JSBool
 SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
-                  unsigned defineHow, Value *vp, JSBool strict);
+                  unsigned defineHow, MutableHandleValue vp, JSBool strict);
 
 inline bool
 SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receiver, PropertyName *name,
-                  unsigned defineHow, Value *vp, JSBool strict)
+                  unsigned defineHow, MutableHandleValue vp, JSBool strict)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return SetPropertyHelper(cx, obj, receiver, id, defineHow, vp, strict);
 }
 
 extern JSBool
 SetElementHelper(JSContext *cx, HandleObject obj, HandleObject Receiver, uint32_t index,
-                 unsigned defineHow, Value *vp, JSBool strict);
+                 unsigned defineHow, MutableHandleValue vp, JSBool strict);
 
 extern JSType
 TypeOf(JSContext *cx, HandleObject obj);
 
 extern JSBool
 GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 
 extern JSBool
@@ -177,32 +177,32 @@ SetAttributes(JSContext *cx, HandleObjec
 
 extern JSBool
 GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 
 extern JSBool
 SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 
 extern JSBool
-DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict);
+DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue rval, JSBool strict);
 
 extern JSBool
-DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict);
+DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue rval, JSBool strict);
 
 extern JSBool
-DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict);
+DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue rval, JSBool strict);
 
 extern JSBool
-DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict);
+DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue rval, JSBool strict);
 
 } /* namespace js::baseops */
 
 /* ES5 8.12.8. */
 extern JSBool
-DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp);
+DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp);
 
 extern Class ArrayClass;
 extern Class ArrayBufferClass;
 extern Class BlockClass;
 extern Class BooleanClass;
 extern Class CallableObjectClass;
 extern Class DataViewClass;
 extern Class DateClass;
@@ -725,17 +725,18 @@ struct JSObject : public js::ObjectImpl
     bool reportNotExtensible(JSContext *cx, unsigned report = JSREPORT_ERROR);
 
     /*
      * Get the property with the given id, then call it as a function with the
      * given arguments, providing this object as |this|. If the property isn't
      * callable a TypeError will be thrown. On success the value returned by
      * the call is stored in *vp.
      */
-    bool callMethod(JSContext *cx, js::HandleId id, unsigned argc, js::Value *argv, js::Value *vp);
+    bool callMethod(JSContext *cx, js::HandleId id, unsigned argc, js::Value *argv,
+                    js::MutableHandleValue vp);
 
   private:
     js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
 
   protected:
     /*
      * Internal helper that adds a shape not yet mapped by this object.
      *
@@ -800,78 +801,78 @@ struct JSObject : public js::ObjectImpl
                                 js::MutableHandleObject objp, js::MutableHandleShape propp);
     inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name,
                                  js::MutableHandleObject objp, js::MutableHandleShape propp);
     inline JSBool lookupElement(JSContext *cx, uint32_t index,
                                 js::MutableHandleObject objp, js::MutableHandleShape propp);
     inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid,
                                 js::MutableHandleObject objp, js::MutableHandleShape propp);
 
-    inline JSBool defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value,
+    inline JSBool defineGeneric(JSContext *cx, js::HandleId id, js::HandleValue value,
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
-    inline JSBool defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
+    inline JSBool defineProperty(JSContext *cx, js::PropertyName *name, js::HandleValue value,
                                  JSPropertyOp getter = JS_PropertyStub,
                                  JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                  unsigned attrs = JSPROP_ENUMERATE);
 
-    inline JSBool defineElement(JSContext *cx, uint32_t index, const js::Value &value,
+    inline JSBool defineElement(JSContext *cx, uint32_t index, js::HandleValue value,
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
-    inline JSBool defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
+    inline JSBool defineSpecial(JSContext *cx, js::SpecialId sid, js::HandleValue value,
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
 
-    inline JSBool getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::Value *vp);
+    inline JSBool getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::MutableHandleValue vp);
     inline JSBool getProperty(JSContext *cx, js::HandleObject receiver, js::PropertyName *name,
-                              js::Value *vp);
-    inline JSBool getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp);
+                              js::MutableHandleValue vp);
+    inline JSBool getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::MutableHandleValue vp);
     /* If element is not present (e.g. array hole) *present is set to
        false and the contents of *vp are unusable garbage. */
     inline JSBool getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t index,
-                                      js::Value *vp, bool *present);
-    inline JSBool getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::Value *vp);
+                                      js::MutableHandleValue vp, bool *present);
+    inline JSBool getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::MutableHandleValue vp);
 
-    inline JSBool getGeneric(JSContext *cx, js::HandleId id, js::Value *vp);
-    inline JSBool getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp);
-    inline JSBool getElement(JSContext *cx, uint32_t index, js::Value *vp);
-    inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp);
+    inline JSBool getGeneric(JSContext *cx, js::HandleId id, js::MutableHandleValue vp);
+    inline JSBool getProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleValue vp);
+    inline JSBool getElement(JSContext *cx, uint32_t index, js::MutableHandleValue vp);
+    inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::MutableHandleValue vp);
 
-    inline JSBool setGeneric(JSContext *cx, js::Handle<JSObject*> receiver, js::HandleId id,
-                             js::Value *vp, JSBool strict);
-    inline JSBool setProperty(JSContext *cx, js::Handle<JSObject*> receiver,
-                              js::PropertyName *name, js::Value *vp, JSBool strict);
-    inline JSBool setElement(JSContext *cx, js::Handle<JSObject*> receiver, uint32_t index,
-                             js::Value *vp, JSBool strict);
-    inline JSBool setSpecial(JSContext *cx, js::Handle<JSObject*> receiver, js::SpecialId sid,
-                             js::Value *vp, JSBool strict);
+    inline JSBool setGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id,
+                             js::MutableHandleValue vp, JSBool strict);
+    inline JSBool setProperty(JSContext *cx, js::HandleObject receiver,
+                              js::PropertyName *name, js::MutableHandleValue vp, JSBool strict);
+    inline JSBool setElement(JSContext *cx, js::HandleObject receiver, uint32_t index,
+                             js::MutableHandleValue vp, JSBool strict);
+    inline JSBool setSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid,
+                             js::MutableHandleValue vp, JSBool strict);
 
-    JSBool nonNativeSetProperty(JSContext *cx, js::HandleId id, js::Value *vp, JSBool strict);
-    JSBool nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict);
+    JSBool nonNativeSetProperty(JSContext *cx, js::HandleId id, js::MutableHandleValue vp, JSBool strict);
+    JSBool nonNativeSetElement(JSContext *cx, uint32_t index, js::MutableHandleValue vp, JSBool strict);
 
     inline JSBool getGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp);
     inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
     inline JSBool getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
     inline JSBool getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
 
     inline JSBool setGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp);
     inline JSBool setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
     inline JSBool setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
     inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
 
-    inline bool deleteProperty(JSContext *cx, js::HandlePropertyName name, js::Value *rval, bool strict);
-    inline bool deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict);
-    inline bool deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::Value *rval, bool strict);
-    bool deleteByValue(JSContext *cx, const js::Value &property, js::Value *rval, bool strict);
+    inline bool deleteProperty(JSContext *cx, js::HandlePropertyName name, js::MutableHandleValue rval, bool strict);
+    inline bool deleteElement(JSContext *cx, uint32_t index, js::MutableHandleValue rval, bool strict);
+    inline bool deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::MutableHandleValue rval, bool strict);
+    bool deleteByValue(JSContext *cx, const js::Value &property, js::MutableHandleValue rval, bool strict);
 
     inline bool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp);
-    inline bool defaultValue(JSContext *cx, JSType hint, js::Value *vp);
+    inline bool defaultValue(JSContext *cx, JSType hint, js::MutableHandleValue vp);
     inline JSType typeOf(JSContext *cx);
     inline JSObject *thisObject(JSContext *cx);
 
     static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
 
     bool swap(JSContext *cx, JSObject *other);
 
     inline void initArrayClass();
@@ -1162,22 +1163,22 @@ const unsigned DNP_UNQUALIFIED  = 4;   /
                                        the defineHow argument of
                                        js_SetPropertyHelper. */
 const unsigned DNP_SKIP_TYPE    = 8;   /* Don't update type information */
 
 /*
  * Return successfully added or changed shape or NULL on error.
  */
 extern Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value,
+DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow = 0);
 
 inline Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const Value &value,
+DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow = 0)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, flags,
                                 shortid, defineHow);
 }
 
@@ -1262,38 +1263,39 @@ js_NativeGet(JSContext *cx, js::Handle<J
 
 extern JSBool
 js_NativeSet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> receiver,
              js::Shape *shape, bool added, bool strict, js::Value *vp);
 
 namespace js {
 
 bool
-GetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, uint32_t getHow, Value *vp);
+GetPropertyHelper(JSContext *cx, HandleObject obj, HandleId id, uint32_t getHow, MutableHandleValue vp);
 
 inline bool
-GetPropertyHelper(JSContext *cx, HandleObject obj, PropertyName *name, uint32_t getHow, Value *vp)
+GetPropertyHelper(JSContext *cx, HandleObject obj, PropertyName *name, uint32_t getHow, MutableHandleValue vp)
 {
-    return GetPropertyHelper(cx, obj, NameToId(name), getHow, vp);
+    RootedId id(cx, NameToId(name));
+    return GetPropertyHelper(cx, obj, id, getHow, vp);
 }
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyDescriptor *desc);
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
 
 bool
 NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp);
 
 extern JSBool
-GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, Value *vp);
+GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, MutableHandleValue vp);
 
 inline bool
-GetMethod(JSContext *cx, HandleObject obj, PropertyName *name, unsigned getHow, Value *vp)
+GetMethod(JSContext *cx, HandleObject obj, PropertyName *name, unsigned getHow, MutableHandleValue vp)
 {
     Rooted<jsid> id(cx, NameToId(name));
     return GetMethod(cx, obj, id, getHow, vp);
 }
 
 /*
  * If obj has an already-resolved data property for id, return true and
  * store the property value in *vp.
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -56,27 +56,27 @@ inline bool
 JSObject::enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp)
 {
     JSNewEnumerateOp op = getOps()->enumerate;
     js::Rooted<JSObject*> obj(cx, this);
     return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp);
 }
 
 inline bool
-JSObject::defaultValue(JSContext *cx, JSType hint, js::Value *vp)
+JSObject::defaultValue(JSContext *cx, JSType hint, js::MutableHandleValue vp)
 {
     js::RootedObject self(cx, this);
 
     JSConvertOp op = getClass()->convert;
     bool ok;
     if (op == JS_ConvertStub)
         ok = js::DefaultValue(cx, self, hint, vp);
     else
         ok = op(cx, self, hint, vp);
-    JS_ASSERT_IF(ok, vp->isPrimitive());
+    JS_ASSERT_IF(ok, vp.isPrimitive());
     return ok;
 }
 
 inline JSType
 JSObject::typeOf(JSContext *cx)
 {
     js::TypeOfOp op = getOps()->typeOf;
     js::Rooted<JSObject*> obj(cx, this);
@@ -87,45 +87,45 @@ inline JSObject *
 JSObject::thisObject(JSContext *cx)
 {
     JSObjectOp op = getOps()->thisObject;
     js::Rooted<JSObject*> obj(cx, this);
     return op ? op(cx, obj) : this;
 }
 
 inline JSBool
-JSObject::setGeneric(JSContext *cx, js::Handle<JSObject*> receiver, js::HandleId id, js::Value *vp,
+JSObject::setGeneric(JSContext *cx, js::Handle<JSObject*> receiver, js::HandleId id, js::MutableHandleValue vp,
                      JSBool strict)
 {
     if (getOps()->setGeneric)
         return nonNativeSetProperty(cx, id, vp, strict);
     js::Rooted<JSObject*> obj(cx, this);
     return js::baseops::SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict);
 }
 
 inline JSBool
 JSObject::setProperty(JSContext *cx, js::Handle<JSObject*> receiver, js::PropertyName *name,
-                      js::Value *vp, JSBool strict)
+                      js::MutableHandleValue vp, JSBool strict)
 {
     js::Rooted<jsid> id(cx, js::NameToId(name));
     return setGeneric(cx, receiver, id, vp, strict);
 }
 
 inline JSBool
-JSObject::setElement(JSContext *cx, js::Handle<JSObject*> receiver, uint32_t index, js::Value *vp,
+JSObject::setElement(JSContext *cx, js::Handle<JSObject*> receiver, uint32_t index, js::MutableHandleValue vp,
                      JSBool strict)
 {
     if (getOps()->setElement)
         return nonNativeSetElement(cx, index, vp, strict);
     js::Rooted<JSObject*> obj(cx, this);
     return js::baseops::SetElementHelper(cx, obj, receiver, index, 0, vp, strict);
 }
 
 inline JSBool
-JSObject::setSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::Value *vp,
+JSObject::setSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::MutableHandleValue vp,
                      JSBool strict)
 {
     js::Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return setGeneric(cx, receiver, id, vp, strict);
 }
 
 inline JSBool
 JSObject::setGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp)
@@ -160,79 +160,79 @@ JSObject::setSpecialAttributes(JSContext
 
 inline bool
 JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs)
 {
     return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter());
 }
 
 inline JSBool
-JSObject::getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::Value *vp)
+JSObject::getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::MutableHandleValue vp)
 {
     js::RootedObject self(cx, this);
 
     js::GenericIdOp op = getOps()->getGeneric;
     if (op) {
         if (!op(cx, self, receiver, id, vp))
             return false;
     } else {
         if (!js::baseops::GetProperty(cx, self, receiver, id, vp))
             return false;
     }
     return true;
 }
 
 inline JSBool
-JSObject::getProperty(JSContext *cx, js::HandleObject receiver, js::PropertyName *name, js::Value *vp)
+JSObject::getProperty(JSContext *cx, js::HandleObject receiver, js::PropertyName *name, js::MutableHandleValue vp)
 {
     js::Rooted<jsid> id(cx, js::NameToId(name));
     return getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
-JSObject::getGeneric(JSContext *cx, js::HandleId id, js::Value *vp)
+JSObject::getGeneric(JSContext *cx, js::HandleId id, js::MutableHandleValue vp)
 {
     js::Rooted<JSObject*> obj(cx, this);
     return getGeneric(cx, obj, id, vp);
 }
 
 inline JSBool
-JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp)
+JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::MutableHandleValue vp)
 {
     js::Rooted<jsid> id(cx, js::NameToId(name));
     return getGeneric(cx, id, vp);
 }
 
 inline bool
-JSObject::deleteProperty(JSContext *cx, js::HandlePropertyName name, js::Value *rval, bool strict)
+JSObject::deleteProperty(JSContext *cx, js::HandlePropertyName name, js::MutableHandleValue rval, bool strict)
 {
     jsid id = js::NameToId(name);
     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::DeletePropertyOp op = getOps()->deleteProperty;
     js::Rooted<JSObject*> obj(cx, this);
     return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, rval, strict);
 }
 
 inline bool
-JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict)
+JSObject::deleteElement(JSContext *cx, uint32_t index, js::MutableHandleValue rval, bool strict)
 {
     js::RootedObject self(cx, this);
 
     jsid id;
     if (!js::IndexToId(cx, index, &id))
         return false;
     js::types::AddTypePropertyId(cx, self, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, self, id);
     js::DeleteElementOp op = self->getOps()->deleteElement;
     return (op ? op : js::baseops::DeleteElement)(cx, self, index, rval, strict);
 }
 
 inline bool
-JSObject::deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::Value *rval, bool strict)
+JSObject::deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::MutableHandleValue rval, bool strict)
 {
     jsid id = SPECIALID_TO_JSID(sid);
     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::DeleteSpecialOp op = getOps()->deleteSpecial;
     js::Rooted<JSObject*> obj(cx, this);
     return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, rval, strict);
 }
@@ -1051,52 +1051,52 @@ inline JSBool
 JSObject::lookupProperty(JSContext *cx, js::PropertyName *name,
                          js::MutableHandleObject objp, js::MutableHandleShape propp)
 {
     js::Rooted<jsid> id(cx, js::NameToId(name));
     return lookupGeneric(cx, id, objp, propp);
 }
 
 inline JSBool
-JSObject::defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value,
+JSObject::defineGeneric(JSContext *cx, js::HandleId id, js::HandleValue value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
     js::RootedObject self(cx, this);
 
     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
     js::DefineGenericOp op = getOps()->defineGeneric;
-    return (op ? op : js::baseops::DefineGeneric)(cx, self, id, &value, getter, setter, attrs);
+    return (op ? op : js::baseops::DefineGeneric)(cx, self, id, value, getter, setter, attrs);
 }
 
 inline JSBool
-JSObject::defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
+JSObject::defineProperty(JSContext *cx, js::PropertyName *name, js::HandleValue value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
     js::Rooted<jsid> id(cx, js::NameToId(name));
     return defineGeneric(cx, id, value, getter, setter, attrs);
 }
 
 inline JSBool
-JSObject::defineElement(JSContext *cx, uint32_t index, const js::Value &value,
+JSObject::defineElement(JSContext *cx, uint32_t index, js::HandleValue value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
     js::RootedObject self(cx, this);
 
     js::DefineElementOp op = getOps()->defineElement;
-    return (op ? op : js::baseops::DefineElement)(cx, self, index, &value, getter, setter, attrs);
+    return (op ? op : js::baseops::DefineElement)(cx, self, index, value, getter, setter, attrs);
 }
 
 inline JSBool
-JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
+JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, js::HandleValue value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
     js::Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return defineGeneric(cx, id, value, getter, setter, attrs);
 }
 
@@ -1114,39 +1114,39 @@ inline JSBool
 JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid,
                         js::MutableHandleObject objp, js::MutableHandleShape propp)
 {
     js::Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return lookupGeneric(cx, id, objp, propp);
 }
 
 inline JSBool
-JSObject::getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp)
+JSObject::getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::MutableHandleValue vp)
 {
     js::RootedObject self(cx, this);
 
     js::ElementIdOp op = getOps()->getElement;
     if (op)
         return op(cx, self, receiver, index, vp);
 
     js::RootedId id(cx);
     if (!js::IndexToId(cx, index, id.address()))
         return false;
     return self->getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
-JSObject::getElement(JSContext *cx, uint32_t index, js::Value *vp)
+JSObject::getElement(JSContext *cx, uint32_t index, js::MutableHandleValue vp)
 {
     js::Rooted<JSObject*> obj(cx, this);
     return getElement(cx, obj, index, vp);
 }
 
 inline JSBool
-JSObject::getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp,
+JSObject::getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t index, js::MutableHandleValue vp,
                               bool *present)
 {
     js::RootedObject self(cx, this);
 
     js::ElementIfPresentOp op = getOps()->getElementIfPresent;
     if (op)
         return op(cx, self, receiver, index, vp, present);
 
@@ -1161,26 +1161,25 @@ JSObject::getElementIfPresent(JSContext 
 
     js::RootedObject obj2(cx);
     js::RootedShape prop(cx);
     if (!self->lookupGeneric(cx, id, &obj2, &prop))
         return false;
 
     if (!prop) {
         *present = false;
-        js::Debug_SetValueRangeToCrashOnTouch(vp, 1);
         return true;
     }
 
     *present = true;
     return self->getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
-JSObject::getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::Value *vp)
+JSObject::getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::MutableHandleValue vp)
 {
     js::Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
 JSObject::getGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp)
 {
@@ -1306,27 +1305,35 @@ IsStopIteration(const js::Value &v)
 }
 
 /* ES5 9.1 ToPrimitive(input). */
 static JS_ALWAYS_INLINE bool
 ToPrimitive(JSContext *cx, Value *vp)
 {
     if (vp->isPrimitive())
         return true;
-    return vp->toObject().defaultValue(cx, JSTYPE_VOID, vp);
+    RootedValue value(cx, *vp);
+    if (!vp->toObject().defaultValue(cx, JSTYPE_VOID, &value))
+        return false;
+    *vp = value;
+    return true;
 }
 
 /* ES5 9.1 ToPrimitive(input, PreferredType). */
 static JS_ALWAYS_INLINE bool
 ToPrimitive(JSContext *cx, JSType preferredType, Value *vp)
 {
     JS_ASSERT(preferredType != JSTYPE_VOID); /* Use the other ToPrimitive! */
     if (vp->isPrimitive())
         return true;
-    return vp->toObject().defaultValue(cx, preferredType, vp);
+    RootedValue value(cx, *vp);
+    if (!vp->toObject().defaultValue(cx, preferredType, &value))
+        return false;
+    *vp = value;
+    return true;
 }
 
 /*
  * Return true if this is a compiler-created internal function accessed by
  * its own object. Such a function object must not be accessible to script
  * or embedding code.
  */
 inline bool
@@ -1646,31 +1653,31 @@ inline bool
 IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
 {
     if (!v.isObject())
         return false;
     return ObjectClassIs(v.toObject(), classValue, cx);
 }
 
 static JS_ALWAYS_INLINE bool
-ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
+ValueIsSpecial(JSObject *obj, MutableHandleValue propval, SpecialId *sidp, JSContext *cx)
 {
 #if JS_HAS_XML_SUPPORT
-    if (!propval->isObject())
+    if (!propval.isObject())
         return false;
 
     if (obj->isXML()) {
-        *sidp = SpecialId(propval->toObject());
+        *sidp = SpecialId(propval.toObject());
         return true;
     }
 
-    JSObject &propobj = propval->toObject();
+    JSObject &propobj = propval.toObject();
     JSAtom *name;
     if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) {
-        propval->setString(name);
+        propval.setString(name);
         return false;
     }
 #endif
 
     return false;
 }
 
 JSObject *
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -51,34 +51,36 @@ Class js::JSONClass = {
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 /* ES5 15.12.2. */
 JSBool
 js_json_parse(JSContext *cx, unsigned argc, Value *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     /* Step 1. */
     JSLinearString *linear;
     if (argc >= 1) {
-        JSString *str = ToString(cx, vp[2]);
+        JSString *str = ToString(cx, args[0]);
         if (!str)
             return false;
         linear = str->ensureLinear(cx);
         if (!linear)
             return false;
     } else {
         linear = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
     }
     JS::Anchor<JSString *> anchor(linear);
 
-    Value reviver = (argc >= 2) ? vp[3] : UndefinedValue();
+    RootedValue reviver(cx, (argc >= 2) ? args[1] : UndefinedValue());
 
     /* Steps 2-5. */
-    return ParseJSONWithReviver(cx, linear->chars(), linear->length(), reviver, vp);
+    return ParseJSONWithReviver(cx, linear->chars(), linear->length(), reviver, args.rval());
 }
 
 /* ES5 15.12.3. */
 JSBool
 js_json_stringify(JSContext *cx, unsigned argc, Value *vp)
 {
     RootedObject replacer(cx, (argc >= 2 && vp[3].isObject())
                               ? &vp[3].toObject()
@@ -273,17 +275,17 @@ class KeyStringifier<jsid> {
 template<typename KeyType>
 static bool
 PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, MutableHandleValue vp, StringifyContext *scx)
 {
     JSString *keyStr = NULL;
 
     /* Step 2. */
     if (vp.get().isObject()) {
-        Value toJSON;
+        RootedValue toJSON(cx);
         RootedId id(cx, NameToId(cx->runtime->atomState.toJSONAtom));
         Rooted<JSObject*> obj(cx, &vp.get().toObject());
         if (!GetMethod(cx, obj, id, 0, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = KeyStringifier<KeyType>::toString(cx, key);
             if (!keyStr)
@@ -408,17 +410,17 @@ JO(JSContext *cx, HandleObject obj, Stri
          * Steps 8a-8b.  Note that the call to Str is broken up into 1) getting
          * the property; 2) processing for toJSON, calling the replacer, and
          * handling boxed Number/String/Boolean objects; 3) filtering out
          * values which process to |undefined|, and 4) stringifying all values
          * which pass the filter.
          */
         id = propertyList[i];
         RootedValue outputValue(cx);
-        if (!obj->getGeneric(cx, id, outputValue.address()))
+        if (!obj->getGeneric(cx, id, &outputValue))
             return false;
         if (!PreprocessValue(cx, obj, id.get(), &outputValue, scx))
             return false;
         if (IsFilteredValue(outputValue))
             continue;
 
         /* Output a comma unless this is the first member to write. */
         if (wroteMember && !scx->sb.append(','))
@@ -484,17 +486,17 @@ JA(JSContext *cx, HandleObject obj, Stri
         RootedValue outputValue(cx);
         for (uint32_t i = 0; i < length; i++) {
             /*
              * Steps 8a-8c.  Again note how the call to the spec's Str method
              * is broken up into getting the property, running it past toJSON
              * and the replacer and maybe unboxing, and interpreting some
              * values as |null| in separate steps.
              */
-            if (!obj->getElement(cx, i, outputValue.address()))
+            if (!obj->getElement(cx, i, &outputValue))
                 return JS_FALSE;
             if (!PreprocessValue(cx, obj, i, &outputValue, scx))
                 return JS_FALSE;
             if (IsFilteredValue(outputValue)) {
                 if (!scx->sb.append("null"))
                     return JS_FALSE;
             } else {
                 if (!Str(cx, outputValue, scx))
@@ -632,19 +634,19 @@ js_Stringify(JSContext *cx, MutableHandl
             HashSet<jsid> idSet(cx);
             if (!idSet.init(len))
                 return false;
 
             /* Step 4b(iii). */
             uint32_t i = 0;
 
             /* Step 4b(iv). */
+            RootedValue v(cx);
             for (; i < len; i++) {
                 /* Step 4b(iv)(2). */
-                Value v;
                 if (!replacer->getElement(cx, i, &v))
                     return false;
 
                 jsid id;
                 if (v.isNumber()) {
                     /* Step 4b(iv)(4). */
                     int32_t n;
                     if (v.isNumber() && ValueFitsInInt32(v, &n) && INT_FITS_IN_JSID(n)) {
@@ -740,43 +742,43 @@ js_Stringify(JSContext *cx, MutableHandl
     if (IsFilteredValue(vp))
         return true;
 
     return Str(cx, vp, &scx);
 }
 
 /* ES5 15.12.2 Walk. */
 static bool
-Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, Value *vp)
+Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     /* Step 1. */
-    Value val;
+    RootedValue val(cx);
     if (!holder->getGeneric(cx, name, &val))
         return false;
 
     /* Step 2. */
     if (val.isObject()) {
         RootedObject obj(cx, &val.toObject());
 
         /* 'val' must have been produced by the JSON parser, so not a proxy. */
         JS_ASSERT(!obj->isProxy());
         if (obj->isArray()) {
             /* Step 2a(ii). */
             uint32_t length = obj->getArrayLength();
 
             /* Step 2a(i), 2a(iii-iv). */
             RootedId id(cx);
+            RootedValue newElement(cx);
             for (uint32_t i = 0; i < length; i++) {
                 if (!IndexToId(cx, i, id.address()))
                     return false;
 
                 /* Step 2a(iii)(1). */
-                Value newElement;
                 if (!Walk(cx, obj, id, reviver, &newElement))
                     return false;
 
                 /*
                  * Arrays which begin empty and whose properties are always
                  * incrementally appended are always dense, no matter their
                  * length, under current dense/slow array heuristics.
                  * Also, deleting a property from a dense array which is not
@@ -786,31 +788,31 @@ Walk(JSContext *cx, HandleObject holder,
                  * property definition and deletion will always succeed,
                  * and we need not check for failure.
                  */
                 if (newElement.isUndefined()) {
                     /* Step 2a(iii)(2). */
                     JS_ALWAYS_TRUE(array_deleteElement(cx, obj, i, &newElement, false));
                 } else {
                     /* Step 2a(iii)(3). */
-                    JS_ALWAYS_TRUE(array_defineElement(cx, obj, i, &newElement, JS_PropertyStub,
+                    JS_ALWAYS_TRUE(array_defineElement(cx, obj, i, newElement, JS_PropertyStub,
                                                        JS_StrictPropertyStub, JSPROP_ENUMERATE));
                 }
             }
         } else {
             /* Step 2b(i). */
             AutoIdVector keys(cx);
             if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &keys))
                 return false;
 
             /* Step 2b(ii). */
             RootedId id(cx);
+            RootedValue newElement(cx);
             for (size_t i = 0, len = keys.length(); i < len; i++) {
                 /* Step 2b(ii)(1). */
-                Value newElement;
                 id = keys[i];
                 if (!Walk(cx, obj, id, reviver, &newElement))
                     return false;
 
                 if (newElement.isUndefined()) {
                     /* Step 2b(ii)(2). */
                     if (!obj->deleteByValue(cx, IdToValue(id), &newElement, false))
                         return false;
@@ -838,39 +840,39 @@ Walk(JSContext *cx, HandleObject holder,
 
     args.calleev() = reviver;
     args.thisv() = ObjectValue(*holder);
     args[0] = StringValue(key);
     args[1] = val;
 
     if (!Invoke(cx, args))
         return false;
-    *vp = args.rval();
+    vp.set(args.rval());
     return true;
 }
 
 static bool
-Revive(JSContext *cx, const Value &reviver, Value *vp)
+Revive(JSContext *cx, const Value &reviver, MutableHandleValue vp)
 {
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!obj)
         return false;
 
-    if (!obj->defineProperty(cx, cx->runtime->atomState.emptyAtom, *vp))
+    if (!obj->defineProperty(cx, cx->runtime->atomState.emptyAtom, vp))
         return false;
 
     Rooted<jsid> id(cx, NameToId(cx->runtime->atomState.emptyAtom));
     return Walk(cx, obj, id, reviver, vp);
 }
 
 namespace js {
 
 JSBool
-ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Value &reviver,
-                     Value *vp, DecodingMode decodingMode /* = STRICT */)
+ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, HandleValue reviver,
+                     MutableHandleValue vp, DecodingMode decodingMode /* = STRICT */)
 {
     /* 15.12.2 steps 2-3. */
     JSONParser parser(cx, chars, length,
                       decodingMode == STRICT ? JSONParser::StrictJSON : JSONParser::LegacyJSON);
     if (!parser.parse(vp))
         return false;
 
     /* 15.12.2 steps 4-5. */
--- a/js/src/json.h
+++ b/js/src/json.h
@@ -32,14 +32,14 @@ js_Stringify(JSContext *cx, js::MutableH
  * omitted.)  New users should use strict decoding rather than legacy decoding,
  * as legacy decoding might be removed at a future time.
  */
 enum DecodingMode { STRICT, LEGACY };
 
 namespace js {
 
 extern JS_FRIEND_API(JSBool)
-ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Value &filter,
-                     Value *vp, DecodingMode decodingMode = STRICT);
+ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, HandleValue filter,
+                     MutableHandleValue vp, DecodingMode decodingMode = STRICT);
 
 } /* namespace js */
 
 #endif /* json_h___ */
--- a/js/src/jsonparser.cpp
+++ b/js/src/jsonparser.cpp
@@ -483,29 +483,29 @@ JSONParser::advanceAfterProperty()
 
 /*
  * This enum is local