Merge autoland to mozilla-central. a=merge
authorMarian-Vasile Laza <mlaza@mozilla.com>
Wed, 01 Dec 2021 07:02:05 +0200
changeset 600693 89800efd9e5cfcf0146767961a63d5c4e2a86e2c
parent 600683 15c1262d6e8f4524fa63dcc9cc2572038ffb3a92 (current diff)
parent 600692 bdb2ea56b4ec89e0c653ebe1597b0dfb016efd5a (diff)
child 600724 85b39e03c1eb3b10764e0dcba9044e3c4c6469f6
push id39026
push usermlaza@mozilla.com
push dateWed, 01 Dec 2021 05:05:07 +0000
treeherdermozilla-central@89800efd9e5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone96.0a1
first release with
nightly linux32
89800efd9e5c / 96.0a1 / 20211201050507 / files
nightly linux64
89800efd9e5c / 96.0a1 / 20211201050507 / files
nightly mac
89800efd9e5c / 96.0a1 / 20211201050507 / files
nightly win32
89800efd9e5c / 96.0a1 / 20211201050507 / files
nightly win64
89800efd9e5c / 96.0a1 / 20211201050507 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central. a=merge
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -2341,17 +2341,17 @@ def linker_ldflags(linker, target, sysro
 
 add_old_configure_assignment("LINKER_LDFLAGS", linker_ldflags)
 
 
 # There's a wrinkle with MinGW: linker configuration is not enabled, so
 # `select_linker` is never invoked.  Hard-code around it.
 @depends(select_linker, target, c_compiler)
 def gcc_use_gnu_ld(select_linker, target, c_compiler):
-    if select_linker is not None:
+    if select_linker is not None and target.kernel != "Darwin":
         return select_linker.KIND in ("bfd", "gold", "lld")
     if target.kernel == "WINNT" and c_compiler.type == "clang":
         return True
     return None
 
 
 # GCC_USE_GNU_LD=1 means the linker is command line compatible with GNU ld.
 set_config("GCC_USE_GNU_LD", gcc_use_gnu_ld)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -265,17 +265,17 @@ endif
 
 #
 # MacOS X specific stuff
 #
 
 ifeq ($(OS_ARCH),Darwin)
 ifneq (,$(SHARED_LIBRARY))
 _LOADER_PATH := @executable_path
-EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name $(_LOADER_PATH)/$@ -compatibility_version 1 -current_version 1 -single_module
+EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name $(_LOADER_PATH)/$@ -compatibility_version 1 -current_version 1
 endif
 endif
 
 #
 # GNU doesn't have path length limitation
 #
 
 ifeq ($(OS_ARCH),GNU)
--- a/dom/fetch/FetchUtil.cpp
+++ b/dom/fetch/FetchUtil.cpp
@@ -442,17 +442,16 @@ class JSStreamConsumer final : public ns
 
         *aWriteCount = consume;
         return NS_OK;
       }
 
       // Zlib is initialized, overwrite the prefix with the inflated data.
 
       MOZ_DIAGNOSTIC_ASSERT(aCount > 0);
-      MOZ_DIAGNOSTIC_ASSERT(self->mZStream.avail_out > 0);
       self->mZStream.avail_in = aCount;
       self->mZStream.next_in = (uint8_t*)aFromSegment;
 
       int ret = inflate(&self->mZStream, Z_NO_FLUSH);
 
       MOZ_DIAGNOSTIC_ASSERT(ret == Z_OK || ret == Z_STREAM_END,
                             "corrupt optimized wasm cache file: data");
       MOZ_DIAGNOSTIC_ASSERT(self->mZStream.avail_in == 0,
--- a/gfx/thebes/d3dkmtQueryStatistics.h
+++ b/gfx/thebes/d3dkmtQueryStatistics.h
@@ -14,18 +14,19 @@
 
 typedef struct _D3DKMTQS_COUNTER {
   ULONG Count;
   ULONGLONG Bytes;
 } D3DKMTQS_COUNTER;
 
 typedef struct _D3DKMTQS_ADAPTER_INFO {
   ULONG NbSegments;
+  ULONG NodeCount;
 
-  ULONG Filler[4];
+  ULONG Filler[3];
   ULONGLONG Filler2[2];  // Assumed sizeof(LONGLONG) = sizeof(ULONGLONG)
   struct {
     ULONG Filler[14];
   } Filler_RDMAB;
   struct {
     ULONG Filler[9];
   } Filler_R;
   struct {
@@ -116,42 +117,57 @@ typedef struct _D3DKMTQS_PROCESS_SEGMENT
     ULONGLONG Filler3;
   } Filler3;
   struct {
     ULONGLONG Filler;
   } Filler4;
   ULONG64 Reserved[8];
 } D3DKMTQS_PROCESS_SEGMENT_INFO;
 
+typedef struct _D3DKMTQS_PROCESS_NODE_INFO {
+  LARGE_INTEGER RunningTime;  // 100ns
+  ULONG ContextSwitch;
+  ULONG PreemptionStatistics[16];
+  ULONG PacketStatistics[32];
+  ULONG64 Reserved[8];
+} D3DKMTQS_PROCESS_NODE_INFO;
+
 typedef enum _D3DKMTQS_TYPE {
   D3DKMTQS_ADAPTER = 0,
   D3DKMTQS_PROCESS = 1,
   D3DKMTQS_SEGMENT = 3,
   D3DKMTQS_PROCESS_SEGMENT = 4,
+  D3DKMTQS_PROCESS_NODE = 6,
 } D3DKMTQS_TYPE;
 
 typedef union _D3DKMTQS_RESULT {
   D3DKMTQS_ADAPTER_INFO AdapterInfo;
   D3DKMTQS_SEGMENT_INFO_WIN7 SegmentInfoWin7;
   D3DKMTQS_SEGMENT_INFO_WIN8 SegmentInfoWin8;
   D3DKMTQS_PROCESS_INFO ProcessInfo;
   D3DKMTQS_PROCESS_SEGMENT_INFO ProcessSegmentInfo;
+  D3DKMTQS_PROCESS_NODE_INFO ProcessNodeInformation;
 } D3DKMTQS_RESULT;
 
 typedef struct _D3DKMTQS_QUERY_SEGMENT {
   ULONG SegmentId;
 } D3DKMTQS_QUERY_SEGMENT;
 
+typedef struct _D3DKMTQS_QUERY_NODE {
+  ULONG NodeId;
+} D3DKMTQS_QUERY_NODE;
+
 typedef struct _D3DKMTQS {
   D3DKMTQS_TYPE Type;
   LUID AdapterLuid;
   HANDLE hProcess;
   D3DKMTQS_RESULT QueryResult;
 
   union {
     D3DKMTQS_QUERY_SEGMENT QuerySegment;
     D3DKMTQS_QUERY_SEGMENT QueryProcessSegment;
+    D3DKMTQS_QUERY_NODE QueryProcessNode;
   };
 } D3DKMTQS;
 
 extern "C" {
 typedef __checkReturn NTSTATUS(APIENTRY* PFND3DKMTQS)(const D3DKMTQS*);
 }
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -308,16 +308,79 @@ gfxWindowsPlatform::~gfxWindowsPlatform(
 void gfxWindowsPlatform::InitMemoryReportersForGPUProcess() {
   MOZ_RELEASE_ASSERT(XRE_IsGPUProcess());
 
   RegisterStrongMemoryReporter(new GfxD2DVramReporter());
   RegisterStrongMemoryReporter(new GPUAdapterReporter());
   RegisterStrongMemoryReporter(new D3DSharedTexturesReporter());
 }
 
+/* static */
+nsresult gfxWindowsPlatform::GetGpuTimeSinceProcessStartInMs(
+    uint64_t* aResult) {
+  RefPtr<ID3D11Device> d3d11Device;
+  if (!(d3d11Device = mozilla::gfx::Factory::GetDirect3D11Device())) {
+    // If we don't have a D3DDevice, we likely didn't use any GPU time.
+    *aResult = 0;
+    return NS_OK;
+  }
+
+  nsModuleHandle module(LoadLibrary(L"gdi32.dll"));
+  if (!module) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  PFND3DKMTQS queryD3DKMTStatistics =
+      (PFND3DKMTQS)GetProcAddress(module, "D3DKMTQueryStatistics");
+  if (!queryD3DKMTStatistics) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  RefPtr<IDXGIDevice> dxgiDevice;
+  if (d3d11Device->QueryInterface(__uuidof(IDXGIDevice),
+                                  getter_AddRefs(dxgiDevice)) != S_OK) {
+    return NS_ERROR_FAILURE;
+  }
+
+  IDXGIAdapter* DXGIAdapter;
+  if (dxgiDevice->GetAdapter(&DXGIAdapter) != S_OK) {
+    return NS_ERROR_FAILURE;
+  }
+
+  DXGI_ADAPTER_DESC adapterDesc;
+  DXGIAdapter->GetDesc(&adapterDesc);
+  DXGIAdapter->Release();
+
+  D3DKMTQS queryStatistics;
+  memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+  queryStatistics.Type = D3DKMTQS_ADAPTER;
+  queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
+  if (!NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  uint64_t result = 0;
+  ULONG nodeCount = queryStatistics.QueryResult.AdapterInfo.NodeCount;
+  for (ULONG i = 0; i < nodeCount; ++i) {
+    memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+    queryStatistics.Type = D3DKMTQS_PROCESS_NODE;
+    queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
+    queryStatistics.hProcess = GetCurrentProcess();
+    queryStatistics.QueryProcessNode.NodeId = i;
+    if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
+      result += queryStatistics.QueryResult.ProcessNodeInformation.RunningTime
+                    .QuadPart *
+                100 / PR_NSEC_PER_MSEC;
+    }
+  }
+
+  *aResult = result;
+  return NS_OK;
+}
+
 static void UpdateANGLEConfig() {
   if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
     gfxConfig::Disable(Feature::D3D11_HW_ANGLE, FeatureStatus::Disabled,
                        "D3D11 compositing is disabled",
                        "FEATURE_FAILURE_HW_ANGLE_D3D11_DISABLED"_ns);
   }
 }
 
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -1,22 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
 #ifndef GFX_WINDOWS_PLATFORM_H
 #define GFX_WINDOWS_PLATFORM_H
 
-/**
- * XXX to get CAIRO_HAS_DWRITE_FONT
- * and cairo_win32_scaled_font_select_font
- */
-#include "cairo-win32.h"
-
 #include "gfxCrashReporterUtils.h"
 #include "gfxFontUtils.h"
 #include "gfxWindowsSurface.h"
 #include "gfxFont.h"
 #include "gfxDWriteFonts.h"
 #include "gfxPlatform.h"
 #include "gfxTelemetry.h"
 #include "gfxTypes.h"
@@ -172,16 +166,18 @@ class gfxWindowsPlatform final : public 
 
   void FontsPrefsChanged(const char* aPref) override;
 
   static inline bool DWriteEnabled() {
     return !!mozilla::gfx::Factory::GetDWriteFactory();
   }
 
  public:
+  static nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
+
   bool DwmCompositionEnabled();
 
   mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
 
   static bool IsOptimus();
 
   bool SupportsApzWheelInput() const override { return true; }
 
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -1024,16 +1024,26 @@ set_define(
 
 
 # ECMAScript Internationalization API Support (uses ICU)
 # ======================================================
 system_lib_option("--with-system-icu", help="Use system ICU")
 
 system_icu = pkg_check_modules("MOZ_ICU", "icu-i18n >= 70.1", when="--with-system-icu")
 
+
+@depends("--with-system-icu")
+def in_tree_icu(system_icu):
+    return not system_icu
+
+
+# Set MOZ_ICU_CFLAGS to an explicit empty value when --with-system-icu is *not* used,
+# for layout/style/extra-bindgen-flags
+set_config("MOZ_ICU_CFLAGS", [], when=in_tree_icu)
+
 set_config("MOZ_SYSTEM_ICU", True, when=system_icu)
 set_define("MOZ_SYSTEM_ICU", True, when=system_icu)
 
 option("--without-intl-api", help="Disable ECMAScript Internationalization API")
 
 
 @depends("--with-intl-api", js_standalone)
 def check_intl_api(enabled, js_standalone):
--- a/layout/style/extra-bindgen-flags.in
+++ b/layout/style/extra-bindgen-flags.in
@@ -1,1 +1,1 @@
-@BINDGEN_SYSTEM_FLAGS@ @NSPR_CFLAGS@ @MOZ_PIXMAN_CFLAGS@
+@BINDGEN_SYSTEM_FLAGS@ @NSPR_CFLAGS@ @MOZ_PIXMAN_CFLAGS@ @MOZ_ICU_CFLAGS@
--- a/mozglue/build/moz.build
+++ b/mozglue/build/moz.build
@@ -111,24 +111,14 @@ if CONFIG["OS_ARCH"] == "WINNT":
 
     EXPORTS += [
         "IAccessible64.manifest",
     ]
 
 LIBRARY_DEFINES["IMPL_MFBT"] = True
 LIBRARY_DEFINES["MOZ_HAS_MOZGLUE"] = True
 
-if CONFIG["OS_TARGET"] == "Darwin":
-    # On OSX 10.10.3, a dead lock happens in some cases involving dynamic
-    # symbol resolution for symbols that jemalloc itself uses. While it
-    # might be possible to find a way to avoid all such symbol resolutions,
-    # it's currently not possible because at the very least there's a call
-    # to pthread_self from tsd_init_check_recursion, which is necessary
-    # because somehow clang doesn't want to accept the __thread keyword
-    # for TLS.
-    LDFLAGS += ["-Wl,-bind_at_load"]
-
 if CONFIG["MOZ_LINKER"] and CONFIG["CPU_ARCH"] == "arm":
     LDFLAGS += ["-Wl,-version-script,%s/arm-eabi-filter" % SRCDIR]
 
 DIST_INSTALL = True
 
 include("replace_malloc.mozbuild")
--- a/toolkit/components/glean/ipc/FOGIPC.cpp
+++ b/toolkit/components/glean/ipc/FOGIPC.cpp
@@ -16,45 +16,55 @@
 
 using mozilla::dom::ContentParent;
 using mozilla::ipc::ByteBuf;
 using FlushFOGDataPromise = mozilla::dom::ContentParent::FlushFOGDataPromise;
 
 namespace mozilla {
 namespace glean {
 
-static void RecordCpuTime() {
-  static uint64_t previousCpuTime = 0;
+static void RecordPowerMetrics() {
+  static uint64_t previousCpuTime = 0, previousGpuTime = 0;
 
   uint64_t cpuTime;
   if (NS_FAILED(GetCpuTimeSinceProcessStartInMs(&cpuTime))) {
     return;
   }
 
   uint64_t newCpuTime = cpuTime - previousCpuTime;
   previousCpuTime += newCpuTime;
 
   if (newCpuTime) {
     // The counters are reset at least once a day. Assuming all cores are used
     // continuously, an int32 can hold the data for 24.85 cores.
     // This should be fine for now, but may overflow in the future.
     power::total_cpu_time_ms.Add(int32_t(newCpuTime));
   }
+
+  uint64_t gpuTime;
+  if (NS_SUCCEEDED(GetGpuTimeSinceProcessStartInMs(&gpuTime))) {
+    uint64_t newGpuTime = gpuTime - previousGpuTime;
+    previousGpuTime += newGpuTime;
+
+    if (newGpuTime) {
+      power::total_gpu_time_ms.Add(int32_t(newGpuTime));
+    }
+  }
 }
 
 /**
  * Flush your data ASAP, either because the parent process is asking you to
  * or because the process is about to shutdown.
  *
  * @param aResolver - The function you need to call with the bincoded,
  *                    serialized payload that the Rust impl hands you.
  */
 void FlushFOGData(std::function<void(ipc::ByteBuf&&)>&& aResolver) {
-  // Record the CPU time right before data is sent to the parent.
-  RecordCpuTime();
+  // Record power metrics right before data is sent to the parent.
+  RecordPowerMetrics();
 
   ByteBuf buf;
   uint32_t ipcBufferSize = impl::fog_serialize_ipc_buf();
   bool ok = buf.Allocate(ipcBufferSize);
   if (!ok) {
     return;
   }
   uint32_t writtenLen = impl::fog_give_ipc_buf(buf.mData, buf.mLen);
@@ -125,18 +135,19 @@ void SendFOGData(ipc::ByteBuf&& buf) {
   }
 }
 
 /**
  * Called on the parent process to ask all child processes for data,
  * sending it all down into Rust to be used.
  */
 RefPtr<GenericPromise> FlushAndUseFOGData() {
-  // Record CPU time on the parent before sending requests to child processes.
-  RecordCpuTime();
+  // Record power metrics on the parent before sending requests to child
+  // processes.
+  RecordPowerMetrics();
 
   RefPtr<GenericPromise::Private> ret = new GenericPromise::Private(__func__);
   std::function<void(nsTArray<ByteBuf> &&)> resolver =
       [ret](nsTArray<ByteBuf>&& bufs) {
         for (ByteBuf& buf : bufs) {
           FOGData(std::move(buf));
         }
         ret->Resolve(true, __func__);
--- a/toolkit/components/processtools/ProcInfo.h
+++ b/toolkit/components/processtools/ProcInfo.h
@@ -22,16 +22,23 @@ class GeckoChildProcessHost;
 
 /**
  * Return the number of milliseconds of CPU time used since process start.
  *
  * @return NS_OK on success.
  */
 nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult);
 
+/**
+ * Return the number of milliseconds of GPU time used since process start.
+ *
+ * @return NS_OK on success.
+ */
+nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
+
 // Process types. When updating this enum, please make sure to update
 // WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
 // mirror the changes.
 enum class ProcType {
   // These must match the ones in RemoteType.h, and E10SUtils.jsm
   Web,
   WebIsolated,
   File,
--- a/toolkit/components/processtools/ProcInfo.mm
+++ b/toolkit/components/processtools/ProcInfo.mm
@@ -26,16 +26,29 @@ nsresult GetCpuTimeSinceProcessStartInMs
   if ((unsigned long)proc_pidinfo(getpid(), PROC_PIDTASKINFO, 0, &pti, PROC_PIDTASKINFO_SIZE) <
       PROC_PIDTASKINFO_SIZE) {
     return NS_ERROR_FAILURE;
   }
   *aResult = (pti.pti_total_user + pti.pti_total_system) / PR_NSEC_PER_MSEC;
   return NS_OK;
 }
 
+nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
+  task_power_info_v2_data_t task_power_info;
+  mach_msg_type_number_t count = TASK_POWER_INFO_V2_COUNT;
+  kern_return_t kr =
+      task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&task_power_info, &count);
+  if (kr != KERN_SUCCESS) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *aResult = task_power_info.gpu_energy.task_gpu_utilisation / PR_NSEC_PER_MSEC;
+  return NS_OK;
+}
+
 RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
   auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
   RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
   nsresult rv = NS_OK;
   nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to get stream transport service");
     holder->Reject(rv, __func__);
--- a/toolkit/components/processtools/ProcInfo_linux.cpp
+++ b/toolkit/components/processtools/ProcInfo_linux.cpp
@@ -191,16 +191,20 @@ nsresult GetCpuTimeSinceProcessStartInMs
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   *aResult = info.cpuTime / PR_NSEC_PER_MSEC;
   return NS_OK;
 }
 
+nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
   auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
   RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
   nsresult rv = NS_OK;
   nsCOMPtr<nsIEventTarget> target =
       do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to get stream transport service");
--- a/toolkit/components/processtools/ProcInfo_win.cpp
+++ b/toolkit/components/processtools/ProcInfo_win.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/ProcInfo.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/SSE.h"
+#include "gfxWindowsPlatform.h"
 #include "nsMemoryReporterManager.h"
 #include "nsNetCID.h"
 #include "nsWindowsHelpers.h"
 #include <windows.h>
 #include <psapi.h>
 #include <tlhelp32.h>
 
 #define PR_USEC_PER_NSEC 1000L
@@ -80,16 +81,20 @@ nsresult GetCpuTimeSinceProcessStartInMs
                        &kernelTime, &userTime)) {
     return NS_ERROR_FAILURE;
   }
   *aResult =
       (ToNanoSeconds(kernelTime) + ToNanoSeconds(userTime)) / PR_NSEC_PER_MSEC;
   return NS_OK;
 }
 
+nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
+  return gfxWindowsPlatform::GetGpuTimeSinceProcessStartInMs(aResult);
+}
+
 RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
   auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
   RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
 
   nsresult rv = NS_OK;
   nsCOMPtr<nsIEventTarget> target =
       do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) {
--- a/toolkit/components/processtools/metrics.yaml
+++ b/toolkit/components/processtools/metrics.yaml
@@ -21,8 +21,24 @@ power:
       - https://bugzilla.mozilla.org/show_bug.cgi?id=1736040
     data_reviews:
       - https://bugzilla.mozilla.org/show_bug.cgi?id=1736040
     data_sensitivity:
       - technical
     notification_emails:
       - florian@mozilla.com
     expires: never
+
+  total_gpu_time_ms:
+    type: counter
+    description: >
+      Total GPU time used by all processes in ms.
+    bugs:
+      - https://bugzilla.mozilla.org/show_bug.cgi?id=1743176
+    data_reviews:
+      - https://bugzilla.mozilla.org/show_bug.cgi?id=1743176
+    data_sensitivity:
+      - technical
+    notification_emails:
+      - florian@mozilla.com
+    expires: never
+    no_lint:
+      - COMMON_PREFIX
--- a/toolkit/components/telemetry/docs/data/deletion-request-ping.rst
+++ b/toolkit/components/telemetry/docs/data/deletion-request-ping.rst
@@ -35,16 +35,32 @@ Structure:
 
 Expected behaviours
 -------------------
 The following is a list of expected behaviours for the ``deletion-request`` ping:
 
 - Telemetry will try to send the ping even if upload is disabled.
 - Telemetry may persist this ping if it can't be immediately sent, and may try to resend it later.
 
+Analysis Gotchas
+----------------
+It is `known <https://bugzilla.mozilla.org/show_bug.cgi?id=1741252>`_ that,
+on a release week, "deletion-request" pings from the previous release version will spike in volume.
+
+There is a strong geo component to these spikes (China and Russia mostly).
+The pings behave like they're coming from real Firefox instances (one per ``client_id``).
+However, we've received no "main" pings from these clients from the previous 28 days
+(per ``clients_last_seen``) which makes them rather unusual.
+
+We suspect this is some sort of automation or pseudo-automation.
+
+Including these pings in our self-service deletion processes doesn't make them any slower,
+and ingesting them isn't breaking the bank, so at time of writing we're inclined to take a
+"document and then ignore" approach.
+
 Version History
 ---------------
 
 - Firefox 72:
 
   - "deletion-request" ping replaces the "optout" ping (`bug 1585410 <https://bugzilla.mozilla.org/show_bug.cgi?id=1585410>`_).
 
 - Firefox 73:
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -9028,18 +9028,18 @@ static void relative_pointer_handle_rela
     void* data, struct zwp_relative_pointer_v1* pointer, uint32_t time_hi,
     uint32_t time_lo, wl_fixed_t dx_w, wl_fixed_t dy_w, wl_fixed_t dx_unaccel_w,
     wl_fixed_t dy_unaccel_w) {
   RefPtr<nsWindow> window(reinterpret_cast<nsWindow*>(data));
 
   WidgetMouseEvent event(true, eMouseMove, window, WidgetMouseEvent::eReal);
 
   event.mRefPoint = window->GetNativePointerLockCenter();
-  event.mRefPoint.x += wl_fixed_to_double(dx_unaccel_w);
-  event.mRefPoint.y += wl_fixed_to_double(dy_unaccel_w);
+  event.mRefPoint.x += wl_fixed_to_int(dx_w);
+  event.mRefPoint.y += wl_fixed_to_int(dy_w);
 
   event.AssignEventTime(window->GetWidgetEventTime(time_lo));
   window->DispatchInputEvent(&event);
 }
 
 static const struct zwp_relative_pointer_v1_listener relative_pointer_listener =
     {
         relative_pointer_handle_relative_motion,