Backed out 2 changesets (bug 1335751) for mochitest devtools failures
authorJon Coppeard <jcoppeard@mozilla.com>
Sun, 05 Mar 2017 12:37:31 +0000
changeset 395009 71f7cd1d842f054d2d8b6ebc4dc06b7c4ba0bc54
parent 395008 376d3e4d4a750adf58e011f65b530ecf65726652
child 395010 3f78543493a2b14aaa43db417fa2085d457c94df
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1335751
milestone54.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
Backed out 2 changesets (bug 1335751) for mochitest devtools failures
js/public/TracingAPI.h
js/src/gc/Marking.cpp
js/src/gc/Verifier.cpp
js/src/jsfriendapi.h
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSContext.h
xpcom/base/nsCycleCollector.cpp
--- a/js/public/TracingAPI.h
+++ b/js/public/TracingAPI.h
@@ -81,31 +81,29 @@ class JS_PUBLIC_API(JSTracer)
         // Traversing children is the responsibility of the callback.
         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_; }
 #ifdef DEBUG
     bool checkEdges() { return checkEdges_; }
 #endif
 
   protected:
     JSTracer(JSRuntime* rt, TracerKindTag tag,
              WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
       : runtime_(rt)
       , weakMapAction_(weakTraceKind)
 #ifdef DEBUG
       , checkEdges_(true)
 #endif
       , tag_(tag)
-      , traceWeakEdges_(true)
     {}
 
 #ifdef DEBUG
     // Set whether to check edges are valid in debug builds.
     void setCheckEdges(bool check) {
         checkEdges_ = check;
     }
 #endif
@@ -114,17 +112,16 @@ class JS_PUBLIC_API(JSTracer)
     JSRuntime* runtime_;
     WeakMapTraceKind weakMapAction_;
 #ifdef DEBUG
     bool checkEdges_;
 #endif
 
   protected:
     TracerKindTag tag_;
-    bool traceWeakEdges_;
 };
 
 namespace JS {
 
 class AutoTracingName;
 class AutoTracingIndex;
 class AutoTracingCallback;
 
@@ -230,21 +227,16 @@ class JS_PUBLIC_API(CallbackTracer) : pu
     void dispatchToOnEdge(JSScript** scriptp) { onScriptEdge(scriptp); }
     void dispatchToOnEdge(js::Shape** shapep) { onShapeEdge(shapep); }
     void dispatchToOnEdge(js::ObjectGroup** groupp) { onObjectGroupEdge(groupp); }
     void dispatchToOnEdge(js::BaseShape** basep) { onBaseShapeEdge(basep); }
     void dispatchToOnEdge(js::jit::JitCode** codep) { onJitCodeEdge(codep); }
     void dispatchToOnEdge(js::LazyScript** lazyp) { onLazyScriptEdge(lazyp); }
     void dispatchToOnEdge(js::Scope** scopep) { onScopeEdge(scopep); }
 
-  protected:
-    void setTraceWeakEdges(bool value) {
-        traceWeakEdges_ = 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
@@ -474,22 +474,19 @@ js::UnsafeTraceManuallyBarrieredEdge(JST
 {
     DispatchToTracer(trc, ConvertToBase(thingp), name);
 }
 
 template <typename T>
 void
 js::TraceWeakEdge(JSTracer* trc, WeakRef<T>* thingp, const char* name)
 {
-    if (!trc->isMarkingTracer()) {
-        // Non-marking tracers can select whether or not they see weak edges.
-        if (trc->traceWeakEdges())
-            DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name);
-        return;
-    }
+    // Non-marking tracers treat the edge strongly.
+    if (!trc->isMarkingTracer())
+        return DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name);
 
     NoteWeakEdge(GCMarker::fromTracer(trc),
                  ConvertToBase(thingp->unsafeUnbarrieredForTracing()));
 }
 
 template <typename T>
 void
 js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -444,34 +444,24 @@ js::gc::GCRuntime::finishVerifier()
     if (verifyPreData) {
         js_delete(verifyPreData.ref());
         verifyPreData = nullptr;
     }
 }
 
 #endif /* JS_GC_ZEAL */
 
-#if defined(JSGC_HASH_TABLE_CHECKS) || defined(DEBUG)
+#ifdef JSGC_HASH_TABLE_CHECKS
 
-class HeapCheckTracerBase : public JS::CallbackTracer
+class CheckHeapTracer : public JS::CallbackTracer
 {
   public:
-    explicit HeapCheckTracerBase(JSRuntime* rt, WeakMapTraceKind weakTraceKind);
+    explicit CheckHeapTracer(JSRuntime* rt);
     bool init();
-    bool traceHeap(AutoLockForExclusiveAccess& lock);
-    virtual void checkCell(Cell* cell) = 0;
-
-  protected:
-    void dumpCellPath();
-
-    Cell* parentCell() {
-        return parentIndex == -1 ? nullptr : stack[parentIndex].thing.asCell();
-    }
-
-    size_t failures;
+    void check(AutoLockForExclusiveAccess& lock);
 
   private:
     void onChild(const JS::GCCellPtr& thing) override;
 
     struct WorkItem {
         WorkItem(JS::GCCellPtr thing, const char* name, int parentIndex)
           : thing(thing), name(name), parentIndex(parentIndex), processed(false)
         {}
@@ -479,216 +469,114 @@ class HeapCheckTracerBase : public JS::C
         JS::GCCellPtr thing;
         const char* name;
         int parentIndex;
         bool processed;
     };
 
     JSRuntime* rt;
     bool oom;
+    size_t failures;
     HashSet<Cell*, DefaultHasher<Cell*>, SystemAllocPolicy> visited;
     Vector<WorkItem, 0, SystemAllocPolicy> stack;
     int parentIndex;
 };
 
-HeapCheckTracerBase::HeapCheckTracerBase(JSRuntime* rt, WeakMapTraceKind weakTraceKind)
-  : CallbackTracer(rt, weakTraceKind),
-    failures(0),
+CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
+  : CallbackTracer(rt, TraceWeakMapKeysValues),
     rt(rt),
     oom(false),
+    failures(0),
     parentIndex(-1)
 {
 #ifdef DEBUG
     setCheckEdges(false);
 #endif
 }
 
 bool
-HeapCheckTracerBase::init()
+CheckHeapTracer::init()
 {
     return visited.init();
 }
 
+inline static bool
+IsValidGCThingPointer(Cell* cell)
+{
+    return (uintptr_t(cell) & CellMask) == 0;
+}
+
 void
-HeapCheckTracerBase::onChild(const JS::GCCellPtr& thing)
+CheckHeapTracer::onChild(const JS::GCCellPtr& thing)
 {
     Cell* cell = thing.asCell();
-    checkCell(cell);
-
     if (visited.lookup(cell))
         return;
 
     if (!visited.put(cell)) {
         oom = true;
         return;
     }
 
+    if (!IsValidGCThingPointer(cell) || !IsGCThingValidAfterMovingGC(cell))
+    {
+        failures++;
+        fprintf(stderr, "Bad pointer %p\n", cell);
+        const char* name = contextName();
+        for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
+            const WorkItem& parent = stack[index];
+            cell = parent.thing.asCell();
+            fprintf(stderr, "  from %s %p %s edge\n",
+                    GCTraceKindToAscii(cell->getTraceKind()), cell, name);
+            name = parent.name;
+        }
+        fprintf(stderr, "  from root %s\n", name);
+        return;
+    }
+
     // Don't trace into GC things owned by another runtime.
     if (cell->runtimeFromAnyThread() != rt)
         return;
 
-    // Don't trace into GC in zones being used by helper threads.
-    Zone* zone = thing.is<JSObject>() ? thing.as<JSObject>().zone() : cell->asTenured().zone();
-    if (zone->group() && zone->group()->usedByHelperThread)
-        return;
-
     WorkItem item(thing, contextName(), parentIndex);
     if (!stack.append(item))
         oom = true;
 }
 
-bool
-HeapCheckTracerBase::traceHeap(AutoLockForExclusiveAccess& lock)
+void
+CheckHeapTracer::check(AutoLockForExclusiveAccess& lock)
 {
     // The analysis thinks that traceRuntime might GC by calling a GC callback.
     JS::AutoSuppressGCAnalysis nogc;
     if (!rt->isBeingDestroyed())
         rt->gc.traceRuntime(this, lock);
 
-    while (!stack.empty() && !oom) {
+    while (!stack.empty()) {
         WorkItem item = stack.back();
         if (item.processed) {
             stack.popBack();
         } else {
             parentIndex = stack.length() - 1;
+            TraceChildren(this, item.thing);
             stack.back().processed = true;
-            TraceChildren(this, item.thing);
         }
     }
 
-    return !oom;
-}
-
-void
-HeapCheckTracerBase::dumpCellPath()
-{
-    const char* name = contextName();
-    for (int index = parentIndex; index != -1; index = stack[index].parentIndex) {
-        const WorkItem& parent = stack[index];
-        Cell* cell = parent.thing.asCell();
-        fprintf(stderr, "  from %s %p %s edge\n",
-                GCTraceKindToAscii(cell->getTraceKind()), cell, name);
-        name = parent.name;
-    }
-    fprintf(stderr, "  from root %s\n", name);
-}
-
-#endif // defined(JSGC_HASH_TABLE_CHECKS) || defined(DEBUG)
-
-#ifdef JSGC_HASH_TABLE_CHECKS
-
-class CheckHeapTracer final : public HeapCheckTracerBase
-{
-  public:
-    explicit CheckHeapTracer(JSRuntime* rt);
-    void check(AutoLockForExclusiveAccess& lock);
-
-  private:
-    void checkCell(Cell* cell) override;
-};
-
-CheckHeapTracer::CheckHeapTracer(JSRuntime* rt)
-  : HeapCheckTracerBase(rt, TraceWeakMapKeysValues)
-{}
-
-inline static bool
-IsValidGCThingPointer(Cell* cell)
-{
-    return (uintptr_t(cell) & CellMask) == 0;
-}
-
-void
-CheckHeapTracer::checkCell(Cell* cell)
-{
-    if (!IsValidGCThingPointer(cell) || !IsGCThingValidAfterMovingGC(cell)) {
-        failures++;
-        fprintf(stderr, "Bad pointer %p\n", cell);
-        dumpCellPath();
-    }
-}
-
-void
-CheckHeapTracer::check(AutoLockForExclusiveAccess& lock)
-{
-    if (!traceHeap(lock))
+    if (oom)
         return;
 
-    if (failures)
-        fprintf(stderr, "Heap check: %" PRIuSIZE " failure(s)\n", failures);
+    if (failures) {
+        fprintf(stderr, "Heap check: %" PRIuSIZE " failure(s) out of %" PRIu32 " pointers checked\n",
+                failures, visited.count());
+    }
     MOZ_RELEASE_ASSERT(failures == 0);
 }
 
 void
 js::gc::CheckHeapAfterGC(JSRuntime* rt)
 {
     AutoTraceSession session(rt, JS::HeapState::Tracing);
     CheckHeapTracer tracer(rt);
     if (tracer.init())
         tracer.check(session.lock);
 }
 
 #endif /* JSGC_HASH_TABLE_CHECKS */
-
-#ifdef DEBUG
-
-class CheckGrayMarkingTracer final : public HeapCheckTracerBase
-{
-  public:
-    explicit CheckGrayMarkingTracer(JSRuntime* rt);
-    bool check(AutoLockForExclusiveAccess& lock);
-
-  private:
-    void checkCell(Cell* cell) override;
-};
-
-CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt)
-  : HeapCheckTracerBase(rt, DoNotTraceWeakMaps)
-{
-    // Weak gray->black edges are allowed.
-    setTraceWeakEdges(false);
-}
-
-void
-CheckGrayMarkingTracer::checkCell(Cell* cell)
-{
-    Cell* parent = parentCell();
-    if (!cell->isTenured() || !parent || !parent->isTenured())
-        return;
-
-    TenuredCell* tenuredCell = &cell->asTenured();
-    TenuredCell* tenuredParent = &parent->asTenured();
-    if (tenuredParent->isMarked(BLACK) && !tenuredParent->isMarked(GRAY) &&
-        tenuredCell->isMarked(GRAY))
-    {
-        failures++;
-        fprintf(stderr, "Found black to gray edge %p\n", cell);
-        dumpCellPath();
-    }
-}
-
-bool
-CheckGrayMarkingTracer::check(AutoLockForExclusiveAccess& lock)
-{
-    if (!traceHeap(lock))
-        return true; // Ignore failure.
-
-    return failures == 0;
-}
-
-JS_FRIEND_API(bool)
-js::CheckGrayMarkingState(JSContext* cx)
-{
-    JSRuntime* rt = cx->runtime();
-    MOZ_ASSERT(!JS::CurrentThreadIsHeapCollecting());
-    MOZ_ASSERT(!rt->gc.isIncrementalGCInProgress());
-    if (!rt->gc.areGrayBitsValid())
-        return true;
-
-    gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PHASE_TRACE_HEAP);
-    AutoTraceSession session(rt, JS::HeapState::Tracing);
-    CheckGrayMarkingTracer tracer(rt);
-    if (!tracer.init())
-        return true; // Ignore failure
-
-    return tracer.check(session.lock);
-}
-
-#endif // DEBUG
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -487,26 +487,16 @@ IterateGrayObjects(JS::Zone* zone, GCThi
 
 /**
  * Invoke cellCallback on every gray JSObject in the given zone while cycle
  * collection is in progress.
  */
 extern JS_FRIEND_API(void)
 IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
 
-#ifdef DEBUG
-// Trace the heap and check there are no black to gray edges. These are
-// not allowed since the cycle collector could throw away the gray thing and
-// leave a dangling pointer.
-//
-// This doesn't trace weak maps as these are handled separately.
-extern JS_FRIEND_API(bool)
-CheckGrayMarkingState(JSContext* cx);
-#endif
-
 #ifdef JS_HAS_CTYPES
 extern JS_FRIEND_API(size_t)
 SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
 #endif
 
 extern JS_FRIEND_API(JSCompartment*)
 GetAnyCompartmentInZone(JS::Zone* zone);
 
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -222,54 +222,17 @@ NoteWeakMapsTracer::trace(JSObject* aMap
     // if we haven't already.
     if (!mChildTracer.mTracedAny &&
         aKey && JS::GCThingIsMarkedGray(aKey) && kdelegate) {
       mCb.NoteWeakMapping(aMap, aKey, kdelegate, nullptr);
     }
   }
 }
 
-// Report whether the key or value of a weak mapping entry are gray but need to
-// be marked black.
-static void
-ShouldWeakMappingEntryBeBlack(JSObject* aMap, JS::GCCellPtr aKey, JS::GCCellPtr aValue,
-                              bool* aKeyShouldBeBlack, bool* aValueShouldBeBlack)
-{
-  *aKeyShouldBeBlack = false;
-  *aValueShouldBeBlack = false;
-
-  // If nothing that could be held alive by this entry is marked gray, return.
-  bool keyMightNeedMarking = aKey && JS::GCThingIsMarkedGray(aKey);
-  bool valueMightNeedMarking = aValue && JS::GCThingIsMarkedGray(aValue) &&
-    aValue.kind() != JS::TraceKind::String;
-  if (!keyMightNeedMarking && !valueMightNeedMarking) {
-    return;
-  }
-
-  if (!AddToCCKind(aKey.kind())) {
-    aKey = nullptr;
-  }
-
-  if (keyMightNeedMarking && aKey.is<JSObject>()) {
-    JSObject* kdelegate = js::GetWeakmapKeyDelegate(&aKey.as<JSObject>());
-    if (kdelegate && !JS::ObjectIsMarkedGray(kdelegate) &&
-        (!aMap || !JS::ObjectIsMarkedGray(aMap)))
-    {
-      *aKeyShouldBeBlack = true;
-    }
-  }
-
-  if (aValue && JS::GCThingIsMarkedGray(aValue) &&
-      (!aKey || !JS::GCThingIsMarkedGray(aKey)) &&
-      (!aMap || !JS::ObjectIsMarkedGray(aMap)) &&
-      aValue.kind() != JS::TraceKind::Shape) {
-    *aValueShouldBeBlack = true;
-  }
-}
-
+// This is based on the logic in FixWeakMappingGrayBitsTracer::trace.
 struct FixWeakMappingGrayBitsTracer : public js::WeakMapTracer
 {
   explicit FixWeakMappingGrayBitsTracer(JSContext* aCx)
     : js::WeakMapTracer(aCx)
   {
   }
 
   void
@@ -278,73 +241,52 @@ struct FixWeakMappingGrayBitsTracer : pu
     do {
       mAnyMarked = false;
       js::TraceWeakMaps(this);
     } while (mAnyMarked);
   }
 
   void trace(JSObject* aMap, JS::GCCellPtr aKey, JS::GCCellPtr aValue) override
   {
-    bool keyShouldBeBlack;
-    bool valueShouldBeBlack;
-    ShouldWeakMappingEntryBeBlack(aMap, aKey, aValue,
-                                  &keyShouldBeBlack, &valueShouldBeBlack);
-    if (keyShouldBeBlack && JS::UnmarkGrayGCThingRecursively(aKey)) {
-      mAnyMarked = true;
+    // If nothing that could be held alive by this entry is marked gray, return.
+    bool keyMightNeedMarking = aKey && JS::GCThingIsMarkedGray(aKey);
+    bool valueMightNeedMarking = aValue && JS::GCThingIsMarkedGray(aValue) &&
+                                 aValue.kind() != JS::TraceKind::String;
+    if (!keyMightNeedMarking && !valueMightNeedMarking) {
+      return;
+    }
+
+    if (!AddToCCKind(aKey.kind())) {
+      aKey = nullptr;
     }
 
-    if (valueShouldBeBlack && JS::UnmarkGrayGCThingRecursively(aValue)) {
-      mAnyMarked = true;
+    if (keyMightNeedMarking && aKey.is<JSObject>()) {
+      JSObject* kdelegate = js::GetWeakmapKeyDelegate(&aKey.as<JSObject>());
+      if (kdelegate && !JS::ObjectIsMarkedGray(kdelegate) &&
+          (!aMap || !JS::ObjectIsMarkedGray(aMap)))
+      {
+        if (JS::UnmarkGrayGCThingRecursively(aKey)) {
+          mAnyMarked = true;
+        }
+      }
+    }
+
+    if (aValue && JS::GCThingIsMarkedGray(aValue) &&
+        (!aKey || !JS::GCThingIsMarkedGray(aKey)) &&
+        (!aMap || !JS::ObjectIsMarkedGray(aMap)) &&
+        aValue.kind() != JS::TraceKind::Shape) {
+      if (JS::UnmarkGrayGCThingRecursively(aValue)) {
+        mAnyMarked = true;
+      }
     }
   }
 
   MOZ_INIT_OUTSIDE_CTOR bool mAnyMarked;
 };
 
-#ifdef DEBUG
-// Check whether weak maps are marked correctly according to the logic above.
-struct CheckWeakMappingGrayBitsTracer : public js::WeakMapTracer
-{
-  explicit CheckWeakMappingGrayBitsTracer(JSContext* aCx)
-    : js::WeakMapTracer(aCx), mFailed(false)
-  {
-  }
-
-  static bool
-  Check(JSContext* aCx)
-  {
-    CheckWeakMappingGrayBitsTracer tracer(aCx);
-    js::TraceWeakMaps(&tracer);
-    return !tracer.mFailed;
-  }
-
-  void trace(JSObject* aMap, JS::GCCellPtr aKey, JS::GCCellPtr aValue) override
-  {
-    bool keyShouldBeBlack;
-    bool valueShouldBeBlack;
-    ShouldWeakMappingEntryBeBlack(aMap, aKey, aValue,
-                                  &keyShouldBeBlack, &valueShouldBeBlack);
-
-    if (keyShouldBeBlack) {
-      fprintf(stderr, "Weak mapping key %p of map %p should be black\n",
-              aKey.asCell(), aMap);
-      mFailed = true;
-    }
-
-    if (valueShouldBeBlack) {
-      fprintf(stderr, "Weak mapping value %p of map %p should be black\n",
-              aValue.asCell(), aMap);
-      mFailed = true;
-    }
-  }
-
-  bool mFailed;
-};
-#endif // DEBUG
-
 static void
 CheckParticipatesInCycleCollection(JS::GCCellPtr aThing, const char* aName,
                                    void* aClosure)
 {
   bool* cycleCollectionEnabled = static_cast<bool*>(aClosure);
 
   if (*cycleCollectionEnabled) {
     return;
@@ -1308,26 +1250,16 @@ CycleCollectedJSContext::FixWeakMappingG
 {
   MOZ_ASSERT(mJSContext);
   MOZ_ASSERT(!JS::IsIncrementalGCInProgress(mJSContext),
              "Don't call FixWeakMappingGrayBits during a GC.");
   FixWeakMappingGrayBitsTracer fixer(mJSContext);
   fixer.FixAll();
 }
 
-void
-CycleCollectedJSContext::CheckGrayBits() const
-{
-  MOZ_ASSERT(mJSContext);
-  MOZ_ASSERT(!JS::IsIncrementalGCInProgress(mJSContext),
-             "Don't call CheckGrayBits during a GC.");
-  MOZ_ASSERT(js::CheckGrayMarkingState(mJSContext));
-  MOZ_ASSERT(CheckWeakMappingGrayBitsTracer::Check(mJSContext));
-}
-
 bool
 CycleCollectedJSContext::AreGCGrayBitsValid() const
 {
   MOZ_ASSERT(mJSContext);
   return js::AreGCGrayBitsValid(mJSContext);
 }
 
 void
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -308,17 +308,16 @@ public:
   std::queue<nsCOMPtr<nsIRunnable>>& GetDebuggerPromiseMicroTaskQueue();
 
   nsCycleCollectionParticipant* GCThingParticipant();
   nsCycleCollectionParticipant* ZoneParticipant();
 
   nsresult TraverseRoots(nsCycleCollectionNoteRootCallback& aCb);
   virtual bool UsefulToMergeZones() const;
   void FixWeakMappingGrayBits() const;
-  void CheckGrayBits() const;
   bool AreGCGrayBitsValid() const;
   void GarbageCollect(uint32_t aReason) const;
 
   void NurseryWrapperAdded(nsWrapperCache* aCache);
   void NurseryWrapperPreserved(JSObject* aWrapper);
   void JSObjectsTenured();
 
   void DeferredFinalize(DeferredFinalizeAppendFunction aAppendFunc,
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -3827,19 +3827,16 @@ nsCycleCollector::BeginCollection(ccType
   bool forceGC = isShutdown || (mLogger && mLogger->IsAllTraces());
 
   // BeginCycleCollectionCallback() might have started an IGC, and we need
   // to finish it before we run FixGrayBits.
   FinishAnyIncrementalGCInProgress();
   timeLog.Checkpoint("Pre-FixGrayBits finish IGC");
 
   FixGrayBits(forceGC, timeLog);
-  if (mJSContext) {
-    mJSContext->CheckGrayBits();
-  }
 
   FreeSnowWhite(true);
   timeLog.Checkpoint("BeginCollection FreeSnowWhite");
 
   if (mLogger && NS_FAILED(mLogger->Begin())) {
     mLogger = nullptr;
   }