Bug 1486616 - Execute record/replay triggers when finalizing deferred things, r=mccr8.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 31 Aug 2018 05:35:36 -1000
changeset 434430 d8447a4c32e7d4d991773f478f9dd2996628c51c
parent 434429 ad486af682370e5d6e16ef832e2ecd5c3a6ba846
child 434431 5830b5e072d00c8ece17d1f7ec92cc7ee3c64b57
push id34557
push userdluca@mozilla.com
push dateSun, 02 Sep 2018 21:34:34 +0000
treeherdermozilla-central@634b562ae2c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1486616
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 1486616 - Execute record/replay triggers when finalizing deferred things, r=mccr8.
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/threads/nsThread.cpp
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -1450,16 +1450,23 @@ CycleCollectedJSRuntime::FinalizeDeferre
     mFinalizeRunnable->ReleaseNow(false);
     if (mFinalizeRunnable) {
       // If we re-entered ReleaseNow, we couldn't delete mFinalizeRunnable and
       // we need to just continue processing it.
       return;
     }
   }
 
+  // When recording or replaying, execute triggers that were activated recently
+  // by mozilla::DeferredFinalize. This will populate the deferred finalizer
+  // table with a consistent set of entries between the recording and replay.
+  if (recordreplay::IsRecordingOrReplaying()) {
+    recordreplay::ExecuteTriggers();
+  }
+
   if (mDeferredFinalizerTable.Count() == 0) {
     return;
   }
 
   mFinalizeRunnable = new IncrementalFinalizeRunnable(this,
                                                       mDeferredFinalizerTable);
 
   // Everything should be gone now.
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -3958,22 +3958,16 @@ nsCycleCollector::BeginCollection(ccType
   FinishAnyIncrementalGCInProgress();
   timeLog.Checkpoint("Pre-FixGrayBits finish IGC");
 
   FixGrayBits(forceGC, timeLog);
   if (mCCJSRuntime) {
     mCCJSRuntime->CheckGrayBits();
   }
 
-  // If we are recording or replaying, force the release of any references
-  // from objects that have recently been finalized.
-  if (recordreplay::IsRecordingOrReplaying()) {
-    recordreplay::ExecuteTriggers();
-  }
-
   FreeSnowWhite(true);
   timeLog.Checkpoint("BeginCollection FreeSnowWhite");
 
   if (mLogger && NS_FAILED(mLogger->Begin())) {
     mLogger = nullptr;
   }
 
   // FreeSnowWhite could potentially have started an IGC, which we need
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -1033,27 +1033,21 @@ nsThread::ProcessNextEvent(bool aMayWait
 {
   LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, aMayWait,
        mNestedEventLoopDepth));
 
   if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
     return NS_ERROR_NOT_SAME_THREAD;
   }
 
-  // When recording or replaying, execute triggers that were activated
-  // non-deterministically at some point since the last turn of the event loop.
-  if (recordreplay::IsRecordingOrReplaying()) {
-    recordreplay::ExecuteTriggers();
-
-    // Vsync observers are notified whenever processing events on the main
-    // thread. Waiting for explicit vsync messages from the UI process can
-    // result in paints happening at unexpected times when replaying/rewinding.
-    if (mIsMainThread == MAIN_THREAD) {
-      recordreplay::child::NotifyVsyncObserver();
-    }
+  // When recording or replaying, vsync observers are notified whenever
+  // processing events on the main thread. Waiting for explicit vsync messages
+  // from the UI process can result in paints happening at unexpected times.
+  if (recordreplay::IsRecordingOrReplaying() && mIsMainThread == MAIN_THREAD) {
+    recordreplay::child::NotifyVsyncObserver();
   }
 
   // The toplevel event loop normally blocks waiting for the next event, but
   // if we're trying to shut this thread down, we must exit the event loop when
   // the event queue is empty.
   // This only applys to the toplevel event loop! Nested event loops (e.g.
   // during sync dispatch) are waiting for some state change and must be able
   // to block even if something has requested shutdown of the thread. Otherwise