Bug 1413418 - Give the last chance to consume micro task queue during the final cycle collection; r=smaug
authorEdgar Chen <echen@mozilla.com>
Thu, 19 Jul 2018 16:38:33 +0000
changeset 427454 c736dc02532d32e5befd401b89fcdd520832b6ef
parent 427453 f97be2485d3d7bc791c22e69e44531e2130ab64f
child 427455 b891899b2036de7b47cf96790c581fb704588c78
push id34306
push usercsabou@mozilla.com
push dateFri, 20 Jul 2018 21:41:18 +0000
treeherdermozilla-central@d6a5e8aea651 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1413418
milestone63.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 1413418 - Give the last chance to consume micro task queue during the final cycle collection; r=smaug Differential Revision: https://phabricator.services.mozilla.com/D2121
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSContext.h
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -500,26 +500,26 @@ public:
     if (ccjs) {
       ccjs->PerformMicroTaskCheckPoint();
     }
     return NS_OK;
   }
 };
 
 bool
-CycleCollectedJSContext::PerformMicroTaskCheckPoint()
+CycleCollectedJSContext::PerformMicroTaskCheckPoint(bool aForce)
 {
   if (mPendingMicroTaskRunnables.empty() && mDebuggerMicroTaskQueue.empty()) {
     AfterProcessMicrotasks();
     // Nothing to do, return early.
     return false;
   }
 
   uint32_t currentDepth = RecursionDepth();
-  if (mMicroTaskRecursionDepth >= currentDepth) {
+  if (mMicroTaskRecursionDepth >= currentDepth && !aForce) {
     // We are already executing microtasks for the current recursion depth.
     return false;
   }
 
   if (mTargetedMicroTaskRecursionDepth != 0 &&
       mTargetedMicroTaskRecursionDepth != currentDepth) {
     return false;
   }
@@ -527,17 +527,17 @@ CycleCollectedJSContext::PerformMicroTas
   if (NS_IsMainThread() && !nsContentUtils::IsSafeToRunScript()) {
     // Special case for main thread where DOM mutations may happen when
     // it is not safe to run scripts.
     nsContentUtils::AddScriptRunner(new AsyncMutationHandler());
     return false;
   }
 
   mozilla::AutoRestore<uint32_t> restore(mMicroTaskRecursionDepth);
-  MOZ_ASSERT(currentDepth > 0);
+  MOZ_ASSERT(aForce ? currentDepth == 0 : currentDepth > 0);
   mMicroTaskRecursionDepth = currentDepth;
 
   bool didProcess = false;
   AutoSlowOperation aso;
 
   std::queue<RefPtr<MicroTaskRunnable>> suppressed;
   for (;;) {
     RefPtr<MicroTaskRunnable> runnable;
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -220,17 +220,17 @@ public:
     return mMicroTaskLevel;
   }
 
   void SetMicroTaskLevel(uint32_t aLevel)
   {
     mMicroTaskLevel = aLevel;
   }
 
-  bool PerformMicroTaskCheckPoint();
+  bool PerformMicroTaskCheckPoint(bool aForce = false);
 
   void PerformDebuggerMicroTaskCheckpoint();
 
   bool IsInStableOrMetaStableState()
   {
     return mDoingStableStates;
   }
 
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -4382,17 +4382,18 @@ nsCycleCollector_shutdown(bool aDoCollec
 
     if (gMainThreadCollector == data->mCollector) {
       gMainThreadCollector = nullptr;
     }
     data->mCollector->Shutdown(aDoCollect);
     data->mCollector = nullptr;
     if (data->mContext) {
       // Run any remaining tasks that may have been enqueued via
-      // RunInStableState during the final cycle collection.
+      // RunInStableState or DispatchToMicroTask during the final cycle collection.
       data->mContext->ProcessStableStateQueue();
+      data->mContext->PerformMicroTaskCheckPoint(true);
     }
     if (!data->mContext) {
       delete data;
       sCollectorData.set(nullptr);
     }
   }
 }