Bug 867459 - Fix toolkit/ rooting hazards r=terrence
authorDavid Zbarsky <dzbarsky@gmail.com>
Thu, 02 May 2013 22:02:37 -0400
changeset 130712 b8786f0e022639f4c9b669bc07bc62212460dc48
parent 130711 e7e44c2d6d72b0c0363d3af25ad46dcf6638876c
child 130713 de74752f65e7fbb3dd9f71ad9682f92cf4227589
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 - Fix toolkit/ rooting hazards r=terrence
toolkit/components/telemetry/Telemetry.cpp
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -55,22 +55,22 @@ using namespace base;
 using namespace mozilla;
 
 template<class EntryType>
 class AutoHashtable : public nsTHashtable<EntryType>
 {
 public:
   AutoHashtable(uint32_t initSize = PL_DHASH_MIN_SIZE);
   ~AutoHashtable();
-  typedef bool (*ReflectEntryFunc)(EntryType *entry, JSContext *cx, JSObject *obj);
-  bool ReflectIntoJS(ReflectEntryFunc entryFunc, JSContext *cx, JSObject *obj);
+  typedef bool (*ReflectEntryFunc)(EntryType *entry, JSContext *cx, JS::Handle<JSObject*> obj);
+  bool ReflectIntoJS(ReflectEntryFunc entryFunc, JSContext *cx, JS::Handle<JSObject*> obj);
 private:
   struct EnumeratorArgs {
     JSContext *cx;
-    JSObject *obj;
+    JS::Handle<JSObject*> obj;
     ReflectEntryFunc entryFunc;
   };
   static PLDHashOperator ReflectEntryStub(EntryType *entry, void *arg);
 };
 
 template<class EntryType>
 AutoHashtable<EntryType>::AutoHashtable(uint32_t initSize)
 {
@@ -96,17 +96,17 @@ AutoHashtable<EntryType>::ReflectEntrySt
 
 /**
  * Reflect the individual entries of table into JS, usually by defining
  * some property and value of obj.  entryFunc is called for each entry.
  */
 template<typename EntryType>
 bool
 AutoHashtable<EntryType>::ReflectIntoJS(ReflectEntryFunc entryFunc,
-                                        JSContext *cx, JSObject *obj)
+                                        JSContext *cx, JS::Handle<JSObject*> obj)
 {
   EnumeratorArgs args = { cx, obj, entryFunc };
   uint32_t num = this->EnumerateEntries(ReflectEntryStub, static_cast<void*>(&args));
   return num == this->Count();
 }
 
 // This class is conceptually a list of ProcessedStack objects, but it represents them
 // more efficiently by keeping a single global list of modules.
@@ -277,23 +277,23 @@ private:
   static nsCString SanitizeSQL(const nsACString& sql);
 
   enum SanitizedState { Sanitized, Unsanitized };
 
   static void StoreSlowSQL(const nsACString &offender, uint32_t delay,
                            SanitizedState state);
 
   static bool ReflectMainThreadSQL(SlowSQLEntryType *entry, JSContext *cx,
-                                   JSObject *obj);
+                                   JS::Handle<JSObject*> obj);
   static bool ReflectOtherThreadsSQL(SlowSQLEntryType *entry, JSContext *cx,
-                                     JSObject *obj);
+                                     JS::Handle<JSObject*> obj);
   static bool ReflectSQL(const SlowSQLEntryType *entry, const Stat *stat,
-                         JSContext *cx, JSObject *obj);
+                         JSContext *cx, JS::Handle<JSObject*> obj);
 
-  bool AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread,
+  bool AddSQLInfo(JSContext *cx, JS::Handle<JSObject*> rootObj, bool mainThread,
                   bool privateSQL);
   bool GetSQLStats(JSContext *cx, JS::Value *ret, bool includePrivateSql);
 
   // Like GetHistogramById, but returns the underlying C++ object, not the JS one.
   nsresult GetHistogramByName(const nsACString &name, Histogram **ret);
   bool ShouldReflectHistogram(Histogram *h);
   void IdentifyCorruptHistograms(StatisticsRecorder::Histograms &hs);
   typedef StatisticsRecorder::Histograms::iterator HistogramIterator;
@@ -305,18 +305,18 @@ private:
     uint32_t histogramType;
     Histogram *h;
   };
   typedef nsBaseHashtableET<nsCStringHashKey, AddonHistogramInfo> AddonHistogramEntryType;
   typedef AutoHashtable<AddonHistogramEntryType> AddonHistogramMapType;
   typedef nsBaseHashtableET<nsCStringHashKey, AddonHistogramMapType *> AddonEntryType;
   typedef AutoHashtable<AddonEntryType> AddonMapType;
   static bool AddonHistogramReflector(AddonHistogramEntryType *entry,
-                                      JSContext *cx, JSObject *obj);
-  static bool AddonReflector(AddonEntryType *entry, JSContext *cx, JSObject *obj);
+                                      JSContext *cx, JS::Handle<JSObject*> obj);
+  static bool AddonReflector(AddonEntryType *entry, JSContext *cx, JS::Handle<JSObject*> obj);
   static bool CreateHistogramForAddon(const nsACString &name,
                                       AddonHistogramInfo &info);
   void ReadLateWritesStacks();
   AddonMapType mAddonMap;
 
   // This is used for speedy string->Telemetry::ID conversions
   typedef nsBaseHashtableET<nsCharPtrHashKey, Telemetry::ID> CharPtrEntryType;
   typedef AutoHashtable<CharPtrEntryType> HistogramMapType;
@@ -515,31 +515,33 @@ GetHistogramByEnumId(Telemetry::ID id, H
   }
   *ret = knownHistograms[id] = h;
   return NS_OK;
 }
 
 bool
 FillRanges(JSContext *cx, JS::Handle<JSObject*> array, Histogram *h)
 {
+  JS::Rooted<JS::Value> range(cx);
   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))
+    range = INT_TO_JSVAL(h->ranges(i));
+    if (!JS_DefineElement(cx, array, i, range, nullptr, nullptr, JSPROP_ENUMERATE))
       return false;
   }
   return true;
 }
 
 enum reflectStatus {
   REFLECT_OK,
   REFLECT_CORRUPT,
   REFLECT_FAILURE
 };
 
 enum reflectStatus
-ReflectHistogramAndSamples(JSContext *cx, JSObject *obj, Histogram *h,
+ReflectHistogramAndSamples(JSContext *cx, JS::Handle<JSObject*> obj, Histogram *h,
                            const Histogram::SampleSet &ss)
 {
   // We don't want to reflect corrupt histograms.
   if (h->FindCorruption(ss) != Histogram::NO_INCONSISTENCIES) {
     return REFLECT_CORRUPT;
   }
 
   if (!(JS_DefineProperty(cx, obj, "min", INT_TO_JSVAL(h->declared_min()), NULL, NULL, JSPROP_ENUMERATE)
@@ -587,22 +589,22 @@ ReflectHistogramAndSamples(JSContext *cx
     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;
     }
   }
- 
+
   return REFLECT_OK;
 }
 
 enum reflectStatus
-ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h)
+ReflectHistogramSnapshot(JSContext *cx, JS::Handle<JSObject*> obj, Histogram *h)
 {
   Histogram::SampleSet ss;
   h->SnapshotSample(&ss);
   return ReflectHistogramAndSamples(cx, obj, h, ss);
 }
 
 bool
 IsEmpty(const Histogram *h)
@@ -983,53 +985,53 @@ TelemetryImpl::NewHistogram(const nsACSt
   h->SetFlags(Histogram::kExtendedStatisticsFlag);
   return WrapAndReturnHistogram(h, cx, ret);
 }
 
 bool
 TelemetryImpl::ReflectSQL(const SlowSQLEntryType *entry,
                           const Stat *stat,
                           JSContext *cx,
-                          JSObject *obj)
+                          JS::Handle<JSObject*> obj)
 {
   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);
+  JS::Rooted<JS::Value> hitCount(cx, UINT_TO_JSVAL(stat->hitCount));
+  JS::Rooted<JS::Value> totalTime(cx, UINT_TO_JSVAL(stat->totalTime));
 
   JS::Rooted<JSObject*> arrayObj(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!arrayObj) {
     return false;
   }
-  return (JS_SetElement(cx, arrayObj, 0, &hitCount)
-          && JS_SetElement(cx, arrayObj, 1, &totalTime)
+  return (JS_SetElement(cx, arrayObj, 0, hitCount.address())
+          && JS_SetElement(cx, arrayObj, 1, totalTime.address())
           && JS_DefineProperty(cx, obj,
                                sql.BeginReading(),
                                OBJECT_TO_JSVAL(arrayObj),
                                NULL, NULL, JSPROP_ENUMERATE));
 }
 
 bool
 TelemetryImpl::ReflectMainThreadSQL(SlowSQLEntryType *entry, JSContext *cx,
-                                    JSObject *obj)
+                                    JS::Handle<JSObject*> obj)
 {
   return ReflectSQL(entry, &entry->mData.mainThread, cx, obj);
 }
 
 bool
 TelemetryImpl::ReflectOtherThreadsSQL(SlowSQLEntryType *entry, JSContext *cx,
-                                      JSObject *obj)
+                                      JS::Handle<JSObject*> obj)
 {
   return ReflectSQL(entry, &entry->mData.otherThreads, cx, obj);
 }
 
 bool
-TelemetryImpl::AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread,
+TelemetryImpl::AddSQLInfo(JSContext *cx, JS::Handle<JSObject*> rootObj, bool mainThread,
                           bool privateSQL)
 {
   JS::Rooted<JSObject*> statsObj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
   if (!statsObj)
     return false;
 
   AutoHashtable<SlowSQLEntryType> &sqlMap =
     (privateSQL ? mPrivateSQL : mSanitizedSQL);
@@ -1349,17 +1351,17 @@ TelemetryImpl::CreateHistogramForAddon(c
   // other ways.
   h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
   info.h = h;
   return true;
 }
 
 bool
 TelemetryImpl::AddonHistogramReflector(AddonHistogramEntryType *entry,
-                                       JSContext *cx, JSObject *obj)
+                                       JSContext *cx, JS::Handle<JSObject*> obj)
 {
   AddonHistogramInfo &info = entry->mData;
 
   // Never even accessed the histogram.
   if (!info.h) {
     // Have to force creation of HISTOGRAM_FLAG histograms.
     if (info.histogramType != nsITelemetry::HISTOGRAM_FLAG) 
       return true;
@@ -1392,17 +1394,17 @@ TelemetryImpl::AddonHistogramReflector(A
     }
     break;
   }
   return true;
 }
 
 bool
 TelemetryImpl::AddonReflector(AddonEntryType *entry,
-                              JSContext *cx, JSObject *obj)
+                              JSContext *cx, JS::Handle<JSObject*> obj)
 {
   const nsACString &addonId = entry->GetKey();
   JS::Rooted<JSObject*> subobj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
   if (!subobj) {
     return false;
   }
 
   AddonHistogramMapType *map = entry->mData;