Bug 1508314 Part 1 - Watch for hits at temporary checkpoint locations when searching backwards, r=mccr8.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 19 Nov 2018 14:09:33 -1000
changeset 504024 436fe5156b0a113bc53392c368bc5d8e2a3d39ef
parent 504023 44f52ad4773bbe634f031ad08cf3a0e6f2310ae5
child 504025 1d4a0822756a5babd2e128ac1a968e67df001b46
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1508314
milestone65.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 1508314 Part 1 - Watch for hits at temporary checkpoint locations when searching backwards, r=mccr8.
toolkit/recordreplay/ipc/ChildNavigation.cpp
--- a/toolkit/recordreplay/ipc/ChildNavigation.cpp
+++ b/toolkit/recordreplay/ipc/ChildNavigation.cpp
@@ -257,16 +257,19 @@ public:
 class FindLastHitPhase final : public NavigationPhase
 {
   // Where we started searching from.
   CheckpointId mStart;
 
   // Endpoint of the search, nothing if the endpoint is the next checkpoint.
   Maybe<ExecutionPoint> mEnd;
 
+  // Whether the endpoint itself is considered to be part of the search space.
+  bool mIncludeEnd;
+
   // Counter that increases as we run forward, for ordering hits.
   size_t mCounter;
 
   // All positions we are interested in hits for, including all breakpoint
   // positions (and possibly other positions).
   struct TrackedPosition {
     BreakpointPosition mPosition;
 
@@ -278,21 +281,22 @@ class FindLastHitPhase final : public Na
 
     explicit TrackedPosition(const BreakpointPosition& aPosition)
       : mPosition(aPosition), mLastHitCount(0)
     {}
   };
   InfallibleVector<TrackedPosition, 4, UntrackedAllocPolicy> mTrackedPositions;
 
   const TrackedPosition& FindTrackedPosition(const BreakpointPosition& aPos);
+  void CheckForRegionEnd(const ExecutionPoint& aPoint);
   void OnRegionEnd();
 
 public:
   // Note: this always rewinds.
-  void Enter(const CheckpointId& aStart, const Maybe<ExecutionPoint>& aEnd);
+  void Enter(const CheckpointId& aStart, const Maybe<ExecutionPoint>& aEnd, bool aIncludeEnd);
 
   void ToString(nsAutoCString& aStr) override {
     aStr.AppendPrintf("FindLastHit");
   }
 
   void AfterCheckpoint(const CheckpointId& aCheckpoint) override;
   void PositionHit(const ExecutionPoint& aPoint) override;
   void HitRecordingEndpoint(const ExecutionPoint& aPoint) override;
@@ -566,23 +570,23 @@ PausedPhase::Resume(bool aForward)
   if (mPoint.HasPosition()) {
     CheckpointId start = gNavigation->LastCheckpoint();
 
     // Skip over any temporary checkpoint we saved.
     if (mSavedTemporaryCheckpoint) {
       MOZ_RELEASE_ASSERT(start.mTemporary);
       start.mTemporary--;
     }
-    gNavigation->mFindLastHitPhase.Enter(start, Some(mPoint));
+    gNavigation->mFindLastHitPhase.Enter(start, Some(mPoint), /* aIncludeEnd = */ false);
   } else {
     // We can't rewind past the beginning of the replay.
     MOZ_RELEASE_ASSERT(mPoint.mCheckpoint != CheckpointId::First);
 
     CheckpointId start(mPoint.mCheckpoint - 1);
-    gNavigation->mFindLastHitPhase.Enter(start, Nothing());
+    gNavigation->mFindLastHitPhase.Enter(start, Nothing(), /* aIncludeEnd = */ false);
   }
   Unreachable();
 }
 
 void
 PausedPhase::RestoreCheckpoint(size_t aCheckpoint)
 {
   ExecutionPoint target = gNavigation->CheckpointExecutionPoint(aCheckpoint);
@@ -902,22 +906,24 @@ ReachBreakpointPhase::PositionHit(const 
   }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // FindLastHitPhase
 ///////////////////////////////////////////////////////////////////////////////
 
 void
-FindLastHitPhase::Enter(const CheckpointId& aStart, const Maybe<ExecutionPoint>& aEnd)
+FindLastHitPhase::Enter(const CheckpointId& aStart, const Maybe<ExecutionPoint>& aEnd,
+                        bool aIncludeEnd)
 {
   MOZ_RELEASE_ASSERT(aEnd.isNothing() || aEnd.ref().HasPosition());
 
   mStart = aStart;
   mEnd = aEnd;
+  mIncludeEnd = aIncludeEnd;
   mCounter = 0;
   mTrackedPositions.clear();
 
   gNavigation->SetPhase(this);
 
   // All breakpoints are tracked positions.
   for (const BreakpointPosition& breakpoint : gNavigation->mBreakpoints) {
     if (breakpoint.IsValid()) {
@@ -957,30 +963,42 @@ FindLastHitPhase::AfterCheckpoint(const 
   if (mEnd.isSome()) {
     js::EnsurePositionHandler(mEnd.ref().mPosition);
   }
 }
 
 void
 FindLastHitPhase::PositionHit(const ExecutionPoint& aPoint)
 {
-  if (mEnd.isSome() && mEnd.ref() == aPoint) {
-    OnRegionEnd();
-    Unreachable();
+  if (!mIncludeEnd) {
+    CheckForRegionEnd(aPoint);
   }
 
   ++mCounter;
 
   for (TrackedPosition& tracked : mTrackedPositions) {
     if (tracked.mPosition.Subsumes(aPoint.mPosition)) {
       tracked.mLastHit = aPoint;
       tracked.mLastHitCount = mCounter;
       break;
     }
   }
+
+  if (mIncludeEnd) {
+    CheckForRegionEnd(aPoint);
+  }
+}
+
+void
+FindLastHitPhase::CheckForRegionEnd(const ExecutionPoint& aPoint)
+{
+  if (mEnd.isSome() && mEnd.ref() == aPoint) {
+    OnRegionEnd();
+    Unreachable();
+  }
 }
 
 void
 FindLastHitPhase::HitRecordingEndpoint(const ExecutionPoint& aPoint)
 {
   OnRegionEnd();
   Unreachable();
 }
@@ -1015,17 +1033,20 @@ FindLastHitPhase::OnRegionEnd()
     // No breakpoints were encountered in the search space.
     if (mStart.mTemporary) {
       // We started searching forwards from a temporary checkpoint.
       // Continue searching backwards without notifying the middleman.
       CheckpointId start = mStart;
       start.mTemporary--;
       ExecutionPoint end = gNavigation->LastTemporaryCheckpointLocation();
       if (end.HasPosition()) {
-        gNavigation->mFindLastHitPhase.Enter(start, Some(end));
+        // The temporary checkpoint comes immediately after its associated
+        // execution point. As we search backwards we need to look for hits at
+        // that execution point itself.
+        gNavigation->mFindLastHitPhase.Enter(start, Some(end), /* aIncludeEnd = */ true);
         Unreachable();
       } else {
         // The last temporary checkpoint may be at the same execution point as
         // the last normal checkpoint, if it was created while handling
         // debugger requests there.
       }
     }