Bug 860311 - GC: More rooting in XPConnect r=bholley
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 09 Apr 2013 16:42:21 +0100
changeset 128576 e2344b2249db0610878f276a393175fc9eb3fd30
parent 128575 a409636a0f32d89e16290d0692c61f78945245d0
child 128577 4eef306e01569ddb07017c71115879397be317f0
push id24532
push userryanvm@gmail.com
push dateFri, 12 Apr 2013 19:06:49 +0000
treeherdermozilla-central@2aff2d574a1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs860311
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 860311 - GC: More rooting in XPConnect r=bholley
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeInfo.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -824,33 +824,33 @@ XPCConvert::NativeInterface2JSObject(XPC
     // Note: If |cache->IsProxy()| is true, then it means that the object
     // implementing it doesn't want a wrapped native as its JS Object, but
     // instead it provides its own proxy object. In that case, the object
     // to use is found as cache->GetWrapper(). If that is null, then the
     // object will create (and fill the cache) from its WrapObject call.
     nsWrapperCache *cache = aHelper.GetWrapperCache();
 
     bool tryConstructSlimWrapper = false;
-    JSObject *flat;
+    JS::RootedObject flat(cx);
     if (cache) {
         flat = cache->GetWrapper();
         if (cache->IsDOMBinding()) {
             XPCCallContext &ccx = lccx.GetXPCCallContext();
             if (!ccx.IsValid())
                 return false;
 
             if (!flat) {
                 flat = cache->WrapObject(lccx.GetJSContext(),
                                          xpcscope->GetGlobalJSObject());
                 if (!flat)
                     return false;
             }
 
             if (flat) {
-                if (allowNativeWrapper && !JS_WrapObject(ccx, &flat))
+                if (allowNativeWrapper && !JS_WrapObject(ccx, flat.address()))
                     return false;
 
                 return CreateHolderIfNeeded(ccx, flat, d, dest);
             }
         }
 
         if (!dest) {
             if (!flat) {
@@ -970,17 +970,17 @@ XPCConvert::NativeInterface2JSObject(XPC
         if (pErr)
             *pErr = NS_OK;
         return true;
     }
 
     // The call to wrap here handles both cross-compartment and same-compartment
     // security wrappers.
     JSObject *original = flat;
-    if (!JS_WrapObject(ccx, &flat))
+    if (!JS_WrapObject(ccx, flat.address()))
         return false;
 
     *d = OBJECT_TO_JSVAL(flat);
 
     if (dest) {
         // The strongWrapper still holds the original flat object.
         if (flat == original) {
             *dest = strongWrapper.forget().get();
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -489,17 +489,17 @@ nsJSIID::HasInstance(nsIXPConnectWrapped
                      JSContext * cx, JSObject * obj,
                      const jsval &val, bool *bp, bool *_retval)
 {
     *bp = false;
     nsresult rv = NS_OK;
 
     if (!JSVAL_IS_PRIMITIVE(val)) {
         // we have a JSObject
-        JSObject* obj = JSVAL_TO_OBJECT(val);
+        JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
 
         NS_ASSERTION(obj, "when is an object not an object?");
 
         nsISupports *identity = nullptr;
         // is this really a native xpcom object with a wrapper?
         const nsIID* iid;
         mInfo->GetIIDShared(&iid);
 
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -24,16 +24,17 @@
 #include "mozilla/StandardInteger.h"
 #include "mozilla/Util.h"
 #include "mozilla/Likely.h"
 #include <algorithm>
 
 using namespace xpc;
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace JS;
 
 bool
 xpc_OkToHandOutWrapper(nsWrapperCache *cache)
 {
     NS_ABORT_IF_FALSE(cache->GetWrapper(), "Must have wrapper");
     NS_ABORT_IF_FALSE(IS_WN_WRAPPER(cache->GetWrapper()),
                       "Must have XPCWrappedNative wrapper");
     return
@@ -279,17 +280,17 @@ FinishCreate(XPCCallContext& ccx,
 // XPCConvert::NativeInterface2JSObject, XPCWrappedNative::GetNewOrUsed,
 // and finally into XPCWrappedNative::Init. Unfortunately, this path assumes
 // very early on that we have an XPCWrappedNativeScope and corresponding global
 // JS object, which are the very things we need to create here. So we special-
 // case the logic and do some things in a different order.
 nsresult
 XPCWrappedNative::WrapNewGlobal(XPCCallContext &ccx, xpcObjectHelper &nativeHelper,
                                 nsIPrincipal *principal, bool initStandardClasses,
-                                JS::ZoneSpecifier zoneSpec,
+                                ZoneSpecifier zoneSpec,
                                 XPCWrappedNative **wrappedGlobal)
 {
     nsISupports *identity = nativeHelper.GetCanonical();
 
     // The object should specify that it's meant to be global.
     MOZ_ASSERT(nativeHelper.GetScriptableFlags() & nsIXPCScriptable::IS_GLOBAL_OBJECT);
 
     // We shouldn't be reusing globals.
@@ -309,17 +310,17 @@ XPCWrappedNative::WrapNewGlobal(XPCCallC
         si(ccx, XPCNativeScriptableInfo::Construct(ccx, &sciWrapper));
     MOZ_ASSERT(si.get());
 
     // Finally, we get to the JSClass.
     JSClass *clasp = si->GetJSClass();
     MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
     // Create the global.
-    JSObject *global = xpc::CreateGlobalObject(ccx, clasp, principal, zoneSpec);
+    RootedObject global(ccx, xpc::CreateGlobalObject(ccx, clasp, principal, zoneSpec));
     if (!global)
         return NS_ERROR_FAILURE;
     XPCWrappedNativeScope *scope = GetCompartmentPrivate(global)->scope;
 
     // Immediately enter the global's compartment, so that everything else we
     // create ends up there.
     JSAutoCompartment ac(ccx, global);
 
@@ -495,33 +496,33 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
     // are also nsIXPCScriptable helper implementations, but the helper
     // code is obviously intended for the implementation of the class
     // described by the nsIClassInfo, not for the class info object
     // itself.
     const XPCNativeScriptableCreateInfo& sciWrapper =
         isClassInfo ? sci :
         GatherScriptableCreateInfo(identity, info, sciProto, sci);
 
-    JSObject* parent = Scope->GetGlobalJSObject();
+    RootedObject parent(ccx, Scope->GetGlobalJSObject());
 
     jsval newParentVal = JSVAL_NULL;
     XPCMarkableJSVal newParentVal_markable(&newParentVal);
     AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
     JSBool needsSOW = false;
     JSBool needsCOW = false;
 
     mozilla::Maybe<JSAutoCompartment> ac;
 
     if (sciWrapper.GetFlags().WantPreCreate()) {
         // PreCreate may touch dead compartments.
         js::AutoMaybeTouchDeadZones agc(parent);
 
-        JSObject* plannedParent = parent;
+        RootedObject plannedParent(ccx, parent);
         nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
-                                                          parent, &parent);
+                                                          parent, parent.address());
         if (NS_FAILED(rv))
             return rv;
 
         if (rv == NS_SUCCESS_CHROME_ACCESS_ONLY)
             needsSOW = true;
         rv = NS_OK;
 
         NS_ASSERTION(!xpc::WrapperFactory::IsXrayWrapper(parent),
@@ -537,17 +538,17 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
             newParentVal = OBJECT_TO_JSVAL(parent);
         }
 
         // Take the performance hit of checking the hashtable again in case
         // the preCreate call caused the wrapper to get created through some
         // interesting path (the DOM code tends to make this happen sometimes).
 
         if (cache) {
-            JSObject *cached = cache->GetWrapper();
+            RootedObject cached(ccx, cache->GetWrapper());
             if (cached) {
                 if (IS_SLIM_WRAPPER_OBJECT(cached)) {
                     if (NS_FAILED(XPCWrappedNative::Morph(ccx, cached,
                           Interface, cache, getter_AddRefs(wrapper))))
                         return NS_ERROR_FAILURE;
                 } else {
                     wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(cached));
                 }
@@ -567,18 +568,18 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
             return NS_OK;
         }
     } else {
         ac.construct(ccx, parent);
 
         nsISupports *Object = helper.Object();
         if (nsXPCWrappedJSClass::IsWrappedJS(Object)) {
             nsCOMPtr<nsIXPConnectWrappedJS> wrappedjs(do_QueryInterface(Object));
-            JSObject *obj;
-            wrappedjs->GetJSObject(&obj);
+            RootedObject obj(ccx);
+            wrappedjs->GetJSObject(obj.address());
             if (xpc::AccessCheck::isChrome(js::GetObjectCompartment(obj)) &&
                 !xpc::AccessCheck::isChrome(js::GetObjectCompartment(Scope->GetGlobalJSObject()))) {
                 needsCOW = true;
             }
         }
     }
 
     AutoMarkingWrappedNativeProtoPtr proto(ccx);
@@ -731,17 +732,17 @@ FinishCreate(XPCCallContext& ccx,
     DEBUG_CheckClassInfoClaims(wrapper);
     *resultWrapper = wrapper.forget().get();
     return NS_OK;
 }
 
 // static
 nsresult
 XPCWrappedNative::Morph(XPCCallContext& ccx,
-                        JSObject* existingJSObject,
+                        HandleObject existingJSObject,
                         XPCNativeInterface* Interface,
                         nsWrapperCache *cache,
                         XPCWrappedNative** resultWrapper)
 {
     NS_ASSERTION(IS_SLIM_WRAPPER(existingJSObject),
                  "Trying to morph a JSObject that's not a slim wrapper?");
 
     nsISupports *identity =
@@ -803,17 +804,17 @@ XPCWrappedNative::GetUsedOnly(XPCCallCon
                               XPCWrappedNative** resultWrapper)
 {
     NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object");
 
     XPCWrappedNative* wrapper;
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(Object, &cache);
     if (cache) {
-        JSObject *flat = cache->GetWrapper();
+        RootedObject flat(ccx, cache->GetWrapper());
         if (flat && IS_SLIM_WRAPPER_OBJECT(flat) && !MorphSlimWrapper(ccx, flat))
            return NS_ERROR_FAILURE;
 
         wrapper = flat ?
                   static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat)) :
                   nullptr;
 
         if (!wrapper) {
@@ -939,34 +940,34 @@ XPCWrappedNative::Destroy()
 
     /*
      * The only time GetRuntime() will be NULL is if Destroy is called a second
      * time on a wrapped native. Since we already unregistered the pointer the
      * first time, there's no need to unregister again. Unregistration is safe
      * the first time because mWrapperWord isn't used afterwards.
      */
     if (XPCJSRuntime *rt = GetRuntime()) {
-        if (JS::IsIncrementalBarrierNeeded(rt->GetJSRuntime()))
-            JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
+        if (IsIncrementalBarrierNeeded(rt->GetJSRuntime()))
+            IncrementalObjectBarrier(GetWrapperPreserveColor());
         mWrapperWord = WRAPPER_WORD_POISON;
     } else {
         MOZ_ASSERT(mWrapperWord == WRAPPER_WORD_POISON);
     }
 
     mMaybeScope = nullptr;
 }
 
 void
 XPCWrappedNative::UpdateScriptableInfo(XPCNativeScriptableInfo *si)
 {
     NS_ASSERTION(mScriptableInfo, "UpdateScriptableInfo expects an existing scriptable info");
 
     // Write barrier for incremental GC.
     JSRuntime* rt = GetRuntime()->GetJSRuntime();
-    if (JS::IsIncrementalBarrierNeeded(rt))
+    if (IsIncrementalBarrierNeeded(rt))
         mScriptableInfo->Mark();
 
     mScriptableInfo = si;
 }
 
 void
 XPCWrappedNative::SetProto(XPCWrappedNativeProto* p)
 {
@@ -1089,17 +1090,17 @@ XPCWrappedNative::GatherScriptableCreate
     return sciProto;
 }
 
 #ifdef DEBUG_slimwrappers
 static uint32_t sMorphedSlimWrappers;
 #endif
 
 JSBool
-XPCWrappedNative::Init(XPCCallContext& ccx, JSObject* parent,
+XPCWrappedNative::Init(XPCCallContext& ccx, HandleObject parent,
                        const XPCNativeScriptableCreateInfo* sci)
 {
     // setup our scriptable info...
 
     if (sci->GetCallback()) {
         if (HasProto()) {
             XPCNativeScriptableInfo* siProto = GetProto()->GetScriptableInfo();
             if (siProto && siProto->GetCallback() == sci->GetCallback())
@@ -1395,52 +1396,52 @@ XPCWrappedNative::SystemIsBeingShutDown(
     }
 }
 
 /***************************************************************************/
 
 // Dynamically ensure that two objects don't end up with the same private.
 class MOZ_STACK_CLASS AutoClonePrivateGuard {
 public:
-    AutoClonePrivateGuard(JSObject *aOld, JSObject *aNew)
-        : mOldReflector(aOld), mNewReflector(aNew)
+    AutoClonePrivateGuard(JSContext *cx, JSObject *aOld, JSObject *aNew)
+        : mOldReflector(cx, aOld), mNewReflector(cx, aNew)
     {
         MOZ_ASSERT(JS_GetPrivate(aOld) == JS_GetPrivate(aNew));
     }
 
     ~AutoClonePrivateGuard()
     {
         if (JS_GetPrivate(mOldReflector)) {
             JS_SetPrivate(mNewReflector, nullptr);
         }
     }
 
 private:
-    JSObject* mOldReflector;
-    JSObject* mNewReflector;
+    RootedObject mOldReflector;
+    RootedObject mNewReflector;
 };
 
 // static
 nsresult
 XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
                                          XPCWrappedNativeScope* aOldScope,
                                          XPCWrappedNativeScope* aNewScope,
-                                         JSObject* aNewParent,
+                                         HandleObject aNewParent,
                                          nsISupports* aCOMObj)
 {
     XPCNativeInterface* iface =
         XPCNativeInterface::GetISupports(ccx);
 
     if (!iface)
         return NS_ERROR_FAILURE;
 
     nsresult rv;
 
     nsRefPtr<XPCWrappedNative> wrapper;
-    JSObject *flat = nullptr;
+    RootedObject flat(ccx);
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(aCOMObj, &cache);
     if (cache) {
         flat = cache->GetWrapper();
         if (flat && !IS_SLIM_WRAPPER_OBJECT(flat)) {
             wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));
             NS_ASSERTION(wrapper->GetScope() == aOldScope,
                          "Incorrect scope passed");
@@ -1500,32 +1501,32 @@ XPCWrappedNative::ReparentWrapperIfFound
         if (wrapper) {
 
             // First, the clone of the reflector, get a copy of its
             // properties and clone its expando chain. The only part that is
             // dangerous here if we have to return early is that we must avoid
             // ending up with two reflectors pointing to the same WN. Other than
             // that, the objects we create will just go away if we return early.
 
-            JSObject *newobj = JS_CloneObject(ccx, flat,
-                                              newProto->GetJSProtoObject(),
-                                              aNewParent);
+            RootedObject newobj(ccx, JS_CloneObject(ccx, flat,
+                                                    newProto->GetJSProtoObject(),
+                                                    aNewParent));
             if (!newobj)
                 return NS_ERROR_FAILURE;
 
             // At this point, both |flat| and |newobj| point to the same wrapped
             // native, which is bad, because one of them will end up finalizing
             // a wrapped native it does not own. |cloneGuard| ensures that if we
             // exit before calling clearing |flat|'s private the private of
             // |newobj| will be set to NULL. |flat| will go away soon, because
             // we swap it with another object during the transplant and let that
             // object die.
-            JSObject *propertyHolder;
+            RootedObject propertyHolder(ccx);
             {
-                AutoClonePrivateGuard cloneGuard(flat, newobj);
+                AutoClonePrivateGuard cloneGuard(ccx, flat, newobj);
 
                 propertyHolder = JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
                 if (!propertyHolder)
                     return NS_ERROR_OUT_OF_MEMORY;
                 if (!JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
                     return NS_ERROR_FAILURE;
 
                 // Expandos from other compartments are attached to the target JS object.
@@ -1663,31 +1664,31 @@ XPCWrappedNative::ReparentWrapperIfFound
 // So we just leave them behind. In practice, the only time this turns out to
 // be a problem is during subsequent wrapper reparenting. When this happens, we
 // call into the below fixup code at the last minute and straighten things out
 // before proceeding.
 //
 // See bug 751995 for more information.
 
 static nsresult
-RescueOrphans(XPCCallContext& ccx, JSObject* obj)
+RescueOrphans(XPCCallContext& ccx, HandleObject obj)
 {
     //
     // Even if we're not an orphan at the moment, one of our ancestors might
     // be. If so, we need to recursively rescue up the parent chain.
     //
 
     // First, get the parent object. If we're currently an orphan, the parent
     // object is a cross-compartment wrapper. Follow the parent into its own
     // compartment and fix it up there. We'll fix up |this| afterwards.
     //
     // NB: We pass stopAtOuter=false during the unwrap because Location objects
     // are parented to outer window proxies.
     nsresult rv;
-    JSObject *parentObj = js::GetObjectParent(obj);
+    RootedObject parentObj(ccx, js::GetObjectParent(obj));
     if (!parentObj)
         return NS_OK; // Global object. We're done.
     parentObj = js::UncheckedUnwrap(parentObj, /* stopAtOuter = */ false);
 
     // PreCreate may touch dead compartments.
     js::AutoMaybeTouchDeadZones agc(parentObj);
 
     bool isWN = IS_WRAPPER_CLASS(js::GetObjectClass(obj));
@@ -1698,18 +1699,18 @@ RescueOrphans(XPCCallContext& ccx, JSObj
     // in the parent chain, depending on the order of fixup. Because the proxy is
     // nuked, we can't follow it anywhere. But we _can_ find the new wrapper for
     // the underlying native parent.
     if (MOZ_UNLIKELY(JS_IsDeadWrapper(parentObj))) {
         if (isWN) {
             XPCWrappedNative *wn =
                 static_cast<XPCWrappedNative*>(js::GetObjectPrivate(obj));
             rv = wn->GetScriptableInfo()->GetCallback()->PreCreate(wn->GetIdentityObject(), ccx,
-                                                           wn->GetScope()->GetGlobalJSObject(),
-                                                           &parentObj);
+                                                                   wn->GetScope()->GetGlobalJSObject(),
+                                                                   parentObj.address());
             NS_ENSURE_SUCCESS(rv, rv);
         } else {
             MOZ_ASSERT(IsDOMObject(obj));
             const DOMClass* domClass = GetDOMClass(obj);
             parentObj = domClass->mGetParent(ccx, obj);
         }
     }
 
@@ -1725,17 +1726,17 @@ RescueOrphans(XPCCallContext& ccx, JSObj
 
     // Now that we know our parent is in the right place, determine if we've
     // been orphaned. If not, we have nothing to do.
     if (!js::IsCrossCompartmentWrapper(parentObj))
         return NS_OK;
 
     // We've been orphaned. Find where our parent went, and follow it.
     if (isWN) {
-        JSObject *realParent = js::UncheckedUnwrap(parentObj);
+        RootedObject realParent(ccx, js::UncheckedUnwrap(parentObj));
         XPCWrappedNative *wn =
             static_cast<XPCWrappedNative*>(js::GetObjectPrivate(obj));
         return wn->ReparentWrapperIfFound(ccx, GetObjectScope(parentObj),
                                           GetObjectScope(realParent),
                                           realParent, wn->GetIdentityObject());
     }
 
     return ReparentWrapper(ccx, obj);
@@ -1743,17 +1744,18 @@ RescueOrphans(XPCCallContext& ccx, JSObj
 
 // Recursively fix up orphans on the parent chain of a wrapper. Note that this
 // can cause a wrapper to move even if it is not an orphan, since its parent
 // might be an orphan and fixing the parent causes this wrapper to become an
 // orphan.
 nsresult
 XPCWrappedNative::RescueOrphans(XPCCallContext& ccx)
 {
-    return ::RescueOrphans(ccx, mFlatJSObject);
+    RootedObject flatJSObject(ccx, mFlatJSObject);
+    return ::RescueOrphans(ccx, flatJSObject);
 }
 
 JSBool
 XPCWrappedNative::ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface)
 {
     // This is only called while locked (during XPCWrappedNative::FindTearOff).
 
     if (!mSet->HasInterface(aInterface)) {
@@ -1928,18 +1930,18 @@ XPCWrappedNative::InitTearOff(XPCCallCon
         // into an infinite loop.
         // see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725
 
         // The code in this block also does a check for the double wrapped
         // nsIPropertyBag case.
 
         nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(obj));
         if (wrappedJS) {
-            JSObject* jso = nullptr;
-            if (NS_SUCCEEDED(wrappedJS->GetJSObject(&jso)) &&
+            RootedObject jso(ccx);
+            if (NS_SUCCEEDED(wrappedJS->GetJSObject(jso.address())) &&
                 jso == mFlatJSObject) {
                 // The implementing JSObject is the same as ours! Just say OK
                 // without actually extending the set.
                 //
                 // XXX It is a little cheesy to have FindTearOff return an
                 // 'empty' tearoff. But this is the centralized place to do the
                 // QI activities on the underlying object. *And* most caller to
                 // FindTearOff only look for a non-null result and ignore the
@@ -1995,18 +1997,18 @@ XPCWrappedNative::InitTearOff(XPCCallCon
             // then it must implement QueryInterface and not throw an exception
             // when asked for nsIPropertyBag. It need not actually *implement*
             // nsIPropertyBag - xpconnect will do that work.
 
             nsXPCWrappedJSClass* clazz;
             if (iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso &&
                 NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(ccx,*iid,&clazz))&&
                 clazz) {
-                JSObject* answer =
-                    clazz->CallQueryInterfaceOnJSObject(ccx, jso, *iid);
+                RootedObject answer(ccx,
+                    clazz->CallQueryInterfaceOnJSObject(ccx, jso, *iid));
                 NS_RELEASE(clazz);
                 if (!answer) {
                     NS_RELEASE(obj);
                     aTearOff->SetInterface(nullptr);
                     return NS_ERROR_NO_INTERFACE;
                 }
             }
         }
@@ -2059,17 +2061,17 @@ XPCWrappedNative::InitTearOffJSObject(XP
     to->SetJSObject(obj);
     return true;
 }
 
 JSObject*
 XPCWrappedNative::GetSameCompartmentSecurityWrapper(JSContext *cx)
 {
     // Grab the current state of affairs.
-    JSObject *flat = GetFlatJSObject();
+    RootedObject flat(cx, GetFlatJSObject());
     JSObject *wrapper = GetWrapper();
 
     // If we already have a wrapper, it must be what we want.
     if (wrapper)
         return wrapper;
 
     // Chrome callers don't need same-compartment security wrappers.
     JSCompartment *cxCompartment = js::GetContextCompartment(cx);
@@ -2433,18 +2435,18 @@ CallMethodHelper::GatherAndConvertResult
     uint8_t paramCount = mMethodInfo->GetParamCount();
     for (uint8_t i = 0; i < paramCount; i++) {
         const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
         if (!paramInfo.IsOut() && !paramInfo.IsDipper())
             continue;
 
         const nsXPTType& type = paramInfo.GetType();
         nsXPTCVariant* dp = GetDispatchParam(i);
-        jsval v = JSVAL_NULL;
-        AUTO_MARK_JSVAL(mCallContext, &v);
+        RootedValue v(mCallContext, NullValue());
+        AUTO_MARK_JSVAL(mCallContext, v.address());
         uint32_t array_count = 0;
         nsXPTType datum_type;
         bool isArray = type.IsArray();
         bool isSizedString = isArray ?
                 false :
                 type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
                 type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
 
@@ -2465,47 +2467,47 @@ CallMethodHelper::GatherAndConvertResult
         nsID param_iid;
         if (datum_type.IsInterfacePointer() &&
             !GetInterfaceTypeFromParam(i, datum_type, &param_iid))
             return false;
 
         nsresult err;
         if (isArray) {
             XPCLazyCallContext lccx(mCallContext);
-            if (!XPCConvert::NativeArray2JS(lccx, &v, (const void**)&dp->val,
+            if (!XPCConvert::NativeArray2JS(lccx, v.address(), (const void**)&dp->val,
                                             datum_type, &param_iid,
                                             array_count, &err)) {
                 // XXX need exception scheme for arrays to indicate bad element
                 ThrowBadParam(err, i, mCallContext);
                 return false;
             }
         } else if (isSizedString) {
-            if (!XPCConvert::NativeStringWithSize2JS(mCallContext, &v,
+            if (!XPCConvert::NativeStringWithSize2JS(mCallContext, v.address(),
                                                      (const void*)&dp->val,
                                                      datum_type,
                                                      array_count, &err)) {
                 ThrowBadParam(err, i, mCallContext);
                 return false;
             }
         } else {
-            if (!XPCConvert::NativeData2JS(mCallContext, &v, &dp->val, datum_type,
+            if (!XPCConvert::NativeData2JS(mCallContext, v.address(), &dp->val, datum_type,
                                            &param_iid, &err)) {
                 ThrowBadParam(err, i, mCallContext);
                 return false;
             }
         }
 
         if (paramInfo.IsRetval()) {
             mCallContext.SetRetVal(v);
         } else if (i < mArgc) {
             // we actually assured this before doing the invoke
             NS_ASSERTION(mArgv[i].isObject(), "out var is not object");
             if (!JS_SetPropertyById(mCallContext,
                                     &mArgv[i].toObject(),
-                                    mIdxValueId, &v)) {
+                                    mIdxValueId, v.address())) {
                 ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, i, mCallContext);
                 return false;
             }
         } else {
             NS_ASSERTION(paramInfo.IsOptional(),
                          "Expected either enough arguments or an optional argument");
         }
     }
@@ -2518,17 +2520,17 @@ CallMethodHelper::QueryInterfaceFastPath
 {
     NS_ASSERTION(mVTableIndex == 0,
                  "Using the QI fast-path for a method other than QueryInterface");
 
     if (mArgc < 1) {
         Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, mCallContext);
         return false;
     }
-    
+
     if (!mArgv[0].isObject()) {
         ThrowBadParam(NS_ERROR_XPC_BAD_CONVERT_JS, 0, mCallContext);
         return false;
     }
 
     const nsID* iid = xpc_JSObjectToID(mCallContext, &mArgv[0].toObject());
     if (!iid) {
         ThrowBadParam(NS_ERROR_XPC_BAD_CONVERT_JS, 0, mCallContext);
@@ -2541,20 +2543,20 @@ CallMethodHelper::QueryInterfaceFastPath
 
     mCallContext.GetXPCContext()->SetLastResult(invokeResult);
 
     if (NS_FAILED(invokeResult)) {
         ThrowBadResult(invokeResult, mCallContext);
         return false;
     }
 
-    jsval v = JSVAL_NULL;
+    RootedValue v(mCallContext, NullValue());
     nsresult err;
     JSBool success =
-        XPCConvert::NativeData2JS(mCallContext, &v, &qiresult,
+        XPCConvert::NativeData2JS(mCallContext, v.address(), &qiresult,
                                   nsXPTType::T_INTERFACE_IS,
                                   iid, &err);
     NS_IF_RELEASE(qiresult);
 
     if (!success) {
         ThrowBadParam(err, 0, mCallContext);
         return false;
     }
@@ -2675,18 +2677,18 @@ CallMethodHelper::ConvertIndependentPara
     if (!type.IsArithmetic())
         dp->SetValNeedsCleanup();
 
     // Even if there's nothing to convert, we still need to examine the
     // JSObject container for out-params. If it's null or otherwise invalid,
     // we want to know before the call, rather than after.
     //
     // This is a no-op for 'in' params.
-    jsval src;
-    if (!GetOutParamSource(i, &src))
+    RootedValue src(mCallContext);
+    if (!GetOutParamSource(i, src.address()))
         return false;
 
     // All that's left to do is value conversion. Bail early if we don't need
     // to do that.
     if (!paramInfo.IsIn())
         return true;
 
     // We're definitely some variety of 'in' now, so there's something to
@@ -2781,18 +2783,18 @@ CallMethodHelper::ConvertDependentParam(
     if (!datum_type.IsArithmetic())
         dp->SetValNeedsCleanup();
 
     // Even if there's nothing to convert, we still need to examine the
     // JSObject container for out-params. If it's null or otherwise invalid,
     // we want to know before the call, rather than after.
     //
     // This is a no-op for 'in' params.
-    jsval src;
-    if (!GetOutParamSource(i, &src))
+    RootedValue src(mCallContext);
+    if (!GetOutParamSource(i, src.address()))
         return false;
 
     // All that's left to do is value conversion. Bail early if we don't need
     // to do that.
     if (!paramInfo.IsIn())
         return true;
 
     // We're definitely some variety of 'in' now, so there's something to
@@ -3593,17 +3595,17 @@ XPCJSObjectHolder::newHolder(XPCCallCont
     if (!obj) {
         NS_ERROR("bad param");
         return nullptr;
     }
     return new XPCJSObjectHolder(ccx, obj);
 }
 
 JSBool
-MorphSlimWrapper(JSContext *cx, JSObject *obj)
+MorphSlimWrapper(JSContext *cx, HandleObject obj)
 {
     SLIM_LOG(("***** morphing from MorphSlimToWrapper (%p, %p)\n",
               obj, static_cast<nsISupports*>(xpc_GetJSPrivate(obj))));
 
     XPCCallContext ccx(JS_CALLER, cx);
 
     nsISupports* object = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
     nsWrapperCache *cache = nullptr;
@@ -3631,29 +3633,29 @@ ConstructSlimWrapper(XPCCallContext &ccx
         return false;
     }
 
     XPCNativeScriptableFlags flags(classInfoHelper->GetScriptableFlags());
 
     NS_ASSERTION(flags.DontAskInstanceForScriptable(),
                  "Not supported for cached wrappers!");
 
-    JSObject* parent = xpcScope->GetGlobalJSObject();
+    RootedObject parent(ccx, xpcScope->GetGlobalJSObject());
     if (!flags.WantPreCreate()) {
         SLIM_LOG_NOT_CREATED(ccx, identityObj,
                              "scriptable helper has no PreCreate hook");
 
         return false;
     }
 
     // PreCreate may touch dead compartments.
     js::AutoMaybeTouchDeadZones agc(parent);
 
-    JSObject* plannedParent = parent;
-    nsresult rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
+    RootedObject plannedParent(ccx, parent);
+    nsresult rv = classInfoHelper->PreCreate(identityObj, ccx, parent, parent.address());
     if (rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS) {
         SLIM_LOG_NOT_CREATED(ccx, identityObj, "PreCreate hook refused");
 
         return false;
     }
 
     if (!js::IsObjectInContextCompartment(parent, ccx.GetJSContext())) {
         SLIM_LOG_NOT_CREATED(ccx, identityObj, "wrong compartment");
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -3,16 +3,18 @@
 /* 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/. */
 
 /* Manage the shared info about interfaces for use by wrappedNatives. */
 
 #include "xpcprivate.h"
 
+using namespace JS;
+
 /***************************************************************************/
 
 // XPCNativeMember
 
 // static
 JSBool
 XPCNativeMember::GetCallInfo(JSObject* funobj,
                              XPCNativeInterface** pInterface,
@@ -25,45 +27,45 @@ XPCNativeMember::GetCallInfo(JSObject* f
     *pInterface = (XPCNativeInterface*) JSVAL_TO_PRIVATE(ifaceVal);
     *pMember = (XPCNativeMember*) JSVAL_TO_PRIVATE(memberVal);
 
     return true;
 }
 
 JSBool
 XPCNativeMember::NewFunctionObject(XPCCallContext& ccx,
-                                   XPCNativeInterface* iface, JSObject *parent,
+                                   XPCNativeInterface* iface, HandleObject parent,
                                    jsval* pval)
 {
     NS_ASSERTION(!IsConstant(),
                  "Only call this if you're sure this is not a constant!");
 
     return Resolve(ccx, iface, parent, pval);
 }
 
 JSBool
 XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
-                         JSObject *parent, jsval *vp)
+                         HandleObject parent, jsval *vp)
 {
     if (IsConstant()) {
         const nsXPTConstant* constant;
         if (NS_FAILED(iface->GetInterfaceInfo()->GetConstant(mIndex, &constant)))
             return false;
 
         const nsXPTCMiniVariant& mv = *constant->GetValue();
 
         // XXX Big Hack!
         nsXPTCVariant v;
         v.flags = 0;
         v.type = constant->GetType();
         memcpy(&v.val, &mv.val, sizeof(mv.val));
 
-        jsval resultVal;
+        RootedValue resultVal(ccx);
 
-        if (!XPCConvert::NativeData2JS(ccx, &resultVal, &v.val, v.type,
+        if (!XPCConvert::NativeData2JS(ccx, resultVal.address(), &v.val, v.type,
                                        nullptr, nullptr))
             return false;
 
         *vp = resultVal;
 
         return true;
     }
     // else...
@@ -225,19 +227,18 @@ XPCNativeInterface::NewInstance(XPCCallC
 
     int i;
     JSBool failed = false;
     uint16_t constCount;
     uint16_t methodCount;
     uint16_t totalCount;
     uint16_t realTotalCount = 0;
     XPCNativeMember* cur;
-    JSString* str = NULL;
-    jsid name;
-    jsid interfaceName;
+    RootedString str(ccx);
+    RootedId interfaceName(ccx);
 
     // XXX Investigate lazy init? This is a problem given the
     // 'placement new' scheme - we need to at least know how big to make
     // the object. We might do a scan of methods to determine needed size,
     // then make our object, but avoid init'ing *any* members until asked?
     // Find out how often we create these objects w/o really looking at
     // (or using) the members.
 
@@ -285,17 +286,17 @@ XPCNativeInterface::NewInstance(XPCCallC
             continue;
 
         str = JS_InternString(ccx, info->GetName());
         if (!str) {
             NS_ERROR("bad method name");
             failed = true;
             break;
         }
-        name = INTERNED_STRING_TO_JSID(ccx, str);
+        jsid name = INTERNED_STRING_TO_JSID(ccx, str);
 
         if (info->IsSetter()) {
             NS_ASSERTION(realTotalCount,"bad setter");
             // Note: ASSUMES Getter/Setter pairs are next to each other
             // This is a rule of the typelib spec.
             cur = &members[realTotalCount-1];
             NS_ASSERTION(cur->GetName() == name,"bad setter");
             NS_ASSERTION(cur->IsReadOnlyAttribute(),"bad setter");
@@ -322,17 +323,17 @@ XPCNativeInterface::NewInstance(XPCCallC
             }
 
             str = JS_InternString(ccx, constant->GetName());
             if (!str) {
                 NS_ERROR("bad constant name");
                 failed = true;
                 break;
             }
-            name = INTERNED_STRING_TO_JSID(ccx, str);
+            jsid name = INTERNED_STRING_TO_JSID(ccx, str);
 
             // XXX need better way to find dups
             //NS_ASSERTION(!LookupMemberByID(name),"duplicate method/constant name");
 
             cur = &members[realTotalCount++];
             cur->SetName(name);
             cur->SetConstant(i);
         }
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -10,16 +10,18 @@
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "AccessCheck.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
+using namespace JS;
+
 /***************************************************************************/
 
 // All of the exceptions thrown into JS from this file go through here.
 // That makes this a nice place to set a breakpoint.
 
 static JSBool Throw(nsresult errNum, JSContext* cx)
 {
     XPCThrower::Throw(errNum, cx);
@@ -135,55 +137,55 @@ XPC_WN_Shared_ToSource(JSContext *cx, un
 // returning the underlying JSObject) so that JS callers will see what looks
 // Like any other xpcom object - and be limited to use its interfaces.
 //
 // See the comment preceding nsIXPCWrappedJSObjectGetter in nsIXPConnect.idl.
 
 static JSObject*
 GetDoubleWrappedJSObject(XPCCallContext& ccx, XPCWrappedNative* wrapper)
 {
-    JSObject* obj = nullptr;
+    RootedObject obj(ccx);
     nsCOMPtr<nsIXPConnectWrappedJS>
         underware = do_QueryInterface(wrapper->GetIdentityObject());
     if (underware) {
-        JSObject* mainObj = nullptr;
-        if (NS_SUCCEEDED(underware->GetJSObject(&mainObj)) && mainObj) {
-            jsid id = ccx.GetRuntime()->
-                    GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
+        RootedObject mainObj(ccx);
+        if (NS_SUCCEEDED(underware->GetJSObject(mainObj.address())) && mainObj) {
+            RootedId id(ccx, ccx.GetRuntime()->
+                            GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT));
 
             JSAutoCompartment ac(ccx, mainObj);
 
-            jsval val;
-            if (JS_GetPropertyById(ccx, mainObj, id, &val) &&
+            RootedValue val(ccx);
+            if (JS_GetPropertyById(ccx, mainObj, id, val.address()) &&
                 !JSVAL_IS_PRIMITIVE(val)) {
                 obj = JSVAL_TO_OBJECT(val);
             }
         }
     }
     return obj;
 }
 
 // This is the getter native function we use to handle 'wrappedJSObject' for
 // double wrapped JSObjects.
 
 static JSBool
 XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
 {
-    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
     MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
 
-    JSObject* realObject = GetDoubleWrappedJSObject(ccx, wrapper);
+    RootedObject realObject(cx, GetDoubleWrappedJSObject(ccx, wrapper));
     if (!realObject) {
         // This is pretty unexpected at this point. The object originally
         // responded to this get property call and now gives no object.
         // XXX Should this throw something at the caller?
         *vp = JSVAL_NULL;
         return true;
     }
 
@@ -227,28 +229,30 @@ XPC_WN_DoubleWrappedGetter(JSContext *cx
 /*
  * NOTE:
  * We *never* set the tearoff names (e.g. nsIFoo) as JS_ENUMERATE.
  * We *never* set toString or toSource as JS_ENUMERATE.
  */
 
 static JSBool
 DefinePropertyIfFound(XPCCallContext& ccx,
-                      JSObject *obj, jsid id,
+                      HandleObject obj,
+                      HandleId idArg,
                       XPCNativeSet* set,
                       XPCNativeInterface* iface,
                       XPCNativeMember* member,
                       XPCWrappedNativeScope* scope,
                       JSBool reflectToStringAndToSource,
                       XPCWrappedNative* wrapperToReflectInterfaceNames,
                       XPCWrappedNative* wrapperToReflectDoubleWrap,
                       XPCNativeScriptableInfo* scriptableInfo,
                       unsigned propFlags,
                       JSBool* resolved)
 {
+    RootedId id(ccx, idArg);
     XPCJSRuntime* rt = ccx.GetRuntime();
     JSBool found;
     const char* name;
 
     if (set) {
         if (iface)
             found = true;
         else
@@ -286,17 +290,17 @@ DefinePropertyIfFound(XPCCallContext& cc
                 name = rt->GetStringName(XPCJSRuntime::IDX_TO_SOURCE);
                 id   = rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE);
             }
 
             else
                 call = nullptr;
 
             if (call) {
-                JSFunction* fun = JS_NewFunction(ccx, call, 0, 0, obj, name);
+                RootedFunction fun(ccx, JS_NewFunction(ccx, call, 0, 0, obj, name));
                 if (!fun) {
                     JS_ReportOutOfMemory(ccx);
                     return false;
                 }
 
                 AutoResolveName arn(ccx, id);
                 if (resolved)
                     *resolved = true;
@@ -310,17 +314,17 @@ DefinePropertyIfFound(XPCCallContext& cc
         // set. Let's lookup the name and see if it is the name of an
         // interface. Then we'll see if the object actually *does* this
         // interface and add a tearoff as necessary.
 
         if (wrapperToReflectInterfaceNames) {
             JSAutoByteString name;
             AutoMarkingNativeInterfacePtr iface2(ccx);
             XPCWrappedNativeTearOff* to;
-            JSObject* jso;
+            RootedObject jso(ccx);
             nsresult rv = NS_OK;
 
             if (JSID_IS_STRING(id) &&
                 name.encodeLatin1(ccx, JSID_TO_STRING(id)) &&
                 (iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name.ptr()), iface2) &&
                 nullptr != (to = wrapperToReflectInterfaceNames->
                            FindTearOff(ccx, iface2, true, &rv)) &&
                 nullptr != (jso = to->GetJSObject()))
@@ -350,79 +354,79 @@ DefinePropertyIfFound(XPCCallContext& cc
             name = rt->GetStringName(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
 
             fun = JS_NewFunction(ccx, XPC_WN_DoubleWrappedGetter,
                                  0, 0, obj, name);
 
             if (!fun)
                 return false;
 
-            JSObject* funobj = JS_GetFunctionObject(fun);
+            RootedObject funobj(ccx, JS_GetFunctionObject(fun));
             if (!funobj)
                 return false;
 
             propFlags |= JSPROP_GETTER;
             propFlags &= ~JSPROP_ENUMERATE;
 
             AutoResolveName arn(ccx, id);
             if (resolved)
                 *resolved = true;
             return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID,
                                          JS_DATA_TO_FUNC_PTR(JSPropertyOp,
-                                                             funobj),
+                                                             funobj.get()),
                                          nullptr, propFlags);
         }
 
         if (resolved)
             *resolved = false;
         return true;
     }
 
     if (!member) {
         if (wrapperToReflectInterfaceNames) {
             XPCWrappedNativeTearOff* to =
               wrapperToReflectInterfaceNames->FindTearOff(ccx, iface, true);
 
             if (!to)
                 return false;
-            JSObject* jso = to->GetJSObject();
+            RootedObject jso(ccx, to->GetJSObject());
             if (!jso)
                 return false;
 
             AutoResolveName arn(ccx, id);
             if (resolved)
                 *resolved = true;
             return JS_DefinePropertyById(ccx, obj, id, OBJECT_TO_JSVAL(jso),
                                          nullptr, nullptr,
                                          propFlags & ~JSPROP_ENUMERATE);
         }
         if (resolved)
             *resolved = false;
         return true;
     }
 
     if (member->IsConstant()) {
-        jsval val;
+        RootedValue val(ccx);
         AutoResolveName arn(ccx, id);
         if (resolved)
             *resolved = true;
-        return member->GetConstantValue(ccx, iface, &val) &&
+        return member->GetConstantValue(ccx, iface, val.address()) &&
                JS_DefinePropertyById(ccx, obj, id, val, nullptr, nullptr,
                                      propFlags);
     }
 
     if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING) ||
         id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE) ||
         (scriptableInfo &&
          scriptableInfo->GetFlags().DontEnumQueryInterface() &&
          id == rt->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE)))
         propFlags &= ~JSPROP_ENUMERATE;
 
-    jsval funval;
-    if (!member->NewFunctionObject(ccx, iface, obj, &funval))
+    RootedValue funval(ccx);
+    if (!member->NewFunctionObject(ccx, iface, obj, funval.address()))
         return false;
 
     // protect funobj until it is actually attached
     AUTO_MARK_JSVAL(ccx, funval);
 
 #ifdef off_DEBUG_jband
     {
         static int cloneCount = 0;
@@ -726,19 +730,19 @@ XPC_WN_OuterObject(JSContext *cx, JSHand
     if (!wrapper->IsValid()) {
         Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);
 
         return nullptr;
     }
 
     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     if (si && si->GetFlags().WantOuterObject()) {
-        JSObject *newThis;
+        RootedObject newThis(cx);
         nsresult rv =
-            si->GetCallback()->OuterObject(wrapper, cx, obj, &newThis);
+            si->GetCallback()->OuterObject(wrapper, cx, obj, newThis.address());
 
         if (NS_FAILED(rv)) {
             Throw(rv, cx);
 
             return nullptr;
         }
 
         obj = newThis;
@@ -929,17 +933,17 @@ XPC_WN_Helper_CheckAccess(JSContext *cx,
     CheckAccess(wrapper, cx, obj, id, mode, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
 {
     // N.B. we want obj to be the callee, not JS_THIS(cx, vp)
-    JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    RootedObject obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
     XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, JSID_VOID,
                        argc, JS_ARGV(cx, vp), vp);
     if (!ccx.IsValid())
         return false;
 
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
@@ -947,17 +951,17 @@ XPC_WN_Helper_Call(JSContext *cx, unsign
     PRE_HELPER_STUB_NO_SLIM
     Call(wrapper, cx, obj, argc, JS_ARGV(cx, vp), vp, &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
 {
-    JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    RootedObject obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!obj)
         return false;
 
     XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, JSID_VOID,
                        argc, JS_ARGV(cx, vp), vp);
     if (!ccx.IsValid())
         return false;
 
@@ -987,54 +991,54 @@ XPC_WN_Helper_Finalize(js::FreeOp *fop, 
 }
 
 static JSBool
 XPC_WN_Helper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                          JSMutableHandleObject objp)
 {
     nsresult rv = NS_OK;
     bool retval = true;
-    JSObject* obj2FromScriptable = nullptr;
+    RootedObject obj2FromScriptable(cx);
     if (IS_SLIM_WRAPPER(obj)) {
         XPCNativeScriptableInfo *si =
             GetSlimWrapperProto(obj)->GetScriptableInfo();
         if (!si->GetFlags().WantNewResolve())
             return retval;
 
         NS_ASSERTION(si->GetFlags().AllowPropModsToPrototype() &&
                      !si->GetFlags().AllowPropModsDuringResolve(),
                      "We don't support these flags for slim wrappers!");
 
         rv = si->GetCallback()->NewResolve(nullptr, cx, obj, id, flags,
-                                           &obj2FromScriptable, &retval);
+                                           obj2FromScriptable.address(), &retval);
         if (NS_FAILED(rv))
             return Throw(rv, cx);
 
         if (obj2FromScriptable)
             objp.set(obj2FromScriptable);
 
         return retval;
     }
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
-    jsid old = ccx.SetResolveName(id);
+    RootedId old(cx, ccx.SetResolveName(id));
 
     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     if (si && si->GetFlags().WantNewResolve()) {
         XPCWrappedNative* oldResolvingWrapper;
         JSBool allowPropMods = si->GetFlags().AllowPropModsDuringResolve();
 
         if (allowPropMods)
             oldResolvingWrapper = ccx.SetResolvingWrapper(wrapper);
 
         rv = si->GetCallback()->NewResolve(wrapper, cx, obj, id, flags,
-                                           &obj2FromScriptable, &retval);
+                                           obj2FromScriptable.address(), &retval);
 
         if (allowPropMods)
             (void)ccx.SetResolvingWrapper(oldResolvingWrapper);
     }
 
     old = ccx.SetResolveName(old);
     NS_ASSERTION(old == id, "bad nest");
 
@@ -1422,19 +1426,19 @@ FixUpThisIfBroken(JSObject *obj, JSObjec
     }
     return obj;
 }
 
 JSBool
 XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
 {
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
-    JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    RootedObject funobj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
 #ifdef DEBUG_slimwrappers
     {
         JSFunction* fun = funobj->getFunctionPrivate();
         JSString *funid = JS_GetFunctionDisplayId(fun);
         JSAutoByteString bytes;
@@ -1458,19 +1462,19 @@ XPC_WN_CallMethod(JSContext *cx, unsigne
     ccx.SetCallInfo(iface, member, false);
     return XPCWrappedNative::CallMethod(ccx);
 }
 
 JSBool
 XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
 {
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
-    JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    RootedObject funobj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
-    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
 #ifdef DEBUG_slimwrappers
     {
         const char* funname = nullptr;
         JSAutoByteString bytes;
         if (JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1132,17 +1132,17 @@ nsXPConnect::InitClassesWithNewWrappedGl
 nsresult
 xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph)
 {
     nsWrapperCache *cache;
     CallQueryInterface(tomorph, &cache);
     if (!cache)
         return NS_OK;
 
-    JSObject *obj = cache->GetWrapper();
+    JS::RootedObject obj(cx, cache->GetWrapper());
     if (!obj || !IS_SLIM_WRAPPER(obj))
         return NS_OK;
     NS_ENSURE_STATE(MorphSlimWrapper(cx, obj));
     return NS_OK;
 }
 
 static nsresult
 NativeInterface2JSObject(XPCLazyCallContext & lccx,
@@ -1403,18 +1403,19 @@ nsXPConnect::ReparentWrappedNativeIfFoun
     if (!ccx.IsValid())
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     XPCWrappedNativeScope* scope = GetObjectScope(aScope);
     XPCWrappedNativeScope* scope2 = GetObjectScope(aNewParent);
     if (!scope || !scope2)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
+    JS::RootedObject newParent(ccx, aNewParent);
     return XPCWrappedNative::
-        ReparentWrapperIfFound(ccx, scope, scope2, aNewParent,
+        ReparentWrapperIfFound(ccx, scope, scope2, newParent,
                                aCOMObj);
 }
 
 static JSDHashOperator
 MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr,
                       uint32_t number, void *arg)
 {
     nsTArray<nsRefPtr<XPCWrappedNative> > *array =
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1781,20 +1781,20 @@ public:
     jsid   GetName() const {return mName;}
 
     uint16_t GetIndex() const {return mIndex;}
 
     JSBool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
                             jsval* pval)
         {NS_ASSERTION(IsConstant(),
                       "Only call this if you're sure this is a constant!");
-         return Resolve(ccx, iface, nullptr, pval);}
+         return Resolve(ccx, iface, JS::NullPtr(), pval);}
 
     JSBool NewFunctionObject(XPCCallContext& ccx, XPCNativeInterface* iface,
-                             JSObject *parent, jsval* pval);
+                             JS::HandleObject parent, jsval* pval);
 
     JSBool IsMethod() const
         {return 0 != (mFlags & METHOD);}
 
     JSBool IsConstant() const
         {return 0 != (mFlags & CONSTANT);}
 
     JSBool IsAttribute() const
@@ -1822,17 +1822,17 @@ public:
         {NS_ASSERTION(mFlags == GETTER,"bad"); mFlags = GETTER | SETTER_TOO;}
 
     /* default ctor - leave random contents */
     XPCNativeMember()  {MOZ_COUNT_CTOR(XPCNativeMember);}
     ~XPCNativeMember() {MOZ_COUNT_DTOR(XPCNativeMember);}
 
 private:
     JSBool Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
-                   JSObject *parent, jsval *vp);
+                   JS::HandleObject parent, jsval *vp);
 
     enum {
         METHOD      = 0x01,
         CONSTANT    = 0x02,
         GETTER      = 0x04,
         SETTER_TOO  = 0x08
     };
 
@@ -2516,17 +2516,17 @@ private:
     QITableEntry*            mOffsets;
 };
 
 class xpcObjectHelper;
 extern JSBool ConstructSlimWrapper(XPCCallContext &ccx,
                                    xpcObjectHelper &aHelper,
                                    XPCWrappedNativeScope* xpcScope,
                                    jsval *rval);
-extern JSBool MorphSlimWrapper(JSContext *cx, JSObject *obj);
+extern JSBool MorphSlimWrapper(JSContext *cx, JS::HandleObject obj);
 
 /***********************************************/
 // XPCWrappedNativeTearOff represents the info needed to make calls to one
 // interface on the underlying native object of a XPCWrappedNative.
 
 class XPCWrappedNativeTearOff
 {
 public:
@@ -2754,49 +2754,50 @@ public:
     GetNewOrUsed(XPCCallContext& ccx,
                  xpcObjectHelper& helper,
                  XPCWrappedNativeScope* Scope,
                  XPCNativeInterface* Interface,
                  XPCWrappedNative** wrapper);
 
     static nsresult
     Morph(XPCCallContext& ccx,
-          JSObject* existingJSObject,
+          JS::HandleObject existingJSObject,
           XPCNativeInterface* Interface,
           nsWrapperCache *cache,
           XPCWrappedNative** resultWrapper);
 
 public:
     static nsresult
     GetUsedOnly(XPCCallContext& ccx,
                 nsISupports* Object,
                 XPCWrappedNativeScope* Scope,
                 XPCNativeInterface* Interface,
                 XPCWrappedNative** wrapper);
 
     static XPCWrappedNative*
-    GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
+    GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj_)
     {
+        JS::RootedObject obj(cx, obj_);
         obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
         if (!obj)
             return nullptr;
         if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
             return nullptr;
 
         if (IS_SLIM_WRAPPER_OBJECT(obj) && !MorphSlimWrapper(cx, obj))
             return nullptr;
         MOZ_ASSERT(IS_WN_WRAPPER(obj));
         return XPCWrappedNative::Get(obj);
     }
 
     static nsresult
     ReparentWrapperIfFound(XPCCallContext& ccx,
                            XPCWrappedNativeScope* aOldScope,
                            XPCWrappedNativeScope* aNewScope,
-                           JSObject* aNewParent,
+                           JS::HandleObject aNewParent,
                            nsISupports* aCOMObj);
 
     nsresult RescueOrphans(XPCCallContext& ccx);
 
     void FlatJSObjectFinalized();
 
     void SystemIsBeingShutDown();
 
@@ -2958,17 +2959,17 @@ private:
     enum {
         NEEDS_SOW = JS_BIT(0),
         NEEDS_COW = JS_BIT(1),
         FLAG_MASK = JS_BITMASK(3)
     };
 
 private:
 
-    JSBool Init(XPCCallContext& ccx, JSObject* parent, const XPCNativeScriptableCreateInfo* sci);
+    JSBool Init(XPCCallContext& ccx, JS::HandleObject parent, const XPCNativeScriptableCreateInfo* sci);
     JSBool Init(XPCCallContext &ccx, JSObject *existingJSObject);
     JSBool FinishInit(XPCCallContext &ccx);
 
     JSBool ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface);
 
     nsresult InitTearOff(XPCCallContext& ccx,
                          XPCWrappedNativeTearOff* aTearOff,
                          XPCNativeInterface* aInterface,
@@ -3832,36 +3833,36 @@ private:
 };
 
 /***************************************************************************/
 class MOZ_STACK_CLASS AutoResolveName
 {
 public:
     AutoResolveName(XPCCallContext& ccx, jsid name
                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
-          mOld(XPCJSRuntime::Get()->SetResolveName(name))
+          mOld(ccx, XPCJSRuntime::Get()->SetResolveName(name))
 #ifdef DEBUG
-          ,mCheck(name)
+          ,mCheck(ccx, name)
 #endif
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
     ~AutoResolveName()
         {
 #ifdef DEBUG
             jsid old =
 #endif
             XPCJSRuntime::Get()->SetResolveName(mOld);
             NS_ASSERTION(old == mCheck, "Bad Nesting!");
         }
 
 private:
-    jsid mOld;
+    JS::RootedId mOld;
 #ifdef DEBUG
-    jsid mCheck;
+    JS::RootedId mCheck;
 #endif
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /***************************************************************************/
 class XPCMarkableJSVal
 {
 public:
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -119,18 +119,19 @@ WrapperFactory::DoubleWrap(JSContext *cx
     if (flags & WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG) {
         JSAutoCompartment ac(cx, obj);
         return WaiveXray(cx, obj);
     }
     return obj;
 }
 
 JSObject *
-WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags)
+WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj_, unsigned flags)
 {
+    JS::RootedObject obj(cx, obj_);
     // Outerize any raw inner objects at the entry point here, so that we don't
     // have to worry about them for the rest of the wrapping code.
     if (js::IsInnerObject(obj)) {
         JSAutoCompartment ac(cx, obj);
         obj = JS_ObjectToOuterObject(cx, obj);
         NS_ENSURE_TRUE(obj, nullptr);
         // The outerization hook wraps, which means that we can end up with a
         // CCW here if |obj| was a navigated-away-from inner. Strip any CCWs.