Bug 1478016 - Add a strongly-typed LayersObserverEpoch type. r=mattwoodrow
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 30 Jul 2018 09:24:50 -0400
changeset 429191 383e6ae8f7d4d1961a56aa6f5a69b4c3e8c3e2e5
parent 429160 f416035aca83e6b01a44053f5a648389cb31c540
child 429192 ba66db7432e535f3eb80fd3d3586e64e96275ab3
push id34355
push userccoroiu@mozilla.com
push dateMon, 30 Jul 2018 21:57:34 +0000
treeherdermozilla-central@896812b8a15b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1478016
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 1478016 - Add a strongly-typed LayersObserverEpoch type. r=mattwoodrow MozReview-Commit-ID: 6fELexXRYeV
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PBrowser.ipdl
dom/ipc/PProcessHangMonitor.ipdl
dom/ipc/ProcessHangMonitor.cpp
dom/ipc/ProcessHangMonitor.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
gfx/layers/Layers.h
gfx/layers/LayersTypes.h
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientLayerManager.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/LayersMessageUtils.h
gfx/layers/ipc/PCompositorBridge.ipdl
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5537,25 +5537,25 @@ ContentParent::SendGetFilesResponseAndFo
   if (mGetFilesPendingRequests.Remove(aUUID)) {
     Unused << SendGetFilesResponse(aUUID, aResult);
   }
 }
 
 void
 ContentParent::PaintTabWhileInterruptingJS(TabParent* aTabParent,
                                            bool aForceRepaint,
-                                           uint64_t aLayerObserverEpoch)
+                                           const layers::LayersObserverEpoch& aEpoch)
 {
   if (!mHangMonitorActor) {
     return;
   }
   ProcessHangMonitor::PaintWhileInterruptingJS(mHangMonitorActor,
                                                aTabParent,
                                                aForceRepaint,
-                                               aLayerObserverEpoch);
+                                               aEpoch);
 }
 
 void
 ContentParent::UpdateCookieStatus(nsIChannel   *aChannel)
 {
   PNeckoParent *neckoParent = LoneManagedOrNullAsserts(ManagedPNeckoParent());
   PCookieServiceParent *csParent = LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
   if (csParent) {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -648,17 +648,19 @@ public:
 
   virtual mozilla::ipc::IPCResult
   RecvClassifyLocal(const URIParams& aURI,
                     const nsCString& aTables,
                     nsresult* aRv,
                     nsTArray<nsCString>* aResults) override;
 
   // Use the PHangMonitor channel to ask the child to repaint a tab.
-  void PaintTabWhileInterruptingJS(TabParent* aTabParent, bool aForceRepaint, uint64_t aLayerObserverEpoch);
+  void PaintTabWhileInterruptingJS(TabParent* aTabParent,
+                                   bool aForceRepaint,
+                                   const layers::LayersObserverEpoch& aEpoch);
 
   // This function is called when we are about to load a document from an
   // HTTP(S), FTP or wyciwyg channel for a content process.  It is a useful
   // place to start to kick off work as early as possible in response to such
   // document loads.
   nsresult AboutToLoadHttpFtpWyciwygDocumentForChild(nsIChannel* aChannel);
 
   nsresult TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal);
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -37,16 +37,17 @@ using mozilla::gfx::SurfaceFormat from "
 using mozilla::LayoutDeviceIntPoint from "Units.h";
 using mozilla::LayoutDevicePoint from "Units.h";
 using mozilla::ScreenIntPoint from "Units.h";
 using ScreenIntSize from "Units.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
 using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
 using mozilla::layers::GeckoContentController::TapType from "mozilla/layers/GeckoContentController.h";
 using FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using nscolor from "nsColor.h";
 using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
 using struct mozilla::widget::IMENotification from "mozilla/widget/IMEData.h";
@@ -537,17 +538,17 @@ parent:
      * Child informs the parent that the content is ready to handle input
      * events. This is sent when the TabChild is created.
      */
     async RemoteIsReadyToHandleInputEvents();
 
     /**
      * Child informs the parent that the layer tree is already available.
      */
-    async PaintWhileInterruptingJSNoOp(uint64_t aLayerObserverEpoch);
+    async PaintWhileInterruptingJSNoOp(LayersObserverEpoch aEpoch);
 
     /**
      * Sent by the child to the parent to inform it that an update to the
      * dimensions has been requested, likely through win.moveTo or resizeTo
      */
     async SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, int32_t aCx, int32_t aCy);
 
     nested(inside_sync) sync DispatchWheelEvent(WidgetWheelEvent event);
@@ -747,22 +748,22 @@ child:
      * clears the layers from the compositor.
      *
      * @param aEnabled
      *        True if the child should render and upload layers, false if the
      *        child should clear layers.
      * @param aForceRepaint
      *        True if the child should force a paint even if it's already
      *        visible.
-     * @param aLayerObserverEpoch
+     * @param aEpoch
      *        The layer observer epoch for this activation. This message should be
      *        ignored if this epoch has already been observed (via
      *        PaintWhileInterruptingJS).
      */
-    async RenderLayers(bool aEnabled, bool aForceRepaint, uint64_t aLayerObserverEpoch);
+    async RenderLayers(bool aEnabled, bool aForceRepaint, LayersObserverEpoch aEpoch);
 
     /**
      * Notify the child that it shouldn't paint the offscreen displayport.
      * This is useful to speed up interactive operations over async
      * scrolling performance like resize, tabswitch, pageload.
      *
      * Each enable call must be matched with a disable call. The child
      * will remain in the suppress mode as long as there's
--- a/dom/ipc/PProcessHangMonitor.ipdl
+++ b/dom/ipc/PProcessHangMonitor.ipdl
@@ -2,16 +2,17 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 using base::ProcessId from "base/process.h";
 using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
+using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 
 struct SlowScriptData
 {
   TabId tabId;
   nsCString filename;
   nsString addonId;
@@ -36,12 +37,12 @@ parent:
   async ClearHang();
 
 child:
   async TerminateScript(bool aTerminateGlobal);
 
   async BeginStartingDebugger();
   async EndStartingDebugger();
 
-  async PaintWhileInterruptingJS(TabId tabId, bool forceRepaint, uint64_t aLayerObserverEpoch);
+  async PaintWhileInterruptingJS(TabId tabId, bool forceRepaint, LayersObserverEpoch aEpoch);
 };
 
 } // namespace mozilla
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -91,31 +91,31 @@ class HangMonitorChild
 
   bool IsDebuggerStartupComplete();
 
   void NotifyPluginHang(uint32_t aPluginId);
   void NotifyPluginHangAsync(uint32_t aPluginId);
 
   void ClearHang();
   void ClearHangAsync();
-  void ClearPaintWhileInterruptingJS(uint64_t aLayerObserverEpoch);
+  void ClearPaintWhileInterruptingJS(const LayersObserverEpoch& aEpoch);
 
   // MaybeStartPaintWhileInterruptingJS will notify the background hang monitor of activity
   // if this is the first time calling it since ClearPaintWhileInterruptingJS. It should be
   // callable from any thread, but you must be holding mMonitor if using it off
   // the main thread, since it could race with ClearPaintWhileInterruptingJS.
   void MaybeStartPaintWhileInterruptingJS();
 
   mozilla::ipc::IPCResult RecvTerminateScript(const bool& aTerminateGlobal) override;
   mozilla::ipc::IPCResult RecvBeginStartingDebugger() override;
   mozilla::ipc::IPCResult RecvEndStartingDebugger() override;
 
   mozilla::ipc::IPCResult RecvPaintWhileInterruptingJS(const TabId& aTabId,
                                                        const bool& aForceRepaint,
-                                                       const uint64_t& aLayerObserverEpoch) override;
+                                                       const LayersObserverEpoch& aEpoch) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void InterruptCallback();
   void Shutdown();
 
   static HangMonitorChild* Get() { return sInstance; }
 
@@ -143,17 +143,17 @@ class HangMonitorChild
   // These fields must be accessed with mMonitor held.
   bool mTerminateScript;
   bool mTerminateGlobal;
   bool mStartDebugger;
   bool mFinishedStartingDebugger;
   bool mPaintWhileInterruptingJS;
   bool mPaintWhileInterruptingJSForce;
   TabId mPaintWhileInterruptingJSTab;
-  MOZ_INIT_OUTSIDE_CTOR uint64_t mPaintWhileInterruptingJSEpoch;
+  MOZ_INIT_OUTSIDE_CTOR LayersObserverEpoch mPaintWhileInterruptingJSEpoch;
   JSContext* mContext;
   bool mShutdownDone;
 
   // This field is only accessed on the hang thread.
   bool mIPCOpen;
 
   // Allows us to ensure we NotifyActivity only once, allowing
   // either thread to do so.
@@ -231,17 +231,17 @@ public:
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void SetProcess(HangMonitoredProcess* aProcess) { mProcess = aProcess; }
 
   void Shutdown();
 
   void PaintWhileInterruptingJS(dom::TabParent* aTabParent,
                                 bool aForceRepaint,
-                                uint64_t aLayerObserverEpoch);
+                                const LayersObserverEpoch& aEpoch);
 
   void TerminateScript(bool aTerminateGlobal);
   void BeginStartingDebugger();
   void EndStartingDebugger();
   void CleanupPluginHang(uint32_t aPluginId, bool aRemoveFiles);
 
   /**
    * Update the dump for the specified plugin. This method is thread-safe and
@@ -262,17 +262,17 @@ private:
   void SendHangNotification(const HangData& aHangData,
                             const nsString& aBrowserDumpId,
                             bool aTakeMinidump);
   void OnTakeFullMinidumpComplete(const HangData& aHangData,
                                   const nsString& aDumpId);
 
   void ClearHangNotification();
 
-  void PaintWhileInterruptingJSOnThread(TabId aTabId, bool aForceRepaint, uint64_t aLayerObserverEpoch);
+  void PaintWhileInterruptingJSOnThread(TabId aTabId, bool aForceRepaint, const LayersObserverEpoch& aEpoch);
 
   void ShutdownOnThread();
 
   const RefPtr<ProcessHangMonitor> mHangMonitor;
 
   // This field is read-only after construction.
   bool mReportHangs;
 
@@ -333,17 +333,17 @@ HangMonitorChild::~HangMonitorChild()
 void
 HangMonitorChild::InterruptCallback()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   bool paintWhileInterruptingJS;
   bool paintWhileInterruptingJSForce;
   TabId paintWhileInterruptingJSTab;
-  uint64_t paintWhileInterruptingJSEpoch;
+  LayersObserverEpoch paintWhileInterruptingJSEpoch;
 
   {
     MonitorAutoLock lock(mMonitor);
     paintWhileInterruptingJS = mPaintWhileInterruptingJS;
     paintWhileInterruptingJSForce = mPaintWhileInterruptingJSForce;
     paintWhileInterruptingJSTab = mPaintWhileInterruptingJSTab;
     paintWhileInterruptingJSEpoch = mPaintWhileInterruptingJSEpoch;
 
@@ -429,27 +429,27 @@ HangMonitorChild::RecvEndStartingDebugge
   MonitorAutoLock lock(mMonitor);
   mFinishedStartingDebugger = true;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 HangMonitorChild::RecvPaintWhileInterruptingJS(const TabId& aTabId,
                                                const bool& aForceRepaint,
-                                               const uint64_t& aLayerObserverEpoch)
+                                               const LayersObserverEpoch& aEpoch)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
   {
     MonitorAutoLock lock(mMonitor);
     MaybeStartPaintWhileInterruptingJS();
     mPaintWhileInterruptingJS = true;
     mPaintWhileInterruptingJSForce = aForceRepaint;
     mPaintWhileInterruptingJSTab = aTabId;
-    mPaintWhileInterruptingJSEpoch = aLayerObserverEpoch;
+    mPaintWhileInterruptingJSEpoch = aEpoch;
   }
 
   JS_RequestInterruptCallback(mContext);
 
   return IPC_OK();
 }
 
 void
@@ -459,17 +459,17 @@ HangMonitorChild::MaybeStartPaintWhileIn
   // has been temporarily removed to diagnose a tab switch spinner
   // problem.
   if (!NS_IsMainThread()) {
     mMonitor.AssertCurrentThreadOwns();
   }
 }
 
 void
-HangMonitorChild::ClearPaintWhileInterruptingJS(uint64_t aLayerObserverEpoch)
+HangMonitorChild::ClearPaintWhileInterruptingJS(const LayersObserverEpoch& aEpoch)
 {
   // See Bug 1449662. The body of this function other than assertions
   // has been temporarily removed to diagnose a tab switch spinner
   // problem.
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(XRE_IsContentProcess());
 }
 
@@ -682,41 +682,40 @@ HangMonitorParent::ShutdownOnThread()
   MonitorAutoLock lock(mMonitor);
   mShutdownDone = true;
   mMonitor.Notify();
 }
 
 void
 HangMonitorParent::PaintWhileInterruptingJS(dom::TabParent* aTab,
                                             bool aForceRepaint,
-                                            uint64_t aLayerObserverEpoch)
+                                            const LayersObserverEpoch& aEpoch)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (sShouldPaintWhileInterruptingJS) {
     TabId id = aTab->GetTabId();
-    Dispatch(NewNonOwningRunnableMethod<TabId, bool, uint64_t>(
+    Dispatch(NewNonOwningRunnableMethod<TabId, bool, LayersObserverEpoch>(
       "HangMonitorParent::PaintWhileInterruptingJSOnThread",
       this,
       &HangMonitorParent::PaintWhileInterruptingJSOnThread,
       id,
       aForceRepaint,
-      aLayerObserverEpoch));
+      aEpoch));
   }
 }
 
 void
 HangMonitorParent::PaintWhileInterruptingJSOnThread(TabId aTabId,
                                                     bool aForceRepaint,
-                                                    uint64_t aLayerObserverEpoch)
+                                                    const LayersObserverEpoch& aEpoch)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
   if (mIPCOpen) {
-    Unused << SendPaintWhileInterruptingJS(aTabId, aForceRepaint,
-                                           aLayerObserverEpoch);
+    Unused << SendPaintWhileInterruptingJS(aTabId, aForceRepaint, aEpoch);
   }
 }
 
 void
 HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
   mIPCOpen = false;
@@ -1381,31 +1380,31 @@ ProcessHangMonitor::ClearHang()
     child->ClearHang();
   }
 }
 
 /* static */ void
 ProcessHangMonitor::PaintWhileInterruptingJS(PProcessHangMonitorParent* aParent,
                                              dom::TabParent* aTabParent,
                                              bool aForceRepaint,
-                                             uint64_t aLayerObserverEpoch)
+                                             const layers::LayersObserverEpoch& aEpoch)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   auto parent = static_cast<HangMonitorParent*>(aParent);
-  parent->PaintWhileInterruptingJS(aTabParent, aForceRepaint, aLayerObserverEpoch);
+  parent->PaintWhileInterruptingJS(aTabParent, aForceRepaint, aEpoch);
 }
 
 /* static */ void
-ProcessHangMonitor::ClearPaintWhileInterruptingJS(uint64_t aLayerObserverEpoch)
+ProcessHangMonitor::ClearPaintWhileInterruptingJS(const layers::LayersObserverEpoch& aEpoch)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(XRE_IsContentProcess());
 
   if (HangMonitorChild* child = HangMonitorChild::Get()) {
-    child->ClearPaintWhileInterruptingJS(aLayerObserverEpoch);
+    child->ClearPaintWhileInterruptingJS(aEpoch);
   }
 }
 
 /* static */ void
 ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(XRE_IsContentProcess());
--- a/dom/ipc/ProcessHangMonitor.h
+++ b/dom/ipc/ProcessHangMonitor.h
@@ -19,16 +19,20 @@ class nsIThread;
 
 namespace mozilla {
 
 namespace dom {
 class ContentParent;
 class TabParent;
 } // namespace dom
 
+namespace layers {
+struct LayersObserverEpoch;
+} // namespace layers
+
 class PProcessHangMonitorParent;
 
 class ProcessHangMonitor final
   : public nsIObserver
 {
  private:
   ProcessHangMonitor();
   virtual ~ProcessHangMonitor();
@@ -43,18 +47,18 @@ class ProcessHangMonitor final
   static PProcessHangMonitorParent* AddProcess(dom::ContentParent* aContentParent);
   static void RemoveProcess(PProcessHangMonitorParent* aParent);
 
   static void ClearHang();
 
   static void PaintWhileInterruptingJS(PProcessHangMonitorParent* aParent,
                                        dom::TabParent* aTab,
                                        bool aForceRepaint,
-                                       uint64_t aLayerObserverEpoch);
-  static void ClearPaintWhileInterruptingJS(uint64_t aLayerObserverEpoch);
+                                       const layers::LayersObserverEpoch& aEpoch);
+  static void ClearPaintWhileInterruptingJS(const layers::LayersObserverEpoch& aEpoch);
   static void MaybeStartPaintWhileInterruptingJS();
 
   enum SlowScriptAction {
     Continue,
     Terminate,
     StartDebugger,
     TerminateGlobal,
   };
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -414,28 +414,28 @@ TabChild::TabChild(nsIContentChild* aMan
   , mHasSiblings(false)
   , mIsTransparent(false)
   , mIPCOpen(false)
   , mParentIsActive(false)
   , mDidSetRealShowInfo(false)
   , mDidLoadURLInit(false)
   , mAwaitingLA(false)
   , mSkipKeyPress(false)
-  , mLayerObserverEpoch(1)
+  , mLayersObserverEpoch{1}
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   , mNativeWindowHandle(0)
 #endif
 #if defined(ACCESSIBILITY)
   , mTopLevelDocAccessibleChild(nullptr)
 #endif
   , mPendingDocShellIsActive(false)
   , mPendingDocShellReceivedMessage(false)
   , mPendingRenderLayers(false)
   , mPendingRenderLayersReceivedMessage(false)
-  , mPendingLayerObserverEpoch(0)
+  , mPendingLayersObserverEpoch{0}
   , mPendingDocShellBlockers(0)
   , mWidgetNativeData(0)
 {
   mozilla::HoldJSObjects(this);
 
   nsWeakPtr weakPtrThis(do_GetWeakReference(static_cast<nsITabChild*>(this)));  // for capture by the lambda
   mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId,
                                                    const nsTArray<TouchBehaviorFlags>& aFlags)
@@ -2546,17 +2546,17 @@ TabChild::RemovePendingDocShellBlocker()
   if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
     mPendingDocShellReceivedMessage = false;
     InternalSetDocShellIsActive(mPendingDocShellIsActive);
   }
   if (!mPendingDocShellBlockers && mPendingRenderLayersReceivedMessage) {
     mPendingRenderLayersReceivedMessage = false;
     RecvRenderLayers(mPendingRenderLayers,
                      false /* aForceRepaint */,
-                     mPendingLayerObserverEpoch);
+                     mPendingLayersObserverEpoch);
   }
 }
 
 void
 TabChild::InternalSetDocShellIsActive(bool aIsActive)
 {
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
 
@@ -2577,67 +2577,67 @@ TabChild::RecvSetDocShellIsActive(const 
     return IPC_OK();
   }
 
   InternalSetDocShellIsActive(aIsActive);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-TabChild::RecvRenderLayers(const bool& aEnabled, const bool& aForceRepaint, const uint64_t& aLayerObserverEpoch)
+TabChild::RecvRenderLayers(const bool& aEnabled, const bool& aForceRepaint, const layers::LayersObserverEpoch& aEpoch)
 {
   if (mPendingDocShellBlockers > 0) {
     mPendingRenderLayersReceivedMessage = true;
     mPendingRenderLayers = aEnabled;
-    mPendingLayerObserverEpoch = aLayerObserverEpoch;
+    mPendingLayersObserverEpoch = aEpoch;
     return IPC_OK();
   }
 
   // Since requests to change the rendering state come in from both the hang
   // monitor channel and the PContent channel, we have an ordering problem. This
   // code ensures that we respect the order in which the requests were made and
   // ignore stale requests.
-  if (mLayerObserverEpoch >= aLayerObserverEpoch) {
+  if (mLayersObserverEpoch >= aEpoch) {
     return IPC_OK();
   }
-  mLayerObserverEpoch = aLayerObserverEpoch;
+  mLayersObserverEpoch = aEpoch;
 
   auto clearPaintWhileInterruptingJS = MakeScopeExit([&] {
     // We might force a paint, or we might already have painted and this is a
     // no-op. In either case, once we exit this scope, we need to alert the
     // ProcessHangMonitor that we've finished responding to what might have
     // been a request to force paint. This is so that the BackgroundHangMonitor
     // for force painting can be made to wait again.
     if (aEnabled) {
-      ProcessHangMonitor::ClearPaintWhileInterruptingJS(mLayerObserverEpoch);
+      ProcessHangMonitor::ClearPaintWhileInterruptingJS(mLayersObserverEpoch);
     }
   });
 
   if (aEnabled) {
     ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS();
   }
 
   if (mCompositorOptions) {
     MOZ_ASSERT(mPuppetWidget);
     RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
     MOZ_ASSERT(lm);
 
     // We send the current layer observer epoch to the compositor so that
     // TabParent knows whether a layer update notification corresponds to the
     // latest RecvRenderLayers request that was made.
-    lm->SetLayerObserverEpoch(mLayerObserverEpoch);
+    lm->SetLayersObserverEpoch(mLayersObserverEpoch);
   }
 
   if (aEnabled) {
     if (!aForceRepaint && IsVisible()) {
       // This request is a no-op. In this case, we still want a MozLayerTreeReady
       // notification to fire in the parent (so that it knows that the child has
       // updated its epoch). PaintWhileInterruptingJSNoOp does that.
       if (IPCOpen()) {
-        Unused << SendPaintWhileInterruptingJSNoOp(mLayerObserverEpoch);
+        Unused << SendPaintWhileInterruptingJSNoOp(mLayersObserverEpoch);
         return IPC_OK();
       }
     }
 
     if (!sVisibleTabs) {
       sVisibleTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
     }
     sVisibleTabs->PutEntry(this);
@@ -2833,17 +2833,17 @@ TabChild::InitRenderingState(const Textu
     if (success) {
       MOZ_ASSERT(mLayersConnected == Some(true));
       // Succeeded to create "remote" layer manager
       ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
       gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
       InitAPZState();
       RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
       MOZ_ASSERT(lm);
-      lm->SetLayerObserverEpoch(mLayerObserverEpoch);
+      lm->SetLayersObserverEpoch(mLayersObserverEpoch);
     } else {
       NS_WARNING("Fallback to BasicLayerManager");
       mLayersConnected = Some(false);
     }
 
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
 
@@ -3228,17 +3228,17 @@ TabChild::ReinitRendering()
 
   mLayersConnected = Some(true);
   ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
   gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
 
   InitAPZState();
   RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
   MOZ_ASSERT(lm);
-  lm->SetLayerObserverEpoch(mLayerObserverEpoch);
+  lm->SetLayersObserverEpoch(mLayersObserverEpoch);
 
   nsCOMPtr<nsIDocument> doc(GetDocument());
   doc->NotifyLayerManagerRecreated();
 }
 
 void
 TabChild::ReinitRenderingForDeviceReset()
 {
@@ -3461,27 +3461,27 @@ ScreenIntRect
 TabChild::GetOuterRect()
 {
   LayoutDeviceIntRect outerRect =
     RoundedToInt(mUnscaledOuterRect * mPuppetWidget->GetDefaultScale());
   return ViewAs<ScreenPixel>(outerRect, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
 }
 
 void
-TabChild::PaintWhileInterruptingJS(uint64_t aLayerObserverEpoch,
+TabChild::PaintWhileInterruptingJS(const layers::LayersObserverEpoch& aEpoch,
                                    bool aForceRepaint)
 {
   if (!IPCOpen() || !mPuppetWidget || !mPuppetWidget->HasLayerManager()) {
     // Don't bother doing anything now. Better to wait until we receive the
     // message on the PContent channel.
     return;
   }
 
   nsAutoScriptBlocker scriptBlocker;
-  RecvRenderLayers(true /* aEnabled */, aForceRepaint, aLayerObserverEpoch);
+  RecvRenderLayers(true /* aEnabled */, aForceRepaint, aEpoch);
 }
 
 void
 TabChild::BeforeUnloadAdded()
 {
   // Don't bother notifying the parent if we don't have an IPC link open.
   if (mBeforeUnloadListeners == 0 && IPCOpen()) {
     SendSetHasBeforeUnload(true);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -651,20 +651,20 @@ public:
                             const int& aArg);
   void StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics);
   void ZoomToRect(const uint32_t& aPresShellId,
                   const FrameMetrics::ViewID& aViewId,
                   const CSSRect& aRect,
                   const uint32_t& aFlags);
 
   // Request that the docshell be marked as active.
-  void PaintWhileInterruptingJS(uint64_t aLayerObserverEpoch,
+  void PaintWhileInterruptingJS(const layers::LayersObserverEpoch& aEpoch,
                                 bool aForceRepaint);
 
-  uint64_t LayerObserverEpoch() const { return mLayerObserverEpoch; }
+  layers::LayersObserverEpoch LayersObserverEpoch() const { return mLayersObserverEpoch; }
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   uintptr_t GetNativeWindowHandle() const { return mNativeWindowHandle; }
 #endif
 
   // These methods return `true` if this TabChild is currently awaiting a
   // Large-Allocation header.
   bool StopAwaitingLargeAlloc();
@@ -727,17 +727,17 @@ protected:
   virtual PRenderFrameChild* AllocPRenderFrameChild() override;
 
   virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override;
 
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
 
   virtual mozilla::ipc::IPCResult RecvSetDocShellIsActive(const bool& aIsActive) override;
 
-  virtual mozilla::ipc::IPCResult RecvRenderLayers(const bool& aEnabled, const bool& aForce, const uint64_t& aLayerObserverEpoch) override;
+  virtual mozilla::ipc::IPCResult RecvRenderLayers(const bool& aEnabled, const bool& aForce, const layers::LayersObserverEpoch& aEpoch) override;
 
   virtual mozilla::ipc::IPCResult RecvNavigateByKey(const bool& aForward,
                                                     const bool& aForDocumentNavigation) override;
 
   virtual mozilla::ipc::IPCResult RecvRequestNotifyAfterRemotePaint() override;
 
   virtual mozilla::ipc::IPCResult RecvSuppressDisplayport(const bool& aEnabled) override;
 
@@ -890,17 +890,17 @@ private:
   nsDeque mToBeDispatchedMouseData;
 
   CoalescedWheelData mCoalescedWheelData;
   RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;
 
   RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
 
   // The most recently seen layer observer epoch in RecvSetDocShellIsActive.
-  uint64_t mLayerObserverEpoch;
+  layers::LayersObserverEpoch mLayersObserverEpoch;
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   // The handle associated with the native window that contains this tab
   uintptr_t mNativeWindowHandle;
 #endif // defined(XP_WIN)
 
 #if defined(ACCESSIBILITY)
   PDocAccessibleChild* mTopLevelDocAccessibleChild;
@@ -913,17 +913,17 @@ private:
   // It is possible, however, for the parent process to send commands to
   // change those states while the DocShell is blocked. We store those
   // states temporarily as "pending", and only apply them once the DocShell
   // is no longer blocked.
   bool mPendingDocShellIsActive;
   bool mPendingDocShellReceivedMessage;
   bool mPendingRenderLayers;
   bool mPendingRenderLayersReceivedMessage;
-  uint64_t mPendingLayerObserverEpoch;
+  layers::LayersObserverEpoch mPendingLayersObserverEpoch;
   // When mPendingDocShellBlockers is greater than 0, the DocShell is blocked,
   // and once it reaches 0, it is no longer blocked.
   uint32_t mPendingDocShellBlockers;
 
   WindowsHandle mWidgetNativeData;
 
   // This state is used to keep track of the current visible tabs (the ones rendering
   // layers). There may be more than one if there are multiple browser windows open, or
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -164,17 +164,17 @@ TabParent::TabParent(nsIContentParent* a
   , mCursor(eCursorInvalid)
   , mCustomCursorHotspotX(0)
   , mCustomCursorHotspotY(0)
   , mTabSetsCursor(false)
   , mHasContentOpener(false)
 #ifdef DEBUG
   , mActiveSupressDisplayportCount(0)
 #endif
-  , mLayerTreeEpoch(1)
+  , mLayerTreeEpoch{1}
   , mPreserveLayers(false)
   , mRenderLayers(true)
   , mHasLayers(false)
   , mHasPresented(false)
   , mHasBeforeUnload(false)
   , mIsMouseEnterIntoWidgetEventSuppressed(false)
   , mIsActiveRecordReplayTab(false)
 {
@@ -2892,17 +2892,17 @@ TabParent::SetRenderLayers(bool aEnabled
 {
   if (aEnabled == mRenderLayers) {
     if (aEnabled && mHasLayers && mPreserveLayers) {
       // RenderLayers might be called when we've been preserving layers,
       // and already had layers uploaded. In that case, the MozLayerTreeReady
       // event will not naturally arrive, which can confuse the front-end
       // layer. So we fire the event here.
       RefPtr<TabParent> self = this;
-      uint64_t epoch = mLayerTreeEpoch;
+      LayersObserverEpoch epoch = mLayerTreeEpoch;
       NS_DispatchToMainThread(NS_NewRunnableFunction(
         "dom::TabParent::RenderLayers",
         [self, epoch] () {
           MOZ_ASSERT(NS_IsMainThread());
           self->LayerTreeUpdate(epoch, true);
         }));
     }
 
@@ -2943,17 +2943,17 @@ TabParent::ForceRepaint()
   return NS_OK;
 }
 
 void
 TabParent::SetRenderLayersInternal(bool aEnabled, bool aForceRepaint)
 {
   // Increment the epoch so that layer tree updates from previous
   // RenderLayers requests are ignored.
-  mLayerTreeEpoch++;
+  mLayerTreeEpoch = mLayerTreeEpoch.Next();
 
   Unused << SendRenderLayers(aEnabled, aForceRepaint, mLayerTreeEpoch);
 
   // Ask the child to repaint using the PHangMonitor channel/thread (which may
   // be less congested).
   if (aEnabled) {
     ContentParent* cp = Manager()->AsContentParent();
     cp->PaintTabWhileInterruptingJS(this, aForceRepaint, mLayerTreeEpoch);
@@ -3054,17 +3054,17 @@ TabParent::TransmitPermissionsForPrincip
 NS_IMETHODIMP
 TabParent::GetHasBeforeUnload(bool* aResult)
 {
   *aResult = mHasBeforeUnload;
   return NS_OK;
 }
 
 void
-TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
+TabParent::LayerTreeUpdate(const LayersObserverEpoch& aEpoch, bool aActive)
 {
   // Ignore updates from old epochs. They might tell us that layers are
   // available when we've already sent a message to clear them. We can't trust
   // the update in that case since layers could disappear anytime after that.
   if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
     return;
   }
 
@@ -3084,22 +3084,22 @@ TabParent::LayerTreeUpdate(uint64_t aEpo
     event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false);
   }
   event->SetTrusted(true);
   event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   mFrameElement->DispatchEvent(*event);
 }
 
 mozilla::ipc::IPCResult
-TabParent::RecvPaintWhileInterruptingJSNoOp(const uint64_t& aLayerObserverEpoch)
+TabParent::RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch)
 {
   // We sent a PaintWhileInterruptingJS message when layers were already visible. In this
   // case, we should act as if an update occurred even though we already have
   // the layers.
-  LayerTreeUpdate(aLayerObserverEpoch, true);
+  LayerTreeUpdate(aEpoch, true);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvRemotePaintIsReady()
 {
   nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
   if (!target) {
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -553,17 +553,17 @@ public:
 
   void SetInitedByParent() { mInitedByParent = true; }
 
   bool IsInitedByParent() const { return mInitedByParent; }
 
   bool SendLoadRemoteScript(const nsString& aURL,
                             const bool& aRunInGlobalScope);
 
-  void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
+  void LayerTreeUpdate(const LayersObserverEpoch& aEpoch, bool aActive);
 
   virtual mozilla::ipc::IPCResult
   RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
                         const uint32_t& aAction,
                         const OptionalShmem& aVisualDnDData,
                         const uint32_t& aStride, const gfx::SurfaceFormat& aFormat,
                         const LayoutDeviceIntRect& aDragRect,
                         const nsCString& aPrincipalURISpec) override;
@@ -615,17 +615,17 @@ protected:
   virtual PRenderFrameParent* AllocPRenderFrameParent() override;
 
   virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) override;
 
   virtual mozilla::ipc::IPCResult RecvRemotePaintIsReady() override;
 
   virtual mozilla::ipc::IPCResult RecvRemoteIsReadyToHandleInputEvents() override;
 
-  virtual mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(const uint64_t& aLayerObserverEpoch) override;
+  virtual mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch) override;
 
   virtual mozilla::ipc::IPCResult RecvSetDimensions(const uint32_t& aFlags,
                                                     const int32_t& aX, const int32_t& aY,
                                                     const int32_t& aCx, const int32_t& aCy) override;
 
   virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) override;
 
   ContentCacheInParent mContentCache;
@@ -752,17 +752,17 @@ private:
   // to dispatch events.
   typedef nsDataHashtable<nsUint64HashKey, TabParent*> LayerToTabParentTable;
   static LayerToTabParentTable* sLayerToTabParentTable;
 
   static void AddTabParentToTable(layers::LayersId aLayersId, TabParent* aTabParent);
 
   static void RemoveTabParentFromTable(layers::LayersId aLayersId);
 
-  uint64_t mLayerTreeEpoch;
+  LayersObserverEpoch mLayerTreeEpoch;
 
   // If this flag is set, then the tab's layers will be preserved even when
   // the tab's docshell is inactive.
   bool mPreserveLayers;
 
   // Holds the most recent value passed to the RenderLayers function. This
   // does not necessarily mean that the layers have finished rendering
   // and have uploaded - for that, use mHasLayers.
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -681,17 +681,17 @@ public:
   }
 
   uint32_t GetAndClearPaintedPixelCount() {
     uint32_t count = mPaintedPixelCount;
     mPaintedPixelCount = 0;
     return count;
   }
 
-  virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) {}
+  virtual void SetLayersObserverEpoch(LayersObserverEpoch aEpoch) {}
 
   virtual void DidComposite(TransactionId aTransactionId,
                             const mozilla::TimeStamp& aCompositeStart,
                             const mozilla::TimeStamp& aCompositeEnd) {}
 
   virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
   virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
 
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -134,16 +134,44 @@ struct TransactionId {
   }
 
   bool operator==(const TransactionId& aOther) const
   {
     return mId == aOther.mId;
   }
 };
 
+struct LayersObserverEpoch {
+  uint64_t mId;
+
+  MOZ_MUST_USE LayersObserverEpoch Next() const {
+    return LayersObserverEpoch{mId + 1};
+  }
+
+  bool operator<=(const LayersObserverEpoch& aOther) const
+  {
+    return mId <= aOther.mId;
+  }
+
+  bool operator>=(const LayersObserverEpoch& aOther) const
+  {
+    return mId >= aOther.mId;
+  }
+
+  bool operator==(const LayersObserverEpoch& aOther) const
+  {
+    return mId == aOther.mId;
+  }
+
+  bool operator!=(const LayersObserverEpoch& aOther) const
+  {
+    return mId != aOther.mId;
+  }
+};
+
 enum class LayersBackend : int8_t {
   LAYERS_NONE = 0,
   LAYERS_BASIC,
   LAYERS_OPENGL,
   LAYERS_D3D11,
   LAYERS_CLIENT,
   LAYERS_WR,
   LAYERS_LAST
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -927,19 +927,19 @@ ClientLayerManager::GetBackendName(nsASt
 
 bool
 ClientLayerManager::AsyncPanZoomEnabled() const
 {
   return mWidget && mWidget->AsyncPanZoomEnabled();
 }
 
 void
-ClientLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
+ClientLayerManager::SetLayersObserverEpoch(LayersObserverEpoch aEpoch)
 {
-  mForwarder->SetLayerObserverEpoch(aLayerObserverEpoch);
+  mForwarder->SetLayersObserverEpoch(aEpoch);
 }
 
 void
 ClientLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
 {
   if (!mDidCompositeObservers.Contains(aObserver)) {
     mDidCompositeObservers.AppendElement(aObserver);
   }
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -237,17 +237,17 @@ public:
   virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override;
 
   virtual TransactionId GetLastTransactionId() override { return mLatestTransactionId; }
 
   float RequestProperty(const nsAString& aProperty) override;
 
   bool AsyncPanZoomEnabled() const override;
 
-  virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
+  virtual void SetLayersObserverEpoch(LayersObserverEpoch aEpoch) override;
 
   virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) override;
   virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) override;
 
   virtual already_AddRefed<PersistentBufferProvider>
   CreatePersistentBufferProvider(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat) override;
 
   static PaintTiming* MaybeGetPaintTiming(LayerManager* aManager) {
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -858,19 +858,19 @@ CompositorBridgeChild::RecvParentAsyncMe
         NS_ERROR("unknown AsyncParentMessageData type");
         return IPC_FAIL_NO_REASON(this);
     }
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-CompositorBridgeChild::RecvObserveLayerUpdate(const LayersId& aLayersId,
-                                              const uint64_t& aEpoch,
-                                              const bool& aActive)
+CompositorBridgeChild::RecvObserveLayersUpdate(const LayersId& aLayersId,
+                                               const LayersObserverEpoch& aEpoch,
+                                               const bool& aActive)
 {
   // This message is sent via the window compositor, not the tab compositor -
   // however it still has a layers id.
   MOZ_ASSERT(aLayersId.IsValid());
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (RefPtr<dom::TabParent> tab = dom::TabParent::GetTabParentFromLayersId(aLayersId)) {
     tab->LayerTreeUpdate(aEpoch, aActive);
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -311,19 +311,19 @@ private:
                                                                    const uint32_t& aAPZCId) override;
 
   virtual mozilla::ipc::IPCResult RecvReleaseSharedCompositorFrameMetrics(const ViewID& aId,
                                                                           const uint32_t& aAPZCId) override;
 
   virtual mozilla::ipc::IPCResult
   RecvRemotePaintIsReady() override;
 
-  mozilla::ipc::IPCResult RecvObserveLayerUpdate(const LayersId& aLayersId,
-                                                 const uint64_t& aEpoch,
-                                                 const bool& aActive) override;
+  mozilla::ipc::IPCResult RecvObserveLayersUpdate(const LayersId& aLayersId,
+                                                  const LayersObserverEpoch& aEpoch,
+                                                  const bool& aActive) override;
 
   virtual mozilla::ipc::IPCResult
   RecvNotifyWebRenderError(const WebRenderError& aError) override;
 
   uint64_t GetNextResourceId();
 
   void ClearSharedFrameMetricsData(LayersId aLayersId);
 
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -133,17 +133,17 @@ public:
   ShmemAllocator* AsShmemAllocator() override { return this; }
 
   CompositorBridgeParentBase* AsCompositorBridgeParentBase() override { return this; }
 
   mozilla::ipc::IPCResult RecvSyncWithCompositor() override { return IPC_OK(); }
 
   mozilla::ipc::IPCResult Recv__delete__() override { return IPC_OK(); }
 
-  virtual void ObserveLayerUpdate(LayersId aLayersId, uint64_t aEpoch, bool aActive) = 0;
+  virtual void ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive) = 0;
 
   virtual void DidComposite(LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) = 0;
 
   // HostIPCAllocator
   base::ProcessId GetChildProcessId() override;
   void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
   void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
 
@@ -278,17 +278,17 @@ public:
                               const wr::Epoch& aEpoch,
                               TimeStamp& aCompositeStart,
                               TimeStamp& aCompositeEnd);
   RefPtr<AsyncImagePipelineManager> GetAsyncImagePipelineManager() const;
 
   PCompositorWidgetParent* AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData) override;
   bool DeallocPCompositorWidgetParent(PCompositorWidgetParent* aActor) override;
 
-  void ObserveLayerUpdate(LayersId aLayersId, uint64_t aEpoch, bool aActive) override { }
+  void ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive) override { }
 
   /**
    * This forces the is-first-paint flag to true. This is intended to
    * be called by the widget code when it loses its viewport information
    * (or for whatever reason wants to refresh the viewport information).
    * The information refresh happens because the compositor will call
    * SetFirstPaintViewport on the next frame of composition.
    */
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -365,17 +365,17 @@ CrossProcessCompositorBridgeParent::Shad
   if(mNotifyAfterRemotePaint)  {
     Unused << SendRemotePaintIsReady();
     mNotifyAfterRemotePaint = false;
   }
 
   if (aLayerTree->ShouldParentObserveEpoch()) {
     // Note that we send this through the window compositor, since this needs
     // to reach the widget owning the tab.
-    Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
+    Unused << state->mParent->SendObserveLayersUpdate(id, aLayerTree->GetChildEpoch(), true);
   }
 
   aLayerTree->SetPendingTransactionId(aInfo.id(), aInfo.refreshStart(), aInfo.transactionStart(), aInfo.fwdTime());
 }
 
 void
 CrossProcessCompositorBridgeParent::DidComposite(
   LayersId aId,
@@ -424,17 +424,17 @@ CrossProcessCompositorBridgeParent::Noti
   LayersId id = aLayerTree->GetId();
   MOZ_ASSERT(id.IsValid());
 
   const CompositorBridgeParent::LayerTreeState* state =
     CompositorBridgeParent::GetIndirectShadowTree(id);
   if (state && state->mParent) {
     // Note that we send this through the window compositor, since this needs
     // to reach the widget owning the tab.
-    Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false);
+    Unused << state->mParent->SendObserveLayersUpdate(id, aLayerTree->GetChildEpoch(), false);
   }
 }
 
 bool
 CrossProcessCompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
                                                       const TimeStamp& aTime)
 {
   MOZ_ASSERT(aId.IsValid());
@@ -643,23 +643,23 @@ CrossProcessCompositorBridgeParent::Upda
   if (!state || !state->mParent) {
     return;
   }
 
   state->mParent->UpdatePaintTime(aLayerTree, aPaintTime);
 }
 
 void
-CrossProcessCompositorBridgeParent::ObserveLayerUpdate(LayersId aLayersId, uint64_t aEpoch, bool aActive)
+CrossProcessCompositorBridgeParent::ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive)
 {
   MOZ_ASSERT(aLayersId.IsValid());
 
   CompositorBridgeParent::LayerTreeState* state =
     CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
   if (!state || !state->mParent) {
     return;
   }
 
-  Unused << state->mParent->SendObserveLayerUpdate(aLayersId, aEpoch, aActive);
+  Unused << state->mParent->SendObserveLayersUpdate(aLayersId, aEpoch, aActive);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
@@ -146,17 +146,17 @@ public:
   void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override;
 
   PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
                                                       const LayoutDeviceIntSize& aSize,
                                                       TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                                       wr::IdNamespace* aIdNamespace) override;
   bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
 
-  void ObserveLayerUpdate(LayersId aLayersId, uint64_t aEpoch, bool aActive) override;
+  void ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive) override;
 
   bool IsRemote() const override {
     return true;
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CrossProcessCompositorBridgeParent();
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -50,18 +50,18 @@ LayerTransactionParent::LayerTransaction
                                                CompositorBridgeParentBase* aBridge,
                                                CompositorAnimationStorage* aAnimStorage,
                                                LayersId aId,
                                                TimeDuration aVsyncRate)
   : mLayerManager(aManager)
   , mCompositorBridge(aBridge)
   , mAnimStorage(aAnimStorage)
   , mId(aId)
-  , mChildEpoch(0)
-  , mParentEpoch(0)
+  , mChildEpoch{0}
+  , mParentEpoch{0}
   , mVsyncRate(aVsyncRate)
   , mPendingTransaction{0}
   , mDestroyed(false)
   , mIPCOpen(false)
 {
   MOZ_ASSERT(mId.IsValid());
 }
 
@@ -642,19 +642,19 @@ LayerTransactionParent::SetLayerAttribut
   default:
     MOZ_CRASH("not reached");
   }
 
   return true;
 }
 
 mozilla::ipc::IPCResult
-LayerTransactionParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
+LayerTransactionParent::RecvSetLayersObserverEpoch(const LayersObserverEpoch& aChildEpoch)
 {
-  mChildEpoch = aLayerObserverEpoch;
+  mChildEpoch = aChildEpoch;
   return IPC_OK();
 }
 
 bool
 LayerTransactionParent::ShouldParentObserveEpoch()
 {
   if (mParentEpoch == mChildEpoch) {
     return false;
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -57,17 +57,17 @@ protected:
 public:
   void Destroy();
 
   void SetLayerManager(HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage);
 
   LayersId GetId() const { return mId; }
   Layer* GetRoot() const { return mRoot; }
 
-  uint64_t GetChildEpoch() const { return mChildEpoch; }
+  LayersObserverEpoch GetChildEpoch() const { return mChildEpoch; }
   bool ShouldParentObserveEpoch();
 
   ShmemAllocator* AsShmemAllocator() override { return this; }
 
   bool AllocShmem(size_t aSize,
                   ipc::SharedMemory::SharedMemoryType aType,
                   ipc::Shmem* aShmem) override;
 
@@ -110,17 +110,17 @@ protected:
   mozilla::ipc::IPCResult RecvShutdown() override;
   mozilla::ipc::IPCResult RecvShutdownSync() override;
 
   mozilla::ipc::IPCResult RecvPaintTime(const TransactionId& aTransactionId,
                                         const TimeDuration& aPaintTime) override;
 
   mozilla::ipc::IPCResult RecvUpdate(const TransactionInfo& aInfo) override;
 
-  mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
+  mozilla::ipc::IPCResult RecvSetLayersObserverEpoch(const LayersObserverEpoch& aChildEpoch) override;
   mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseLayer(const LayerHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   mozilla::ipc::IPCResult RecvClearCachedResources() override;
   mozilla::ipc::IPCResult RecvScheduleComposite() override;
   mozilla::ipc::IPCResult RecvSetTestSampleTime(const TimeStamp& aTime) override;
@@ -193,18 +193,18 @@ private:
   nsRefPtrHashtable<nsUint64HashKey, Layer> mLayerMap;
 
   LayersId mId;
 
   // These fields keep track of the latest epoch values in the child and the
   // parent. mChildEpoch is the latest epoch value received from the child.
   // mParentEpoch is the latest epoch value that we have told TabParent about
   // (via ObserveLayerUpdate).
-  uint64_t mChildEpoch;
-  uint64_t mParentEpoch;
+  LayersObserverEpoch mChildEpoch;
+  LayersObserverEpoch mParentEpoch;
 
   TimeDuration mVsyncRate;
 
   TransactionId mPendingTransaction;
   TimeStamp mRefreshStartTime;
   TimeStamp mTxnStartTime;
   TimeStamp mFwdTime;
 
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -39,16 +39,21 @@ struct ParamTraits<mozilla::layers::Laye
 {};
 
 template <>
 struct ParamTraits<mozilla::layers::TransactionId>
   : public PlainOldDataSerializer<mozilla::layers::TransactionId>
 {};
 
 template <>
+struct ParamTraits<mozilla::layers::LayersObserverEpoch>
+  : public PlainOldDataSerializer<mozilla::layers::LayersObserverEpoch>
+{};
+
+template <>
 struct ParamTraits<mozilla::layers::LayersBackend>
   : public ContiguousEnumSerializer<
              mozilla::layers::LayersBackend,
              mozilla::layers::LayersBackend::LAYERS_NONE,
              mozilla::layers::LayersBackend::LAYERS_LAST>
 {};
 
 template <>
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -38,16 +38,17 @@ using class mozilla::TimeStamp from "moz
 using class mozilla::layers::FrameUniformityData from "mozilla/layers/FrameUniformityData.h";
 using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using base::ProcessId from "base/process.h";
 using mozilla::wr::MaybeExternalImageId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::WebRenderError from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 
 /**
  * The PCompositorBridge protocol is a top-level protocol for the compositor.
@@ -128,17 +129,17 @@ child:
   /**
    * Hides all registered plugin widgets associated with a particular chrome
    * widget.
    */
   async HideAllPlugins(uintptr_t aParentWidget);
 
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
-  async ObserveLayerUpdate(LayersId aLayersId, uint64_t aEpoch, bool aActive);
+  async ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch, bool aActive);
 
 parent:
   async __delete__();
 
   // Must be called before Initialize().
   async PCompositorWidget(CompositorWidgetInitData aInitData);
 
   // When out-of-process, this must be called to finish initialization.
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -18,16 +18,17 @@ using struct mozilla::layers::TextureInf
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::LayerHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
@@ -49,17 +50,17 @@ sync protocol PLayerTransaction {
 
 parent:
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   async Update(TransactionInfo txn);
 
   async PaintTime(TransactionId id, TimeDuration paintTime);
 
-  async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
+  async SetLayersObserverEpoch(LayersObserverEpoch aChildEpoch);
 
   // Create a new Compositable.
   async NewCompositable(CompositableHandle handle, TextureInfo info);
 
   // Release an object that is no longer in use.
   async ReleaseLayer(LayerHandle layer);
   async ReleaseCompositable(CompositableHandle compositable);
 
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -19,16 +19,17 @@ using mozilla::layers::ScrollUpdatesMap 
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::wr::BuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollData.h";
 using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
+using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 sync protocol PWebRenderBridge
 {
   manager PCompositorBridge;
@@ -46,17 +47,17 @@ parent:
                        IdNamespace aIdNamespace, TimeStamp refreshStartTime, TimeStamp txnStartTime, TimeStamp fwdTime);
   async EmptyTransaction(FocusTarget focusTarget, ScrollUpdatesMap scrollUpdates, uint32_t aPaintSequenceNumber,
                          WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
                          IdNamespace aIdNamespace, TimeStamp refreshStartTime, TimeStamp txnStartTime, TimeStamp fwdTime);
   async SetFocusTarget(FocusTarget focusTarget);
   async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync GetSnapshot(PTexture texture);
-  async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
+  async SetLayersObserverEpoch(LayersObserverEpoch childEpoch);
   async ClearCachedResources();
   // Schedule a composite if one isn't already scheduled.
   async ScheduleComposite();
   // Save the frame capture to disk
   async Capture();
 
   // Replacement for PCompositorBridge::SyncWithCompositor, but for WR. We need
   // it on PWebRenderBridge because it associated with a particular top-level
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -803,22 +803,22 @@ ShadowLayerForwarder::FindCompositable(c
   CompositableClient* client = nullptr;
   if (!mCompositables.Get(aHandle.Value(), &client)) {
     return nullptr;
   }
   return client;
 }
 
 void
-ShadowLayerForwarder::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
+ShadowLayerForwarder::SetLayersObserverEpoch(LayersObserverEpoch aEpoch)
 {
   if (!IPCOpen()) {
     return;
   }
-  Unused << mShadowManager->SendSetLayerObserverEpoch(aLayerObserverEpoch);
+  Unused << mShadowManager->SendSetLayersObserverEpoch(aEpoch);
 }
 
 void
 ShadowLayerForwarder::UpdateTextureLocks()
 {
 #ifdef XP_DARWIN
   if (!IPCOpen()) {
     return;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -338,17 +338,17 @@ public:
    */
   void SetIsFirstPaint() { mIsFirstPaint = true; }
 
   /**
    * Set the current focus target to be sent with the next paint.
    */
   void SetFocusTarget(const FocusTarget& aFocusTarget) { mFocusTarget = aFocusTarget; }
 
-  void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
+  void SetLayersObserverEpoch(LayersObserverEpoch aEpoch);
 
   static void PlatformSyncBeforeUpdate();
 
   virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
                                       gfxContentType aContent,
                                       SurfaceDescriptor* aBuffer) override;
 
   virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -189,18 +189,18 @@ WebRenderBridgeParent::WebRenderBridgePa
   : mCompositorBridge(aCompositorBridge)
   , mPipelineId(aPipelineId)
   , mWidget(aWidget)
   , mApi(aApi)
   , mAsyncImageManager(aImageMgr)
   , mCompositorScheduler(aScheduler)
   , mAnimStorage(aAnimStorage)
   , mVsyncRate(aVsyncRate)
-  , mChildLayerObserverEpoch(0)
-  , mParentLayerObserverEpoch(0)
+  , mChildLayersObserverEpoch{0}
+  , mParentLayersObserverEpoch{0}
   , mWrEpoch{0}
   , mIdNamespace(aApi->GetNamespace())
   , mPaused(false)
   , mDestroyed(false)
   , mForceRendering(false)
   , mReceivedDisplayList(false)
 {
   MOZ_ASSERT(mAsyncImageManager);
@@ -210,18 +210,18 @@ WebRenderBridgeParent::WebRenderBridgePa
     MOZ_ASSERT(!mCompositorScheduler);
     mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
   }
 }
 
 WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId)
   : mCompositorBridge(nullptr)
   , mPipelineId(aPipelineId)
-  , mChildLayerObserverEpoch(0)
-  , mParentLayerObserverEpoch(0)
+  , mChildLayersObserverEpoch{0}
+  , mParentLayersObserverEpoch{0}
   , mWrEpoch{0}
   , mIdNamespace{0}
   , mPaused(false)
   , mDestroyed(true)
   , mForceRendering(false)
   , mReceivedDisplayList(false)
 {
 }
@@ -824,17 +824,17 @@ WebRenderBridgeParent::RecvSetDisplayLis
     // though DisplayList was not pushed to webrender.
     if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
       TimeStamp now = TimeStamp::Now();
       cbp->NotifyPipelineRendered(mPipelineId, wrEpoch, now, now);
     }
   }
 
   if (ShouldParentObserveEpoch()) {
-    mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
+    mCompositorBridge->ObserveLayersUpdate(GetLayersId(), mChildLayersObserverEpoch, true);
   }
 
   wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
   wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -908,17 +908,17 @@ WebRenderBridgeParent::RecvEmptyTransact
     MOZ_ASSERT(mPendingTransactionIds.size() == 1);
     if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
       TimeStamp now = TimeStamp::Now();
       cbp->NotifyPipelineRendered(mPipelineId, mWrEpoch, now, now);
     }
   }
 
   if (ShouldParentObserveEpoch()) {
-    mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
+    mCompositorBridge->ObserveLayersUpdate(GetLayersId(), mChildLayersObserverEpoch, true);
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetFocusTarget(const FocusTarget& aFocusTarget)
 {
@@ -1216,32 +1216,32 @@ WebRenderBridgeParent::ReleaseTextureOfI
   }
   if (wrTexture) {
     mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, wrTexture);
   }
   mTextureHosts.erase(id);
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
+WebRenderBridgeParent::RecvSetLayersObserverEpoch(const LayersObserverEpoch& aChildEpoch)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
-  mChildLayerObserverEpoch = aLayerObserverEpoch;
+  mChildLayersObserverEpoch = aChildEpoch;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvClearCachedResources()
 {
   if (mDestroyed) {
     return IPC_OK();
   }
-  mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), false);
+  mCompositorBridge->ObserveLayersUpdate(GetLayersId(), mChildLayersObserverEpoch, false);
 
   // Clear resources
   wr::TransactionBuilder txn;
   txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
   mApi->SendTransaction(txn);
   // Schedule generate frame to clean up Pipeline
   ScheduleGenerateFrame();
   // Remove animations.
@@ -1776,21 +1776,21 @@ WebRenderBridgeParent::ClearResources()
   mAsyncImageManager = nullptr;
   mApi = nullptr;
   mCompositorBridge = nullptr;
 }
 
 bool
 WebRenderBridgeParent::ShouldParentObserveEpoch()
 {
-  if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
+  if (mParentLayersObserverEpoch == mChildLayersObserverEpoch) {
     return false;
   }
 
-  mParentLayerObserverEpoch = mChildLayerObserverEpoch;
+  mParentLayersObserverEpoch = mChildLayersObserverEpoch;
   return true;
 }
 
 void
 WebRenderBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
 {
   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
 }
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -101,17 +101,17 @@ public:
                                                const wr::IdNamespace& aIdNamespace,
                                                const TimeStamp& aRefreshStartTime,
                                                const TimeStamp& aTxnStartTime,
                                                const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvSetFocusTarget(const FocusTarget& aFocusTarget) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
   mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
 
-  mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
+  mozilla::ipc::IPCResult RecvSetLayersObserverEpoch(const LayersObserverEpoch& aChildEpoch) override;
 
   mozilla::ipc::IPCResult RecvClearCachedResources() override;
   mozilla::ipc::IPCResult RecvScheduleComposite() override;
   mozilla::ipc::IPCResult RecvCapture() override;
   mozilla::ipc::IPCResult RecvSyncWithCompositor() override;
 
   mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
                                                      nsTArray<ScrollableLayerGuid>&& aTargets) override;
@@ -226,17 +226,16 @@ private:
   void RemoveExternalImageId(const ExternalImageId& aImageId);
   void ReleaseTextureOfImage(const wr::ImageKey& aKey);
 
   LayersId GetLayersId() const;
   void ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands,
                                       wr::TransactionBuilder& aTxn);
 
   void ClearResources();
-  uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
   mozilla::ipc::IPCResult HandleShutdown();
 
   // Returns true if there is any animation (including animations in delay
   // phase).
   bool AdvanceAnimations();
   bool SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
@@ -299,21 +298,21 @@ private:
   std::unordered_set<uint64_t> mActiveAnimations;
   std::unordered_map<uint64_t, RefPtr<WebRenderImageHost>> mAsyncCompositables;
   std::unordered_map<uint64_t, CompositableTextureHostRef> mTextureHosts;
   std::unordered_set<uint64_t> mSharedSurfaceIds;
 
   TimeDuration mVsyncRate;
   TimeStamp mPreviousFrameTimeStamp;
   // These fields keep track of the latest layer observer epoch values in the child and the
-  // parent. mChildLayerObserverEpoch is the latest epoch value received from the child.
-  // mParentLayerObserverEpoch is the latest epoch value that we have told TabParent about
+  // parent. mChildLayersObserverEpoch is the latest epoch value received from the child.
+  // mParentLayersObserverEpoch is the latest epoch value that we have told TabParent about
   // (via ObserveLayerUpdate).
-  uint64_t mChildLayerObserverEpoch;
-  uint64_t mParentLayerObserverEpoch;
+  LayersObserverEpoch mChildLayersObserverEpoch;
+  LayersObserverEpoch mParentLayersObserverEpoch;
 
   std::queue<PendingTransactionId> mPendingTransactionIds;
   std::queue<CompositorAnimationIdsForEpoch> mCompositorAnimationsToDelete;
   wr::Epoch mWrEpoch;
   wr::IdNamespace mIdNamespace;
 
   bool mPaused;
   bool mDestroyed;
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -475,20 +475,20 @@ WebRenderLayerManager::DiscardLocalImage
 {
   // Removes images but doesn't tell the parent side about them
   // This is useful in empty / failed transactions where we created
   // image keys but didn't tell the parent about them yet.
   mImageKeysToDelete.Clear();
 }
 
 void
-WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
+WebRenderLayerManager::SetLayersObserverEpoch(LayersObserverEpoch aEpoch)
 {
   if (WrBridge()->IPCOpen()) {
-    WrBridge()->SendSetLayerObserverEpoch(aLayerObserverEpoch);
+    WrBridge()->SendSetLayersObserverEpoch(aEpoch);
   }
 }
 
 void
 WebRenderLayerManager::DidComposite(TransactionId aTransactionId,
                                     const mozilla::TimeStamp& aCompositeStart,
                                     const mozilla::TimeStamp& aCompositeEnd)
 {
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -86,17 +86,17 @@ public:
   already_AddRefed<PaintedLayer> CreatePaintedLayer() override { return nullptr; }
   already_AddRefed<ContainerLayer> CreateContainerLayer() override { return nullptr; }
   already_AddRefed<ImageLayer> CreateImageLayer() override { return nullptr; }
   already_AddRefed<ColorLayer> CreateColorLayer() override { return nullptr; }
   already_AddRefed<CanvasLayer> CreateCanvasLayer() override { return nullptr; }
 
   virtual bool NeedsWidgetInvalidation() override { return false; }
 
-  virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
+  virtual void SetLayersObserverEpoch(LayersObserverEpoch aEpoch) override;
 
   virtual void DidComposite(TransactionId aTransactionId,
                             const mozilla::TimeStamp& aCompositeStart,
                             const mozilla::TimeStamp& aCompositeEnd) override;
 
   virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
   virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) override;
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override;