Bug 867459: Root toolkit/ r=terrence
authorDavid Zbarsky <dzbarsky@gmail.com>
Wed, 01 May 2013 18:43:53 -0400
changeset 130572 9b1b9e61db7b18f51b5113866cf42a25bf577a02
parent 130571 e1fe36ce89d100ea57b31768b7d0c8b00f2a034c
child 130573 29aa0fd47707864bf9307ca51e5e06b523e128ca
push id1579
push userphilringnalda@gmail.com
push dateSat, 04 May 2013 04:38:04 +0000
treeherderfx-team@a56432a42a41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs867459
milestone23.0a1
Bug 867459: Root toolkit/ r=terrence
toolkit/components/perf/PerfMeasurement.cpp
toolkit/components/places/History.cpp
toolkit/components/places/PlaceInfo.cpp
toolkit/components/startup/nsAppStartup.cpp
toolkit/components/telemetry/Telemetry.cpp
--- a/toolkit/components/perf/PerfMeasurement.cpp
+++ b/toolkit/components/perf/PerfMeasurement.cpp
@@ -36,35 +36,35 @@ Module::~Module()
 #define XPC_MAP_QUOTED_CLASSNAME "Module"
 #define XPC_MAP_WANT_CALL
 #define XPC_MAP_FLAGS nsIXPCScriptable::WANT_CALL
 #include "xpc_map_end.h"
 
 static JSBool
 SealObjectAndPrototype(JSContext* cx, JSObject* parent, const char* name)
 {
-  JS::Value prop;
-  if (!JS_GetProperty(cx, parent, name, &prop))
+  JS::Rooted<JS::Value> prop(cx);
+  if (!JS_GetProperty(cx, parent, name, prop.address()))
     return false;
 
   if (prop.isUndefined()) {
     // Pretend we sealed the object.
     return true;
   }
 
-  JSObject* obj = JSVAL_TO_OBJECT(prop);
-  if (!JS_GetProperty(cx, obj, "prototype", &prop))
+  JS::Rooted<JSObject*> obj(cx, prop.toObjectOrNull());
+  if (!JS_GetProperty(cx, obj, "prototype", prop.address()))
     return false;
 
-  JSObject* prototype = JSVAL_TO_OBJECT(prop);
+  JS::Rooted<JSObject*> prototype(cx, prop.toObjectOrNull());
   return JS_FreezeObject(cx, obj) && JS_FreezeObject(cx, prototype);
 }
 
 static JSBool
-InitAndSealPerfMeasurementClass(JSContext* cx, JSObject* global)
+InitAndSealPerfMeasurementClass(JSContext* cx, JS::Handle<JSObject*> global)
 {
   // Init the PerfMeasurement class
   if (!JS::RegisterPerfMeasurement(cx, global))
     return false;
 
   // Seal up Object, Function, and Array and their prototypes.  (This single
   // object instance is shared amongst everyone who imports the jsperf module.)
   if (!SealObjectAndPrototype(cx, global, "Object") ||
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -223,18 +223,18 @@ namespace {
  *        The name of the property to get the URI from.
  * @return the URI if it exists.
  */
 already_AddRefed<nsIURI>
 GetURIFromJSObject(JSContext* aCtx,
                    JSObject* aObject,
                    const char* aProperty)
 {
-  JS::Value uriVal;
-  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, &uriVal);
+  JS::Rooted<JS::Value> uriVal(aCtx);
+  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, uriVal.address());
   NS_ENSURE_TRUE(rc, nullptr);
 
   if (!JSVAL_IS_PRIMITIVE(uriVal)) {
     nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
     nsCOMPtr<nsIXPConnectWrappedNative> wrappedObj;
     nsresult rv = xpc->GetWrappedNativeOfJSObject(aCtx, JSVAL_TO_OBJECT(uriVal),
                                                   getter_AddRefs(wrappedObj));
@@ -258,18 +258,18 @@ GetURIFromJSObject(JSContext* aCtx,
  *        The string to populate with the value, or set it to void.
  */
 void
 GetStringFromJSObject(JSContext* aCtx,
                       JSObject* aObject,
                       const char* aProperty,
                       nsString& _string)
 {
-  JS::Value val;
-  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, &val);
+  JS::Rooted<JS::Value> val(aCtx);
+  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, val.address());
   if (!rc || JSVAL_IS_VOID(val) ||
       !(JSVAL_IS_NULL(val) || JSVAL_IS_STRING(val))) {
     _string.SetIsVoid(true);
     return;
   }
   // |null| in JS maps to the empty string.
   if (JSVAL_IS_NULL(val)) {
     _string.Truncate();
@@ -299,18 +299,18 @@ GetStringFromJSObject(JSContext* aCtx,
  */
 template <typename IntType>
 nsresult
 GetIntFromJSObject(JSContext* aCtx,
                    JSObject* aObject,
                    const char* aProperty,
                    IntType* _int)
 {
-  JS::Value value;
-  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, &value);
+  JS::Rooted<JS::Value> value(aCtx);
+  JSBool rc = JS_GetProperty(aCtx, aObject, aProperty, value.address());
   NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   if (JSVAL_IS_VOID(value)) {
     return NS_ERROR_INVALID_ARG;
   }
   NS_ENSURE_ARG(JSVAL_IS_PRIMITIVE(value));
   NS_ENSURE_ARG(JSVAL_IS_NUMBER(value));
 
   double num;
@@ -340,18 +340,18 @@ nsresult
 GetJSObjectFromArray(JSContext* aCtx,
                      JSObject* aArray,
                      uint32_t aIndex,
                      JSObject** _rooter)
 {
   NS_PRECONDITION(JS_IsArrayObject(aCtx, aArray),
                   "Must provide an object that is an array!");
 
-  JS::Value value;
-  JSBool rc = JS_GetElement(aCtx, aArray, aIndex, &value);
+  JS::Rooted<JS::Value> value(aCtx);
+  JSBool rc = JS_GetElement(aCtx, aArray, aIndex, value.address());
   NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   NS_ENSURE_ARG(!JSVAL_IS_PRIMITIVE(value));
   *_rooter = JSVAL_TO_OBJECT(value);
   return NS_OK;
 }
 
 class VisitedQuery : public AsyncStatementCallback
 {
@@ -2501,36 +2501,36 @@ NS_IMETHODIMP
 History::UpdatePlaces(const JS::Value& aPlaceInfos,
                       mozIVisitInfoCallback* aCallback,
                       JSContext* aCtx)
 {
   NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_UNEXPECTED);
   NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aPlaceInfos), NS_ERROR_INVALID_ARG);
 
   uint32_t infosLength = 1;
-  JSObject* infos;
-  if (JS_IsArrayObject(aCtx, JSVAL_TO_OBJECT(aPlaceInfos))) {
-    infos = JSVAL_TO_OBJECT(aPlaceInfos);
+  JS::Rooted<JSObject*> infos(aCtx);
+  if (JS_IsArrayObject(aCtx, aPlaceInfos.toObjectOrNull())) {
+    infos = aPlaceInfos.toObjectOrNull();
     (void)JS_GetArrayLength(aCtx, infos, &infosLength);
     NS_ENSURE_ARG(infosLength > 0);
   }
   else {
     // Build a temporary array to store this one item so the code below can
     // just loop.
     infos = JS_NewArrayObject(aCtx, 0, NULL);
     NS_ENSURE_TRUE(infos, NS_ERROR_OUT_OF_MEMORY);
 
     JSBool rc = JS_DefineElement(aCtx, infos, 0, aPlaceInfos, NULL, NULL, 0);
     NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   }
 
   nsTArray<VisitData> visitData;
   for (uint32_t i = 0; i < infosLength; i++) {
-    JSObject* info;
-    nsresult rv = GetJSObjectFromArray(aCtx, infos, i, &info);
+    JS::Rooted<JSObject*> info(aCtx);
+    nsresult rv = GetJSObjectFromArray(aCtx, infos, i, info.address());
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIURI> uri = GetURIFromJSObject(aCtx, info, "uri");
     nsCString guid;
     {
       nsString fatGUID;
       GetStringFromJSObject(aCtx, info, "guid", fatGUID);
       if (fatGUID.IsVoid()) {
@@ -2552,20 +2552,20 @@ History::UpdatePlaces(const JS::Value& a
 
     // If we were given a guid, make sure it is valid.
     bool isValidGUID = IsValidGUID(guid);
     NS_ENSURE_ARG(guid.IsVoid() || isValidGUID);
 
     nsString title;
     GetStringFromJSObject(aCtx, info, "title", title);
 
-    JSObject* visits = NULL;
+    JS::Rooted<JSObject*> visits(aCtx, nullptr);
     {
-      JS::Value visitsVal;
-      JSBool rc = JS_GetProperty(aCtx, info, "visits", &visitsVal);
+      JS::Rooted<JS::Value> visitsVal(aCtx);
+      JSBool rc = JS_GetProperty(aCtx, info, "visits", visitsVal.address());
       NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
       if (!JSVAL_IS_PRIMITIVE(visitsVal)) {
         visits = JSVAL_TO_OBJECT(visitsVal);
         NS_ENSURE_ARG(JS_IsArrayObject(aCtx, visits));
       }
     }
     NS_ENSURE_ARG(visits);
 
@@ -2573,18 +2573,18 @@ History::UpdatePlaces(const JS::Value& a
     if (visits) {
       (void)JS_GetArrayLength(aCtx, visits, &visitsLength);
     }
     NS_ENSURE_ARG(visitsLength > 0);
 
     // Check each visit, and build our array of VisitData objects.
     visitData.SetCapacity(visitData.Length() + visitsLength);
     for (uint32_t j = 0; j < visitsLength; j++) {
-      JSObject* visit;
-      rv = GetJSObjectFromArray(aCtx, visits, j, &visit);
+      JS::Rooted<JSObject*> visit(aCtx);
+      rv = GetJSObjectFromArray(aCtx, visits, j, visit.address());
       NS_ENSURE_SUCCESS(rv, rv);
 
       VisitData& data = *visitData.AppendElement(VisitData(uri));
       data.title = title;
       data.guid = guid;
 
       // We must have a date and a transaction type!
       rv = GetIntFromJSObject(aCtx, visit, "visitDate", &data.visitTime);
--- a/toolkit/components/places/PlaceInfo.cpp
+++ b/toolkit/components/places/PlaceInfo.cpp
@@ -70,33 +70,33 @@ PlaceInfo::GetFrecency(int64_t* _frecenc
 }
 
 NS_IMETHODIMP
 PlaceInfo::GetVisits(JSContext* aContext,
                      JS::Value* _visits)
 {
   // TODO bug 625913 when we use this in situations that have more than one
   // visit here, we will likely want to make this cache the value.
-  JSObject* visits = JS_NewArrayObject(aContext, 0, NULL);
+  JS::Rooted<JSObject*> visits(aContext, JS_NewArrayObject(aContext, 0, NULL));
   NS_ENSURE_TRUE(visits, NS_ERROR_OUT_OF_MEMORY);
 
-  JSObject* global = JS_GetGlobalForScopeChain(aContext);
+  JS::Rooted<JSObject*> global(aContext, JS_GetGlobalForScopeChain(aContext));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
   for (VisitsArray::size_type idx = 0; idx < mVisits.Length(); idx++) {
     nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
     nsresult rv = xpc->WrapNative(aContext, global, mVisits[idx],
                                   NS_GET_IID(mozIVisitInfo),
                                   getter_AddRefs(wrapper));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    JSObject* jsobj;
-    rv = wrapper->GetJSObject(&jsobj);
+    JS::Rooted<JSObject*> jsobj(aContext);
+    rv = wrapper->GetJSObject(jsobj.address());
     NS_ENSURE_SUCCESS(rv, rv);
     JS::Value wrappedVisit = OBJECT_TO_JSVAL(jsobj);
 
     JSBool rc = JS_SetElement(aContext, visits, idx, &wrappedVisit);
     NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   }
 
   *_visits = OBJECT_TO_JSVAL(visits);
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -777,21 +777,21 @@ CalculateProcessCreationTimestamp()
 }
 #else
 static PRTime
 CalculateProcessCreationTimestamp()
 {
   return 0;
 }
 #endif
- 
+
 NS_IMETHODIMP
 nsAppStartup::GetStartupInfo(JSContext* aCx, JS::Value* aRetval)
 {
-  JSObject *obj = JS_NewObject(aCx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, NULL, NULL, NULL));
   *aRetval = OBJECT_TO_JSVAL(obj);
 
   PRTime ProcessCreationTimestamp = StartupTimeline::Get(StartupTimeline::PROCESS_CREATION);
 
   if (!ProcessCreationTimestamp) {
     PRTime MainTimestamp = StartupTimeline::Get(StartupTimeline::MAIN);
     char *moz_app_restart = PR_GetEnv("MOZ_APP_RESTART");
     if (moz_app_restart) {
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -513,17 +513,17 @@ GetHistogramByEnumId(Telemetry::ID id, H
   if (p.extendedStatisticsOK) {
     h->SetFlags(Histogram::kExtendedStatisticsFlag);
   }
   *ret = knownHistograms[id] = h;
   return NS_OK;
 }
 
 bool
-FillRanges(JSContext *cx, JSObject *array, Histogram *h)
+FillRanges(JSContext *cx, JS::Handle<JSObject*> array, Histogram *h)
 {
   for (size_t i = 0; i < h->bucket_count(); i++) {
     if (!JS_DefineElement(cx, array, i, INT_TO_JSVAL(h->ranges(i)), NULL, NULL, JSPROP_ENUMERATE))
       return false;
   }
   return true;
 }
 
@@ -563,32 +563,30 @@ ReflectHistogramAndSamples(JSContext *cx
     uint32_t hi = static_cast<uint32_t>(sum_squares >> 32);
     if (!(JS_DefineProperty(cx, obj, "sum_squares_lo", INT_TO_JSVAL(lo), NULL, NULL, JSPROP_ENUMERATE)
           && JS_DefineProperty(cx, obj, "sum_squares_hi", INT_TO_JSVAL(hi), NULL, NULL, JSPROP_ENUMERATE))) {
       return REFLECT_FAILURE;
     }
   }
 
   const size_t count = h->bucket_count();
-  JSObject *rarray = JS_NewArrayObject(cx, count, nullptr);
+  JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, count, nullptr));
   if (!rarray) {
     return REFLECT_FAILURE;
   }
-  JS::AutoObjectRooter aroot(cx, rarray);
   if (!(FillRanges(cx, rarray, h)
         && JS_DefineProperty(cx, obj, "ranges", OBJECT_TO_JSVAL(rarray),
                              NULL, NULL, JSPROP_ENUMERATE))) {
     return REFLECT_FAILURE;
   }
 
-  JSObject *counts_array = JS_NewArrayObject(cx, count, NULL);
+  JS::Rooted<JSObject*> counts_array(cx, JS_NewArrayObject(cx, count, nullptr));
   if (!counts_array) {
     return REFLECT_FAILURE;
   }
-  JS::AutoObjectRooter croot(cx, counts_array);
   if (!JS_DefineProperty(cx, obj, "counts", OBJECT_TO_JSVAL(counts_array),
                          NULL, NULL, JSPROP_ENUMERATE)) {
     return REFLECT_FAILURE;
   }
   for (size_t i = 0; i < count; i++) {
     if (!JS_DefineElement(cx, counts_array, i, INT_TO_JSVAL(ss.counts(i)),
                           NULL, NULL, JSPROP_ENUMERATE)) {
       return REFLECT_FAILURE;
@@ -651,20 +649,19 @@ JSBool
 JSHistogram_Snapshot(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JSObject *obj = JS_THIS_OBJECT(cx, vp);
   if (!obj) {
     return JS_FALSE;
   }
 
   Histogram *h = static_cast<Histogram*>(JS_GetPrivate(obj));
-  JSObject *snapshot = JS_NewObject(cx, nullptr, nullptr, nullptr);
+  JS::Rooted<JSObject*> snapshot(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
   if (!snapshot)
     return JS_FALSE;
-  JS::AutoObjectRooter sroot(cx, snapshot);
 
   switch (ReflectHistogramSnapshot(cx, snapshot, h)) {
   case REFLECT_FAILURE:
     return JS_FALSE;
   case REFLECT_CORRUPT:
     JS_ReportError(cx, "Histogram is corrupt");
     return JS_FALSE;
   case REFLECT_OK:
@@ -694,20 +691,19 @@ WrapAndReturnHistogram(Histogram *h, JSC
 {
   static JSClass JSHistogram_class = {
     "JSHistogram",  /* name */
     JSCLASS_HAS_PRIVATE, /* flags */
     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
   };
 
-  JSObject *obj = JS_NewObject(cx, &JSHistogram_class, NULL, NULL);
+  JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &JSHistogram_class, NULL, NULL));
   if (!obj)
     return NS_ERROR_FAILURE;
-  JS::AutoObjectRooter root(cx, obj);
   if (!(JS_DefineFunction(cx, obj, "add", JSHistogram_Add, 1, 0)
         && JS_DefineFunction(cx, obj, "snapshot", JSHistogram_Snapshot, 0, 0)
         && JS_DefineFunction(cx, obj, "clear", JSHistogram_Clear, 0, 0))) {
     return NS_ERROR_FAILURE;
   }
   *ret = OBJECT_TO_JSVAL(obj);
   JS_SetPrivate(obj, h);
   return NS_OK;
@@ -996,21 +992,20 @@ TelemetryImpl::ReflectSQL(const SlowSQLE
 {
   if (stat->hitCount == 0)
     return true;
 
   const nsACString &sql = entry->GetKey();
   JS::Value hitCount = UINT_TO_JSVAL(stat->hitCount);
   JS::Value totalTime = UINT_TO_JSVAL(stat->totalTime);
 
-  JSObject *arrayObj = JS_NewArrayObject(cx, 0, nullptr);
+  JS::Rooted<JSObject*> arrayObj(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!arrayObj) {
     return false;
   }
-  JS::AutoObjectRooter root(cx, arrayObj);
   return (JS_SetElement(cx, arrayObj, 0, &hitCount)
           && JS_SetElement(cx, arrayObj, 1, &totalTime)
           && JS_DefineProperty(cx, obj,
                                sql.BeginReading(),
                                OBJECT_TO_JSVAL(arrayObj),
                                NULL, NULL, JSPROP_ENUMERATE));
 }
 
@@ -1027,20 +1022,19 @@ TelemetryImpl::ReflectOtherThreadsSQL(Sl
 {
   return ReflectSQL(entry, &entry->mData.otherThreads, cx, obj);
 }
 
 bool
 TelemetryImpl::AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread,
                           bool privateSQL)
 {
-  JSObject *statsObj = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> statsObj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!statsObj)
     return false;
-  JS::AutoObjectRooter root(cx, statsObj);
 
   AutoHashtable<SlowSQLEntryType> &sqlMap =
     (privateSQL ? mPrivateSQL : mSanitizedSQL);
   AutoHashtable<SlowSQLEntryType>::ReflectEntryFunc reflectFunction =
     (mainThread ? ReflectMainThreadSQL : ReflectOtherThreadsSQL);
   if(!sqlMap.ReflectIntoJS(reflectFunction, cx, statsObj)) {
     return false;
   }
@@ -1278,17 +1272,17 @@ TelemetryImpl::UnregisterAddonHistograms
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetHistogramSnapshots(JSContext *cx, JS::Value *ret)
 {
-  JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> root_obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!root_obj)
     return NS_ERROR_FAILURE;
   *ret = OBJECT_TO_JSVAL(root_obj);
 
   // Ensure that all the HISTOGRAM_FLAG histograms have been created, so
   // that their values are snapshotted.
   for (size_t i = 0; i < Telemetry::HistogramCount; ++i) {
     if (gHistograms[i].histogramType == nsITelemetry::HISTOGRAM_FLAG) {
@@ -1311,21 +1305,20 @@ TelemetryImpl::GetHistogramSnapshots(JSC
 
   // OK, now we can actually reflect things.
   for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) {
     Histogram *h = *it;
     if (!ShouldReflectHistogram(h) || IsEmpty(h)) {
       continue;
     }
 
-    JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL);
+    JS::Rooted<JSObject*> hobj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     if (!hobj) {
       return NS_ERROR_FAILURE;
     }
-    JS::AutoObjectRooter root(cx, hobj);
     switch (ReflectHistogramSnapshot(cx, hobj, h)) {
     case REFLECT_CORRUPT:
       // We can still hit this case even if ShouldReflectHistograms
       // returns true.  The histogram lies outside of our control
       // somehow; just skip it.
       continue;
     case REFLECT_FAILURE:
       return NS_ERROR_FAILURE;
@@ -1374,22 +1367,21 @@ TelemetryImpl::AddonHistogramReflector(A
       return false;
     }
   }
 
   if (IsEmpty(info.h)) {
     return true;
   }
 
-  JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> snapshot(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!snapshot) {
     // Just consider this to be skippable.
     return true;
   }
-  JS::AutoObjectRooter r(cx, snapshot);
   switch (ReflectHistogramSnapshot(cx, snapshot, info.h)) {
   case REFLECT_FAILURE:
   case REFLECT_CORRUPT:
     return false;
   case REFLECT_OK:
     const nsACString &histogramName = entry->GetKey();
     if (!JS_DefineProperty(cx, obj,
                            PromiseFlatCString(histogramName).get(),
@@ -1402,66 +1394,64 @@ TelemetryImpl::AddonHistogramReflector(A
   return true;
 }
 
 bool
 TelemetryImpl::AddonReflector(AddonEntryType *entry,
                               JSContext *cx, JSObject *obj)
 {
   const nsACString &addonId = entry->GetKey();
-  JSObject *subobj = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> subobj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!subobj) {
     return false;
   }
-  JS::AutoObjectRooter r(cx, subobj);
 
   AddonHistogramMapType *map = entry->mData;
   if (!(map->ReflectIntoJS(AddonHistogramReflector, cx, subobj)
         && JS_DefineProperty(cx, obj,
                              PromiseFlatCString(addonId).get(),
                              OBJECT_TO_JSVAL(subobj), NULL, NULL,
                              JSPROP_ENUMERATE))) {
     return false;
   }
   return true;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetAddonHistogramSnapshots(JSContext *cx, JS::Value *ret)
 {
   *ret = JSVAL_VOID;
-  JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
-  JS::AutoObjectRooter r(cx, obj);
 
   if (!mAddonMap.ReflectIntoJS(AddonReflector, cx, obj)) {
     return NS_ERROR_FAILURE;
   }
   *ret = OBJECT_TO_JSVAL(obj);
   return NS_OK;
 }
 
 bool
 TelemetryImpl::GetSQLStats(JSContext *cx, JS::Value *ret, bool includePrivateSql)
 {
-  JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> root_obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!root_obj)
     return false;
   *ret = OBJECT_TO_JSVAL(root_obj);
 
   MutexAutoLock hashMutex(mHashMutex);
   // Add info about slow SQL queries on the main thread
   if (!AddSQLInfo(cx, root_obj, true, includePrivateSql))
     return false;
   // Add info about slow SQL queries on other threads
   if (!AddSQLInfo(cx, root_obj, false, includePrivateSql))
     return false;
-  
+
   return true;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetSlowSQL(JSContext *cx, JS::Value *ret)
 {
   if (GetSQLStats(cx, ret, false))
     return NS_OK;
@@ -1486,24 +1476,24 @@ TelemetryImpl::GetMaximalNumberOfConcurr
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetChromeHangs(JSContext *cx, JS::Value *ret)
 {
   MutexAutoLock hangReportMutex(mHangReportsMutex);
 
   const CombinedStacks& stacks = mHangReports.GetStacks();
-  JSObject *fullReportObj = CreateJSStackObject(cx, stacks);
+  JS::Rooted<JSObject*> fullReportObj(cx, CreateJSStackObject(cx, stacks));
   if (!fullReportObj) {
     return NS_ERROR_FAILURE;
   }
 
   *ret = OBJECT_TO_JSVAL(fullReportObj);
 
-  JSObject *durationArray = JS_NewArrayObject(cx, 0, nullptr);
+  JS::Rooted<JSObject*> durationArray(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!durationArray) {
     return NS_ERROR_FAILURE;
   }
   JSBool ok = JS_DefineProperty(cx, fullReportObj, "durations",
                                 OBJECT_TO_JSVAL(durationArray),
                                 NULL, NULL, JSPROP_ENUMERATE);
   if (!ok) {
     return NS_ERROR_FAILURE;
@@ -1517,39 +1507,39 @@ TelemetryImpl::GetChromeHangs(JSContext 
     }
   }
 
   return NS_OK;
 }
 
 static JSObject *
 CreateJSStackObject(JSContext *cx, const CombinedStacks &stacks) {
-  JSObject *ret = JS_NewObject(cx, nullptr, nullptr, nullptr);
+  JS::Rooted<JSObject*> ret(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
   if (!ret) {
     return nullptr;
   }
 
-  JSObject *moduleArray = JS_NewArrayObject(cx, 0, nullptr);
+  JS::Rooted<JSObject*> moduleArray(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!moduleArray) {
     return nullptr;
   }
   JSBool ok = JS_DefineProperty(cx, ret, "memoryMap",
                                 OBJECT_TO_JSVAL(moduleArray),
                                 NULL, NULL, JSPROP_ENUMERATE);
   if (!ok) {
     return nullptr;
   }
 
   const size_t moduleCount = stacks.GetModuleCount();
   for (size_t moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
     // Current module
     const Telemetry::ProcessedStack::Module& module =
       stacks.GetModule(moduleIndex);
 
-    JSObject *moduleInfoArray = JS_NewArrayObject(cx, 0, nullptr);
+    JS::Rooted<JSObject*> moduleInfoArray(cx, JS_NewArrayObject(cx, 0, nullptr));
     if (!moduleInfoArray) {
       return nullptr;
     }
     JS::Value val = OBJECT_TO_JSVAL(moduleInfoArray);
     if (!JS_SetElement(cx, moduleArray, moduleIndex, &val)) {
       return nullptr;
     }
 
@@ -1571,45 +1561,45 @@ CreateJSStackObject(JSContext *cx, const
       return nullptr;
     }
     val = STRING_TO_JSVAL(id);
     if (!JS_SetElement(cx, moduleInfoArray, index++, &val)) {
       return nullptr;
     }
   }
 
-  JSObject *reportArray = JS_NewArrayObject(cx, 0, nullptr);
+  JS::Rooted<JSObject*> reportArray(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!reportArray) {
     return nullptr;
   }
   ok = JS_DefineProperty(cx, ret, "stacks",
                          OBJECT_TO_JSVAL(reportArray),
                          NULL, NULL, JSPROP_ENUMERATE);
   if (!ok) {
     return nullptr;
   }
 
   const size_t length = stacks.GetStackCount();
   for (size_t i = 0; i < length; ++i) {
     // Represent call stack PCs as (module index, offset) pairs.
-    JSObject *pcArray = JS_NewArrayObject(cx, 0, nullptr);
+    JS::Rooted<JSObject*> pcArray(cx, JS_NewArrayObject(cx, 0, nullptr));
     if (!pcArray) {
       return nullptr;
     }
 
     JS::Value pcArrayVal = OBJECT_TO_JSVAL(pcArray);
     if (!JS_SetElement(cx, reportArray, i, &pcArrayVal)) {
       return nullptr;
     }
 
     const CombinedStacks::Stack& stack = stacks.GetStack(i);
     const uint32_t pcCount = stack.size();
     for (size_t pcIndex = 0; pcIndex < pcCount; ++pcIndex) {
       const Telemetry::ProcessedStack::Frame& frame = stack[pcIndex];
-      JSObject *framePair = JS_NewArrayObject(cx, 0, nullptr);
+      JS::Rooted<JSObject*> framePair(cx, JS_NewArrayObject(cx, 0, nullptr));
       if (!framePair) {
         return nullptr;
       }
       int modIndex = (std::numeric_limits<uint16_t>::max() == frame.mModIndex) ?
         -1 : frame.mModIndex;
       JS::Value modIndexVal = INT_TO_JSVAL(modIndex);
       if (!JS_SetElement(cx, framePair, 0, &modIndexVal)) {
         return nullptr;
@@ -1792,24 +1782,24 @@ TelemetryImpl::GetLateWrites(JSContext *
   *ret = OBJECT_TO_JSVAL(report);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetRegisteredHistograms(JSContext *cx, JS::Value *ret)
 {
   size_t count = ArrayLength(gHistograms);
-  JSObject *info = JS_NewObject(cx, NULL, NULL, NULL);
+  JS::Rooted<JSObject*> info(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!info)
     return NS_ERROR_FAILURE;
   JS::AutoObjectRooter root(cx, info);
 
   for (size_t i = 0; i < count; ++i) {
     JSString *comment = JS_InternString(cx, gHistograms[i].comment());
-    
+
     if (!(comment
           && JS_DefineProperty(cx, info, gHistograms[i].id(),
                                STRING_TO_JSVAL(comment), NULL, NULL,
                                JSPROP_ENUMERATE))) {
       return NS_ERROR_FAILURE;
     }
   }