Bug 1540028 [wpt PR 16099] - Catch more exceptions in Document-createElement-namespac...
[gecko.git] / image / ImageMemoryReporter.cpp
blob5792b0cee5ca36c2a2be1de72f3a34a9568ddd30
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ImageMemoryReporter.h"
8 #include "Image.h"
9 #include "mozilla/layers/SharedSurfacesParent.h"
10 #include "nsIMemoryReporter.h"
11 #include "nsISupportsImpl.h"
13 namespace mozilla {
14 namespace image {
16 ImageMemoryReporter::WebRenderReporter* ImageMemoryReporter::sWrReporter;
18 class ImageMemoryReporter::WebRenderReporter final : public nsIMemoryReporter {
19 public:
20 NS_DECL_ISUPPORTS
22 WebRenderReporter() {}
24 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
25 nsISupports* aData, bool aAnonymize) override {
26 layers::SharedSurfacesMemoryReport report;
27 layers::SharedSurfacesParent::AccumulateMemoryReport(report);
28 ReportSharedSurfaces(aHandleReport, aData, /* aIsForCompositor */ true,
29 report);
30 return NS_OK;
33 private:
34 virtual ~WebRenderReporter() {}
37 NS_IMPL_ISUPPORTS(ImageMemoryReporter::WebRenderReporter, nsIMemoryReporter)
39 /* static */
40 void ImageMemoryReporter::InitForWebRender() {
41 MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
42 if (!sWrReporter) {
43 sWrReporter = new WebRenderReporter();
44 RegisterStrongMemoryReporter(sWrReporter);
48 /* static */
49 void ImageMemoryReporter::ShutdownForWebRender() {
50 MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
51 if (sWrReporter) {
52 UnregisterStrongMemoryReporter(sWrReporter);
53 sWrReporter = nullptr;
57 /* static */
58 void ImageMemoryReporter::ReportSharedSurfaces(
59 nsIHandleReportCallback* aHandleReport, nsISupports* aData,
60 const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
61 ReportSharedSurfaces(aHandleReport, aData,
62 /* aIsForCompositor */ false, aSharedSurfaces);
65 /* static */
66 void ImageMemoryReporter::ReportSharedSurfaces(
67 nsIHandleReportCallback* aHandleReport, nsISupports* aData,
68 bool aIsForCompositor,
69 const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
70 MOZ_ASSERT_IF(aIsForCompositor, XRE_IsParentProcess() || XRE_IsGPUProcess());
71 MOZ_ASSERT_IF(!aIsForCompositor,
72 XRE_IsParentProcess() || XRE_IsContentProcess());
74 for (auto i = aSharedSurfaces.mSurfaces.begin();
75 i != aSharedSurfaces.mSurfaces.end(); ++i) {
76 ReportSharedSurface(aHandleReport, aData, aIsForCompositor, i->first,
77 i->second);
81 /* static */
82 void ImageMemoryReporter::ReportSharedSurface(
83 nsIHandleReportCallback* aHandleReport, nsISupports* aData,
84 bool aIsForCompositor, uint64_t aExternalId,
85 const layers::SharedSurfacesMemoryReport::SurfaceEntry& aEntry) {
86 nsAutoCString path;
87 if (aIsForCompositor) {
88 path.AppendLiteral("gfx/webrender/images/mapped_from_owner/");
89 } else {
90 path.AppendLiteral("gfx/webrender/images/owner_cache_missing/");
93 if (aIsForCompositor) {
94 path.AppendLiteral("pid=");
95 path.AppendInt(uint32_t(aEntry.mCreatorPid));
96 path.AppendLiteral("/");
99 if (gfxPrefs::ImageMemDebugReporting()) {
100 path.AppendInt(aExternalId, 16);
101 path.AppendLiteral("/");
104 path.AppendLiteral("image(");
105 path.AppendInt(aEntry.mSize.width);
106 path.AppendLiteral("x");
107 path.AppendInt(aEntry.mSize.height);
108 path.AppendLiteral(", compositor_ref:");
109 path.AppendInt(aEntry.mConsumers);
110 path.AppendLiteral(", creator_ref:");
111 path.AppendInt(aEntry.mCreatorRef);
112 path.AppendLiteral(")/decoded-nonheap");
114 size_t surfaceSize = mozilla::ipc::SharedMemory::PageAlignedSize(
115 aEntry.mSize.height * aEntry.mStride);
117 // If this memory has already been reported elsewhere (e.g. as part of our
118 // explicit section in the surface cache), we don't want report it again as
119 // KIND_NONHEAP and have it counted again.
120 bool sameProcess = aEntry.mCreatorPid == base::GetCurrentProcId();
121 int32_t kind = aIsForCompositor && !sameProcess
122 ? nsIMemoryReporter::KIND_NONHEAP
123 : nsIMemoryReporter::KIND_OTHER;
125 NS_NAMED_LITERAL_CSTRING(desc, "Decoded image data stored in shared memory.");
126 aHandleReport->Callback(EmptyCString(), path, kind,
127 nsIMemoryReporter::UNITS_BYTES, surfaceSize, desc,
128 aData);
131 /* static */
132 void ImageMemoryReporter::AppendSharedSurfacePrefix(
133 nsACString& aPathPrefix, const SurfaceMemoryCounter& aCounter,
134 layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
135 uint64_t extId = aCounter.Values().ExternalId();
136 if (extId) {
137 auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);
139 if (gfxPrefs::ImageMemDebugReporting()) {
140 aPathPrefix.AppendLiteral(", external_id:");
141 aPathPrefix.AppendInt(extId, 16);
142 if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
143 aPathPrefix.AppendLiteral(", compositor_ref:");
144 aPathPrefix.AppendInt(gpuEntry->second.mConsumers);
145 } else {
146 aPathPrefix.AppendLiteral(", compositor_ref:missing");
150 if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
151 MOZ_ASSERT(gpuEntry->second.mCreatorRef);
152 aSharedSurfaces.mSurfaces.erase(gpuEntry);
157 /* static */
158 void ImageMemoryReporter::TrimSharedSurfaces(
159 const ImageMemoryCounter& aCounter,
160 layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
161 if (aSharedSurfaces.mSurfaces.empty()) {
162 return;
165 for (const SurfaceMemoryCounter& counter : aCounter.Surfaces()) {
166 uint64_t extId = counter.Values().ExternalId();
167 if (extId) {
168 auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);
169 if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
170 MOZ_ASSERT(gpuEntry->second.mCreatorRef);
171 aSharedSurfaces.mSurfaces.erase(gpuEntry);
177 } // namespace image
178 } // namespace mozilla