Bug 1464639 - Call JSPurpleBuffer::Destroy before shutting down the CC. r=mccr8.
authorPeter Van der Beken <peterv@propagandism.org>
Mon, 28 May 2018 22:23:45 +0200
changeset 420973 3567106d0a0505dc65477d2f43d67d1edbf46ba6
parent 420972 22e014e0bea4a4a87d23a48007c014e3a54b37cb
child 420974 4975928725165a5d5918085f951a4ef2c37f1ad0
push id34083
push userapavel@mozilla.com
push dateSat, 02 Jun 2018 23:03:25 +0000
treeherdermozilla-central@1f62ecdf59b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1464639
milestone62.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 1464639 - Call JSPurpleBuffer::Destroy before shutting down the CC. r=mccr8. Currently we call JSPurpleBuffer::Destroy from nsCycleCollector::PrepareForGarbageCollection. If the CC is shut down after a call to nsCycleCollector::GetJSPurpleBuffer (which creates a JSPurpleBuffer) but before a GC happens, we'll release the strong reference in mJSPurpleBuffer from nsCycleCollector's destructor but we won't call JSPurpleBuffer::Destroy. That leaves a stale pointer to the JSPurpleBuffer in the JSHolder's hash.
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2642,17 +2642,18 @@ public:
     , mObjects(kSegmentSize)
   {
     mReferenceToThis = this;
     mozilla::HoldJSObjects(this);
   }
 
   void Destroy()
   {
-    mReferenceToThis = nullptr;
+    RefPtr<JSPurpleBuffer> referenceToThis;
+    mReferenceToThis.swap(referenceToThis);
     mValues.Clear();
     mObjects.Clear();
     mozilla::DropJSObjects(this);
   }
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(JSPurpleBuffer)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(JSPurpleBuffer)
 
@@ -3484,16 +3485,18 @@ nsCycleCollector::nsCycleCollector() :
   mForgetSkippableCB(nullptr),
   mUnmergedNeeded(0),
   mMergedInARow(0)
 {
 }
 
 nsCycleCollector::~nsCycleCollector()
 {
+  MOZ_ASSERT(!mJSPurpleBuffer, "Didn't call JSPurpleBuffer::Destroy?");
+
   UnregisterWeakMemoryReporter(this);
 }
 
 void
 nsCycleCollector::SetCCJSRuntime(CycleCollectedJSRuntime* aCCRuntime)
 {
   MOZ_RELEASE_ASSERT(!mCCJSRuntime, "Multiple registrations of CycleCollectedJSRuntime in cycle collector");
   mCCJSRuntime = aCCRuntime;
@@ -3984,16 +3987,20 @@ nsCycleCollector::Shutdown(bool aDoColle
   }
 
   // Always delete snow white objects.
   FreeSnowWhite(true);
 
   if (aDoCollect) {
     ShutdownCollect();
   }
+
+  if (mJSPurpleBuffer) {
+    mJSPurpleBuffer->Destroy();
+  }
 }
 
 void
 nsCycleCollector::RemoveObjectFromGraph(void* aObj)
 {
   if (IsIdle()) {
     return;
   }