Bug 1460636 - Don't trace jsids on ObjectGroup in the cycle collector. r=jonco, r=sfink, a=RyanVM
authorAndrew McCreight <continuation@gmail.com>
Fri, 11 May 2018 11:38:58 -0700
changeset 470764 7b8ada24da4ddc1a1b3961f9d0fffa7fd75f95c3
parent 470763 1da8d36ce5a4c6f41863ecd4edd5b0ae5c548c69
child 470765 c2cc19eb1159bea5cd8e8be6c2c9c5fd41e7b053
push id9218
push userryanvm@gmail.com
push dateSun, 13 May 2018 19:56:21 +0000
treeherdermozilla-beta@5fcefe47c777 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco, sfink, RyanVM
bugs1460636
milestone61.0
Bug 1460636 - Don't trace jsids on ObjectGroup in the cycle collector. r=jonco, r=sfink, a=RyanVM For some reason, the CC spends a lot of time tracing jsids on ObjectGroups when an addon is installed. This patch avoids that by adding a canSkipJsids flag to JSTracer, and using it in ObjectGroup::traceChildren. If this is true, then the tracer is free to not report every jsid. This flag is set to true for the two CC tracers. MozReview-Commit-ID: CWFqQEr0SxV
js/public/TracingAPI.h
js/src/gc/Marking.cpp
xpcom/base/CycleCollectedJSRuntime.cpp
--- a/js/public/TracingAPI.h
+++ b/js/public/TracingAPI.h
@@ -81,16 +81,17 @@ class JS_PUBLIC_API(JSTracer)
         Callback
     };
     bool isMarkingTracer() const { return tag_ == TracerKindTag::Marking || tag_ == TracerKindTag::WeakMarking; }
     bool isWeakMarkingTracer() const { return tag_ == TracerKindTag::WeakMarking; }
     bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
     bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
     inline JS::CallbackTracer* asCallbackTracer();
     bool traceWeakEdges() const { return traceWeakEdges_; }
+    bool canSkipJsids() const { return canSkipJsids_; }
 #ifdef DEBUG
     bool checkEdges() { return checkEdges_; }
 #endif
 
     // Get the current GC number. Only call this method if |isMarkingTracer()|
     // is true.
     uint32_t gcNumberForMarking() const;
 
@@ -99,16 +100,17 @@ class JS_PUBLIC_API(JSTracer)
              WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
       : runtime_(rt)
       , weakMapAction_(weakTraceKind)
 #ifdef DEBUG
       , checkEdges_(true)
 #endif
       , tag_(tag)
       , traceWeakEdges_(true)
+      , canSkipJsids_(false)
     {}
 
 #ifdef DEBUG
     // Set whether to check edges are valid in debug builds.
     void setCheckEdges(bool check) {
         checkEdges_ = check;
     }
 #endif
@@ -118,16 +120,17 @@ class JS_PUBLIC_API(JSTracer)
     WeakMapTraceKind weakMapAction_;
 #ifdef DEBUG
     bool checkEdges_;
 #endif
 
   protected:
     TracerKindTag tag_;
     bool traceWeakEdges_;
+    bool canSkipJsids_;
 };
 
 namespace JS {
 
 class AutoTracingName;
 class AutoTracingIndex;
 class AutoTracingCallback;
 
@@ -249,16 +252,22 @@ class JS_PUBLIC_API(CallbackTracer) : pu
     void dispatchToOnEdge(js::Scope** scopep) { onScopeEdge(scopep); }
     void dispatchToOnEdge(js::RegExpShared** sharedp) { onRegExpSharedEdge(sharedp); }
 
   protected:
     void setTraceWeakEdges(bool value) {
         traceWeakEdges_ = value;
     }
 
+    // If this is set to false, then the tracer will skip some jsids
+    // to improve performance. This is needed for the cycle collector.
+    void setCanSkipJsids(bool value) {
+        canSkipJsids_ = value;
+    }
+
   private:
     friend class AutoTracingName;
     const char* contextName_;
 
     friend class AutoTracingIndex;
     size_t contextIndex_;
 
     friend class AutoTracingDetails;
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1451,20 +1451,23 @@ js::GCMarker::eagerlyMarkChildren(Scope*
             traverseEdge(scope, static_cast<JSString*>(names[i].name()));
     }
 }
 
 void
 js::ObjectGroup::traceChildren(JSTracer* trc)
 {
     AutoSweepObjectGroup sweep(this);
-    unsigned count = getPropertyCount(sweep);
-    for (unsigned i = 0; i < count; i++) {
-        if (ObjectGroup::Property* prop = getProperty(sweep, i))
-            TraceEdge(trc, &prop->id, "group_property");
+
+    if (!trc->canSkipJsids()) {
+        unsigned count = getPropertyCount(sweep);
+        for (unsigned i = 0; i < count; i++) {
+            if (ObjectGroup::Property* prop = getProperty(sweep, i))
+                TraceEdge(trc, &prop->id, "group_property");
+        }
     }
 
     if (proto().isObject())
         TraceEdge(trc, &proto(), "group_proto");
 
     if (trc->isMarkingTracer())
         compartment()->mark();
 
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -138,16 +138,17 @@ public:
 
 struct NoteWeakMapChildrenTracer : public JS::CallbackTracer
 {
   NoteWeakMapChildrenTracer(JSRuntime* aRt,
                             nsCycleCollectionNoteRootCallback& aCb)
     : JS::CallbackTracer(aRt), mCb(aCb), mTracedAny(false), mMap(nullptr),
       mKey(nullptr), mKeyDelegate(nullptr)
   {
+    setCanSkipJsids(true);
   }
   void onChild(const JS::GCCellPtr& aThing) override;
   nsCycleCollectionNoteRootCallback& mCb;
   bool mTracedAny;
   JSObject* mMap;
   JS::GCCellPtr mKey;
   JSObject* mKeyDelegate;
 };
@@ -394,16 +395,17 @@ JSZoneParticipant::TraverseNative(void* 
   return NS_OK;
 }
 
 struct TraversalTracer : public JS::CallbackTracer
 {
   TraversalTracer(JSRuntime* aRt, nsCycleCollectionTraversalCallback& aCb)
     : JS::CallbackTracer(aRt, DoNotTraceWeakMaps), mCb(aCb)
   {
+    setCanSkipJsids(true);
   }
   void onChild(const JS::GCCellPtr& aThing) override;
   nsCycleCollectionTraversalCallback& mCb;
 };
 
 void
 TraversalTracer::onChild(const JS::GCCellPtr& aThing)
 {