xpcom/base/nsIMemoryReporter.idl

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/base/nsIMemoryReporter.idl	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,651 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "nsISupports.idl"
    1.11 +
    1.12 +interface nsIDOMWindow;
    1.13 +interface nsIRunnable;
    1.14 +interface nsISimpleEnumerator;
    1.15 +
    1.16 +/*
    1.17 + * Memory reporters measure Firefox's memory usage.  They are primarily used to
    1.18 + * generate the about:memory page.  You should read
    1.19 + * https://wiki.mozilla.org/Memory_Reporting before writing a memory
    1.20 + * reporter.
    1.21 + */
    1.22 +
    1.23 +[scriptable, function, uuid(3a61be3b-b93b-461a-a4f8-388214f558b1)]
    1.24 +interface nsIMemoryReporterCallback : nsISupports
    1.25 +{
    1.26 +  /*
    1.27 +   * The arguments to the callback are as follows.
    1.28 +   *
    1.29 +   *
    1.30 +   * |process|  The name of the process containing this reporter.  Each
    1.31 +   * reporter initially has "" in this field, indicating that it applies to the
    1.32 +   * current process.  (This is true even for reporters in a child process.)
    1.33 +   * When a reporter from a child process is copied into the main process, the
    1.34 +   * copy has its 'process' field set appropriately.
    1.35 +   *
    1.36 +   *
    1.37 +   * |path|  The path that this memory usage should be reported under.  Paths
    1.38 +   * are '/'-delimited, eg. "a/b/c".
    1.39 +   *
    1.40 +   * Each reporter can be viewed as representing a leaf node in a tree.
    1.41 +   * Internal nodes of the tree don't have reporters.  So, for example, the
    1.42 +   * reporters "explicit/a/b", "explicit/a/c", "explicit/d/e", and
    1.43 +   * "explicit/d/f" define this tree:
    1.44 +   *
    1.45 +   *   explicit
    1.46 +   *   |--a
    1.47 +   *   |  |--b [*]
    1.48 +   *   |  \--c [*]
    1.49 +   *   \--d
    1.50 +   *      |--e [*]
    1.51 +   *      \--f [*]
    1.52 +   *
    1.53 +   * Nodes marked with a [*] have a reporter.  Notice that the internal
    1.54 +   * nodes are implicitly defined by the paths.
    1.55 +   *
    1.56 +   * Nodes within a tree should not overlap measurements, otherwise the
    1.57 +   * parent node measurements will be double-counted.  So in the example
    1.58 +   * above, |b| should not count any allocations counted by |c|, and vice
    1.59 +   * versa.
    1.60 +   *
    1.61 +   * All nodes within each tree must have the same units.
    1.62 +   *
    1.63 +   * If you want to include a '/' not as a path separator, e.g. because the
    1.64 +   * path contains a URL, you need to convert each '/' in the URL to a '\'.
    1.65 +   * Consumers of the path will undo this change.  Any other '\' character
    1.66 +   * in a path will also be changed.  This is clumsy but hasn't caused any
    1.67 +   * problems so far.
    1.68 +   *
    1.69 +   * The paths of all reporters form a set of trees.  Trees can be
    1.70 +   * "degenerate", i.e. contain a single entry with no '/'.
    1.71 +   *
    1.72 +   *
    1.73 +   * |kind|  There are three kinds of memory reporters.
    1.74 +   *
    1.75 +   *  - HEAP: reporters measuring memory allocated by the heap allocator,
    1.76 +   *    e.g. by calling malloc, calloc, realloc, memalign, operator new, or
    1.77 +   *    operator new[].  Reporters in this category must have units
    1.78 +   *    UNITS_BYTES.
    1.79 +   *
    1.80 +   *  - NONHEAP: reporters measuring memory which the program explicitly
    1.81 +   *    allocated, but does not live on the heap.  Such memory is commonly
    1.82 +   *    allocated by calling one of the OS's memory-mapping functions (e.g.
    1.83 +   *    mmap, VirtualAlloc, or vm_allocate).  Reporters in this category
    1.84 +   *    must have units UNITS_BYTES.
    1.85 +   *
    1.86 +   *  - OTHER: reporters which don't fit into either of these categories.
    1.87 +   *    They can have any units.
    1.88 +   *
    1.89 +   * The kind only matters for reporters in the "explicit" tree;
    1.90 +   * aboutMemory.js uses it to calculate "heap-unclassified".
    1.91 +   *
    1.92 +   *
    1.93 +   * |units|  The units on the reporter's amount.  One of the following.
    1.94 +   *
    1.95 +   *  - BYTES: The amount contains a number of bytes.
    1.96 +   *
    1.97 +   *  - COUNT: The amount is an instantaneous count of things currently in
    1.98 +   *    existence.  For instance, the number of tabs currently open would have
    1.99 +   *    units COUNT.
   1.100 +   *
   1.101 +   *  - COUNT_CUMULATIVE: The amount contains the number of times some event
   1.102 +   *    has occurred since the application started up.  For instance, the
   1.103 +   *    number of times the user has opened a new tab would have units
   1.104 +   *    COUNT_CUMULATIVE.
   1.105 +   *
   1.106 +   *    The amount returned by a reporter with units COUNT_CUMULATIVE must
   1.107 +   *    never decrease over the lifetime of the application.
   1.108 +   *
   1.109 +   *  - PERCENTAGE: The amount contains a fraction that should be expressed as
   1.110 +   *    a percentage.  NOTE!  The |amount| field should be given a value 100x
   1.111 +   *    the actual percentage;  this number will be divided by 100 when shown.
   1.112 +   *    This allows a fractional percentage to be shown even though |amount| is
   1.113 +   *    an integer.  E.g. if the actual percentage is 12.34%, |amount| should
   1.114 +   *    be 1234.
   1.115 +   *
   1.116 +   *    Values greater than 100% are allowed.
   1.117 +   *
   1.118 +   *
   1.119 +   * |amount|  The numeric value reported by this memory reporter.  Accesses
   1.120 +   * can fail if something goes wrong when getting the amount.
   1.121 +   *
   1.122 +   *
   1.123 +   * |description|  A human-readable description of this memory usage report.
   1.124 +   */
   1.125 +  void callback(in ACString process, in AUTF8String path, in int32_t kind,
   1.126 +                in int32_t units, in int64_t amount,
   1.127 +                in AUTF8String description, in nsISupports data);
   1.128 +};
   1.129 +
   1.130 +/*
   1.131 + * An nsIMemoryReporter reports one or more memory measurements via a
   1.132 + * callback function which is called once for each measurement.
   1.133 + *
   1.134 + * An nsIMemoryReporter that reports a single measurement is sometimes called a
   1.135 + * "uni-reporter".  One that reports multiple measurements is sometimes called
   1.136 + * a "multi-reporter".
   1.137 + *
   1.138 + * aboutMemory.js is the most important consumer of memory reports.  It
   1.139 + * places the following constraints on reports.
   1.140 + *
   1.141 + * - All reports within a single sub-tree must have the same units.
   1.142 + *
   1.143 + * - There may be an "explicit" tree.  If present, it represents
   1.144 + *   non-overlapping regions of memory that have been explicitly allocated with
   1.145 + *   an OS-level allocation (e.g. mmap/VirtualAlloc/vm_allocate) or a
   1.146 + *   heap-level allocation (e.g. malloc/calloc/operator new).  Reporters in
   1.147 + *   this tree must have kind HEAP or NONHEAP, units BYTES.
   1.148 + *
   1.149 + * It is preferred, but not required, that report descriptions use complete
   1.150 + * sentences (i.e. start with a capital letter and end with a period, or
   1.151 + * similar).
   1.152 + */
   1.153 +[scriptable, uuid(0884cd0f-5829-4381-979b-0f53904030ed)]
   1.154 +interface nsIMemoryReporter : nsISupports
   1.155 +{
   1.156 +  /*
   1.157 +   * Run the reporter.
   1.158 +   */
   1.159 +  void collectReports(in nsIMemoryReporterCallback callback,
   1.160 +                      in nsISupports data);
   1.161 +
   1.162 +  /*
   1.163 +   * Kinds.  See the |kind| comment in nsIMemoryReporterCallback.
   1.164 +   */
   1.165 +  const int32_t KIND_NONHEAP = 0;
   1.166 +  const int32_t KIND_HEAP    = 1;
   1.167 +  const int32_t KIND_OTHER   = 2;
   1.168 +
   1.169 +  /*
   1.170 +   * Units.  See the |units| comment in nsIMemoryReporterCallback.
   1.171 +   */
   1.172 +  const int32_t UNITS_BYTES = 0;
   1.173 +  const int32_t UNITS_COUNT = 1;
   1.174 +  const int32_t UNITS_COUNT_CUMULATIVE = 2;
   1.175 +  const int32_t UNITS_PERCENTAGE = 3;
   1.176 +};
   1.177 +
   1.178 +[scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)]
   1.179 +interface nsIFinishReportingCallback : nsISupports
   1.180 +{
   1.181 +  void callback(in nsISupports data);
   1.182 +};
   1.183 +
   1.184 +[scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)]
   1.185 +interface nsIMemoryReporterManager : nsISupports
   1.186 +{
   1.187 +  /*
   1.188 +   * Initialize.
   1.189 +   */
   1.190 +  void init();
   1.191 +
   1.192 +  /*
   1.193 +   * Register the given nsIMemoryReporter.  The Manager service will hold a
   1.194 +   * strong reference to the given reporter, and will be responsible for freeing
   1.195 +   * the reporter at shutdown.  You may manually unregister the reporter with
   1.196 +   * unregisterStrongReporter() at any point.
   1.197 +   */
   1.198 +  void registerStrongReporter(in nsIMemoryReporter reporter);
   1.199 +
   1.200 +  /*
   1.201 +   * Like registerReporter, but the Manager service will hold a weak reference
   1.202 +   * via a raw pointer to the given reporter.  The reporter should be
   1.203 +   * unregistered before shutdown.
   1.204 +   * You cannot register JavaScript components with this function!  Always
   1.205 +   * register your JavaScript components with registerStrongReporter().
   1.206 +   */
   1.207 +  void registerWeakReporter(in nsIMemoryReporter reporter);
   1.208 +
   1.209 +  /*
   1.210 +   * Unregister the given memory reporter, which must have been registered with
   1.211 +   * registerStrongReporter().  You normally don't need to unregister your
   1.212 +   * strong reporters, as nsIMemoryReporterManager will take care of that at
   1.213 +   * shutdown.
   1.214 +   */
   1.215 +  void unregisterStrongReporter(in nsIMemoryReporter reporter);
   1.216 +
   1.217 +  /*
   1.218 +   * Unregister the given memory reporter, which must have been registered with
   1.219 +   * registerWeakReporter().
   1.220 +   */
   1.221 +  void unregisterWeakReporter(in nsIMemoryReporter reporter);
   1.222 +
   1.223 +  /*
   1.224 +   * These functions should only be used for testing purposes.
   1.225 +   */
   1.226 +  void blockRegistrationAndHideExistingReporters();
   1.227 +  void unblockRegistrationAndRestoreOriginalReporters();
   1.228 +  void registerStrongReporterEvenIfBlocked(in nsIMemoryReporter aReporter);
   1.229 +
   1.230 +  /*
   1.231 +   * Get memory reports for the current process and all child processes.
   1.232 +   * |handleReport| is called for each report, and |finishReporting| is called
   1.233 +   * once all reports have been handled.
   1.234 +   *
   1.235 +   * |finishReporting| is called even if, for example, some child processes
   1.236 +   * fail to report back.  However, calls to this method will silently and
   1.237 +   * immediately abort -- and |finishReporting| will not be called -- if a
   1.238 +   * previous getReports() call is still in flight, i.e. if it has not yet
   1.239 +   * finished invoking |finishReporting|.  The silent abort is because the
   1.240 +   * in-flight request will finish soon, and the caller would very likely just
   1.241 +   * catch and ignore any error anyway.
   1.242 +   */
   1.243 +  void getReports(in nsIMemoryReporterCallback handleReport,
   1.244 +                  in nsISupports handleReportData,
   1.245 +                  in nsIFinishReportingCallback finishReporting,
   1.246 +                  in nsISupports finishReportingData);
   1.247 +
   1.248 +  /*
   1.249 +   * As above, but: If |minimizeMemoryUsage| is true, then each process will
   1.250 +   * minimize its memory usage (see the |minimizeMemoryUsage| method) before
   1.251 +   * gathering its report.  If DMD is enabled and |DMDDumpIdent| is non-empty
   1.252 +   * then write a DMD report to a file in the usual temporary directory (see
   1.253 +   * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
   1.254 +   */
   1.255 +  [noscript] void
   1.256 +    getReportsExtended(in nsIMemoryReporterCallback handleReport,
   1.257 +                       in nsISupports handleReportData,
   1.258 +                       in nsIFinishReportingCallback finishReporting,
   1.259 +                       in nsISupports finishReportingData,
   1.260 +                       in boolean minimizeMemoryUsage,
   1.261 +                       in AString DMDDumpIdent);
   1.262 +
   1.263 +  /*
   1.264 +   * Get memory reports in the current process only.  |handleReport| is called
   1.265 +   * for each report.
   1.266 +   */
   1.267 +  void getReportsForThisProcess(in nsIMemoryReporterCallback handleReport,
   1.268 +                                in nsISupports handleReportData);
   1.269 +
   1.270 +  /*
   1.271 +   * As above, but if DMD is enabled and |DMDDumpIdent| is non-empty
   1.272 +   * then write a DMD report to a file in the usual temporary directory (see
   1.273 +   * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
   1.274 +   */
   1.275 +  [noscript] void
   1.276 +    getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport,
   1.277 +                                     in nsISupports handleReportData,
   1.278 +                                     in AString DMDDumpIdent);
   1.279 +
   1.280 +  /*
   1.281 +   * The memory reporter manager, for the most part, treats reporters
   1.282 +   * registered with it as a black box.  However, there are some
   1.283 +   * "distinguished" amounts (as could be reported by a memory reporter) that
   1.284 +   * the manager provides as attributes, because they are sufficiently
   1.285 +   * interesting that we want external code (e.g. telemetry) to be able to rely
   1.286 +   * on them.
   1.287 +   *
   1.288 +   * Note that these are not reporters and so getReports() and
   1.289 +   * getReportsForThisProcess() do not look at them.  However, distinguished
   1.290 +   * amounts can be embedded in a reporter.
   1.291 +   *
   1.292 +   * Access to these attributes can fail.  In particular, some of them are not
   1.293 +   * available on all platforms.
   1.294 +   *
   1.295 +   * If you add a new distinguished amount, please update
   1.296 +   * toolkit/components/aboutmemory/tests/test_memoryReporters.xul.
   1.297 +   *
   1.298 +   * |explicit| (UNITS_BYTES)  The total size of explicit memory allocations,
   1.299 +   * both at the OS-level (eg. via mmap, VirtualAlloc) and at the heap level
   1.300 +   * (eg. via malloc, calloc, operator new).  It covers all heap allocations,
   1.301 +   * but will miss any OS-level ones not covered by memory reporters.
   1.302 +   *
   1.303 +   * |vsize| (UNITS_BYTES)  The virtual size, i.e. the amount of address space
   1.304 +   * taken up.
   1.305 +   *
   1.306 +   * |vsizeMaxContiguous| (UNITS_BYTES)  The size of the largest contiguous
   1.307 +   * block of virtual memory.
   1.308 +   *
   1.309 +   * |resident| (UNITS_BYTES)  The resident size (a.k.a. RSS or physical memory
   1.310 +   * used).
   1.311 +   *
   1.312 +   * |residentFast| (UNITS_BYTES)  This is like |resident|, but on Mac OS
   1.313 +   * |resident| can purge pages, which is slow.  It also affects the result of
   1.314 +   * |residentFast|, and so |resident| and |residentFast| should not be used
   1.315 +   * together.
   1.316 +   *
   1.317 +   * |heapAllocated| (UNITS_BYTES)  Memory mapped by the heap allocator.
   1.318 +   *
   1.319 +   * |heapOverheadRatio| (UNITS_PERCENTAGE)  In the heap allocator, this is the
   1.320 +   * ratio of committed, unused bytes to allocated bytes.  Like all
   1.321 +   * UNITS_PERCENTAGE measurements, its amount is multiplied by 100x so it can
   1.322 +   * be represented by an int64_t.
   1.323 +   *
   1.324 +   * |JSMainRuntimeGCHeap| (UNITS_BYTES)  Size of the main JS runtime's GC
   1.325 +   * heap.
   1.326 +   *
   1.327 +   * |JSMainRuntimeTemporaryPeak| (UNITS_BYTES)  Peak size of the transient
   1.328 +   * storage in the main JSRuntime.
   1.329 +   *
   1.330 +   * |JSMainRuntimeCompartments{System,User}| (UNITS_COUNT)  The number of
   1.331 +   * {system,user} compartments in the main JS runtime.
   1.332 +   *
   1.333 +   * |imagesContentUsedUncompressed| (UNITS_BYTES)  Memory used for decoded
   1.334 +   * images in content.
   1.335 +   *
   1.336 +   * |storageSQLite| (UNITS_BYTES)  Memory used by SQLite.
   1.337 +   *
   1.338 +   * |lowMemoryEvents{Virtual,Physical}| (UNITS_COUNT_CUMULATIVE)  The number
   1.339 +   * of low-{virtual,physical}-memory events that have occurred since the
   1.340 +   * process started.
   1.341 +   *
   1.342 +   * |ghostWindows| (UNITS_COUNT)  The number of ghost windows.
   1.343 +   *
   1.344 +   * |pageFaultsHard| (UNITS_COUNT_CUMULATIVE)  The number of hard (a.k.a.
   1.345 +   * major) page faults that have occurred since the process started.
   1.346 +   */
   1.347 +  readonly attribute int64_t explicit;
   1.348 +  readonly attribute int64_t vsize;
   1.349 +  readonly attribute int64_t vsizeMaxContiguous;
   1.350 +  readonly attribute int64_t resident;
   1.351 +  readonly attribute int64_t residentFast;
   1.352 +
   1.353 +  readonly attribute int64_t heapAllocated;
   1.354 +  readonly attribute int64_t heapOverheadRatio;
   1.355 +
   1.356 +  readonly attribute int64_t JSMainRuntimeGCHeap;
   1.357 +  readonly attribute int64_t JSMainRuntimeTemporaryPeak;
   1.358 +  readonly attribute int64_t JSMainRuntimeCompartmentsSystem;
   1.359 +  readonly attribute int64_t JSMainRuntimeCompartmentsUser;
   1.360 +
   1.361 +  readonly attribute int64_t imagesContentUsedUncompressed;
   1.362 +
   1.363 +  readonly attribute int64_t storageSQLite;
   1.364 +
   1.365 +  readonly attribute int64_t lowMemoryEventsVirtual;
   1.366 +  readonly attribute int64_t lowMemoryEventsPhysical;
   1.367 +
   1.368 +  readonly attribute int64_t ghostWindows;
   1.369 +
   1.370 +  readonly attribute int64_t pageFaultsHard;
   1.371 +
   1.372 +  /*
   1.373 +   * This attribute indicates if moz_malloc_usable_size() works.
   1.374 +   */
   1.375 +  [infallible] readonly attribute boolean hasMozMallocUsableSize;
   1.376 +
   1.377 +  /*
   1.378 +   * Run a series of GC/CC's in an attempt to minimize the application's memory
   1.379 +   * usage.  When we're finished, we invoke the given runnable if it's not
   1.380 +   * null.
   1.381 +   */
   1.382 +  void minimizeMemoryUsage(in nsIRunnable callback);
   1.383 +
   1.384 +  /*
   1.385 +   * Measure the memory that is known to be owned by this tab, split up into
   1.386 +   * several broad categories.  Note that this will be an underestimate of the
   1.387 +   * true number, due to imperfect memory reporter coverage (corresponding to
   1.388 +   * about:memory's "heap-unclassified"), and due to some memory shared between
   1.389 +   * tabs not being counted.
   1.390 +   *
   1.391 +   * The time taken for the measurement (split into JS and non-JS parts) is
   1.392 +   * also returned.
   1.393 +   */
   1.394 +  void sizeOfTab(in nsIDOMWindow window,
   1.395 +                 out int64_t jsObjectsSize, out int64_t jsStringsSize,
   1.396 +                 out int64_t jsOtherSize, out int64_t domSize,
   1.397 +                 out int64_t styleSize, out int64_t otherSize,
   1.398 +                 out int64_t totalSize,
   1.399 +                 out double jsMilliseconds, out double nonJSMilliseconds);
   1.400 +};
   1.401 +
   1.402 +%{C++
   1.403 +
   1.404 +#include "js/TypeDecls.h"
   1.405 +#include "nsStringGlue.h"
   1.406 +#include "nsTArray.h"
   1.407 +#include "mozilla/Atomics.h"
   1.408 +
   1.409 +class nsPIDOMWindow;
   1.410 +
   1.411 +// nsIHandleReportCallback is a better name, but keep nsIMemoryReporterCallback
   1.412 +// around for backwards compatibility.
   1.413 +typedef nsIMemoryReporterCallback nsIHandleReportCallback;
   1.414 +
   1.415 +namespace mozilla {
   1.416 +
   1.417 +// Register a memory reporter.  The manager service will hold a strong
   1.418 +// reference to this reporter.
   1.419 +XPCOM_API(nsresult) RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter);
   1.420 +
   1.421 +// Register a memory reporter.  The manager service will hold a weak reference
   1.422 +// to this reporter.
   1.423 +XPCOM_API(nsresult) RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
   1.424 +
   1.425 +// Unregister a weak memory reporter.
   1.426 +XPCOM_API(nsresult) UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
   1.427 +
   1.428 +// The memory reporter manager provides access to several distinguished
   1.429 +// amounts via attributes.  Some of these amounts are provided by Gecko
   1.430 +// components that cannot be accessed directly from XPCOM code.  So we provide
   1.431 +// the following functions for those components to be registered with the
   1.432 +// manager.
   1.433 +
   1.434 +typedef int64_t (*InfallibleAmountFn)();
   1.435 +typedef nsresult (*FallibleAmountFn)(int64_t* aAmount);
   1.436 +
   1.437 +#define DECL_REGISTER_DISTINGUISHED_AMOUNT(kind, name) \
   1.438 +    nsresult Register##name##DistinguishedAmount(kind##AmountFn aAmountFn);
   1.439 +#define DECL_UNREGISTER_DISTINGUISHED_AMOUNT(name) \
   1.440 +    nsresult Unregister##name##DistinguishedAmount();
   1.441 +
   1.442 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeGCHeap)
   1.443 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeTemporaryPeak)
   1.444 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsSystem)
   1.445 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsUser)
   1.446 +
   1.447 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, ImagesContentUsedUncompressed)
   1.448 +
   1.449 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, StorageSQLite)
   1.450 +DECL_UNREGISTER_DISTINGUISHED_AMOUNT(StorageSQLite)
   1.451 +
   1.452 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsVirtual)
   1.453 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsPhysical)
   1.454 +
   1.455 +DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, GhostWindows)
   1.456 +
   1.457 +#undef DECL_REGISTER_DISTINGUISHED_AMOUNT
   1.458 +#undef DECL_UNREGISTER_DISTINGUISHED_AMOUNT
   1.459 +
   1.460 +// Likewise for per-tab measurement.
   1.461 +
   1.462 +typedef nsresult (*JSSizeOfTabFn)(JSObject* aObj,
   1.463 +                                  size_t* aJsObjectsSize,
   1.464 +                                  size_t* aJsStringSize,
   1.465 +                                  size_t* aJsPrivateSize,
   1.466 +                                  size_t* aJsOtherSize);
   1.467 +typedef nsresult (*NonJSSizeOfTabFn)(nsPIDOMWindow* aWindow,
   1.468 +                                     size_t* aDomSize,
   1.469 +                                     size_t* aStyleSize,
   1.470 +                                     size_t* aOtherSize);
   1.471 +
   1.472 +nsresult RegisterJSSizeOfTab(JSSizeOfTabFn aSizeOfTabFn);
   1.473 +nsresult RegisterNonJSSizeOfTab(NonJSSizeOfTabFn aSizeOfTabFn);
   1.474 +
   1.475 +}
   1.476 +
   1.477 +#if defined(MOZ_DMD)
   1.478 +namespace mozilla {
   1.479 +namespace dmd {
   1.480 +// This runs all the memory reporters in the current process but does nothing
   1.481 +// with the results;  i.e. it does the minimal amount of work possible for DMD
   1.482 +// to do its thing.  It does nothing with child processes.
   1.483 +void RunReportersForThisProcess();
   1.484 +}
   1.485 +}
   1.486 +
   1.487 +#if !defined(MOZ_MEMORY)
   1.488 +#error "MOZ_DMD requires MOZ_MEMORY"
   1.489 +#endif
   1.490 +
   1.491 +#include "DMD.h"
   1.492 +
   1.493 +#define MOZ_REPORT(ptr)          mozilla::dmd::Report(ptr)
   1.494 +#define MOZ_REPORT_ON_ALLOC(ptr) mozilla::dmd::ReportOnAlloc(ptr)
   1.495 +
   1.496 +#else
   1.497 +
   1.498 +#define MOZ_REPORT(ptr)
   1.499 +#define MOZ_REPORT_ON_ALLOC(ptr)
   1.500 +
   1.501 +#endif  // defined(MOZ_DMD)
   1.502 +
   1.503 +// Functions generated via this macro should be used by all traversal-based
   1.504 +// memory reporters.  Such functions return |moz_malloc_size_of(ptr)|;  this
   1.505 +// will always be zero on some obscure platforms.
   1.506 +//
   1.507 +// You might be wondering why we have a macro that creates multiple functions
   1.508 +// that differ only in their name, instead of a single MallocSizeOf function.
   1.509 +// It's mostly to help with DMD integration, though it sometimes also helps
   1.510 +// with debugging and temporary ad hoc profiling.  The function name chosen
   1.511 +// doesn't matter greatly, but it's best to make it similar to the path used by
   1.512 +// the relevant memory reporter(s).
   1.513 +#define MOZ_DEFINE_MALLOC_SIZE_OF(fn)                                         \
   1.514 +  static size_t fn(const void* aPtr)                                          \
   1.515 +  {                                                                           \
   1.516 +      MOZ_REPORT(aPtr);                                                       \
   1.517 +      return moz_malloc_size_of(aPtr);                                        \
   1.518 +  }
   1.519 +
   1.520 +// Functions generated by the next two macros should be used by wrapping
   1.521 +// allocators that report heap blocks as soon as they are allocated and
   1.522 +// unreport them as soon as they are freed.  Such allocators are used in cases
   1.523 +// where we have third-party code that we cannot modify.  The two functions
   1.524 +// must always be used in tandem.
   1.525 +#define MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(fn)                                \
   1.526 +  static size_t fn(const void* aPtr)                                          \
   1.527 +  {                                                                           \
   1.528 +      MOZ_REPORT_ON_ALLOC(aPtr);                                              \
   1.529 +      return moz_malloc_size_of(aPtr);                                        \
   1.530 +  }
   1.531 +#define MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(fn)                                 \
   1.532 +  static size_t fn(const void* aPtr)                                          \
   1.533 +  {                                                                           \
   1.534 +      return moz_malloc_size_of(aPtr);                                        \
   1.535 +  }
   1.536 +
   1.537 +namespace mozilla {
   1.538 +
   1.539 +// This CRTP class handles several details of wrapping allocators and should
   1.540 +// be preferred to manually counting with MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC
   1.541 +// and MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE.  The typical use is in a memory
   1.542 +// reporter for a particular third party library:
   1.543 +//
   1.544 +//   class MyMemoryReporter : public CountingAllocatorBase<MyMemoryReporter>
   1.545 +//   {
   1.546 +//     ...
   1.547 +//     NS_IMETHODIMP
   1.548 +//     CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
   1.549 +//     {
   1.550 +//        return MOZ_COLLECT_REPORTER(
   1.551 +//          "explicit/path/to/somewhere", KIND_HEAP, UNITS_BYTES,
   1.552 +//          MemoryAllocated(),
   1.553 +//          "A description of what we are reporting."
   1.554 +//     }
   1.555 +//   };
   1.556 +//
   1.557 +//   ...somewhere later in the code...
   1.558 +//   SetThirdPartyMemoryFunctions(MyMemoryReporter::CountingAlloc,
   1.559 +//                                MyMemoryReporter::CountingFree);
   1.560 +template<typename T>
   1.561 +class CountingAllocatorBase
   1.562 +{
   1.563 +public:
   1.564 +  CountingAllocatorBase()
   1.565 +  {
   1.566 +#ifdef DEBUG
   1.567 +    // There must be only one instance of this class, due to |sAmount| being
   1.568 +    // static.
   1.569 +    static bool hasRun = false;
   1.570 +    MOZ_ASSERT(!hasRun);
   1.571 +    hasRun = true;
   1.572 +#endif
   1.573 +  }
   1.574 +
   1.575 +  static size_t
   1.576 +  MemoryAllocated()
   1.577 +  {
   1.578 +    return sAmount;
   1.579 +  }
   1.580 +
   1.581 +  static void*
   1.582 +  CountingMalloc(size_t size)
   1.583 +  {
   1.584 +    void* p = malloc(size);
   1.585 +    sAmount += MallocSizeOfOnAlloc(p);
   1.586 +    return p;
   1.587 +  }
   1.588 +
   1.589 +  static void*
   1.590 +  CountingCalloc(size_t nmemb, size_t size)
   1.591 +  {
   1.592 +    void* p = calloc(nmemb, size);
   1.593 +    sAmount += MallocSizeOfOnAlloc(p);
   1.594 +    return p;
   1.595 +  }
   1.596 +
   1.597 +  static void*
   1.598 +  CountingRealloc(void* p, size_t size)
   1.599 +  {
   1.600 +    size_t oldsize = MallocSizeOfOnFree(p);
   1.601 +    void *pnew = realloc(p, size);
   1.602 +    if (pnew) {
   1.603 +      size_t newsize = MallocSizeOfOnAlloc(pnew);
   1.604 +      sAmount += newsize - oldsize;
   1.605 +    } else if (size == 0) {
   1.606 +      // We asked for a 0-sized (re)allocation of some existing pointer
   1.607 +      // and received NULL in return.  0-sized allocations are permitted
   1.608 +      // to either return NULL or to allocate a unique object per call (!).
   1.609 +      // For a malloc implementation that chooses the second strategy,
   1.610 +      // that allocation may fail (unlikely, but possible).
   1.611 +      //
   1.612 +      // Given a NULL return value and an allocation size of 0, then, we
   1.613 +      // don't know if that means the original pointer was freed or if
   1.614 +      // the allocation of the unique object failed.  If the original
   1.615 +      // pointer was freed, then we have nothing to do here.  If the
   1.616 +      // allocation of the unique object failed, the original pointer is
   1.617 +      // still valid and we ought to undo the decrement from above.
   1.618 +      // However, we have no way of knowing how the underlying realloc
   1.619 +      // implementation is behaving.  Assuming that the original pointer
   1.620 +      // was freed is the safest course of action.  We do, however, need
   1.621 +      // to note that we freed memory.
   1.622 +      sAmount -= oldsize;
   1.623 +    } else {
   1.624 +      // realloc failed.  The amount allocated hasn't changed.
   1.625 +    }
   1.626 +    return pnew;
   1.627 +  }
   1.628 +
   1.629 +  static void
   1.630 +  CountingFree(void* p)
   1.631 +  {
   1.632 +    sAmount -= MallocSizeOfOnFree(p);
   1.633 +    free(p);
   1.634 +  }
   1.635 +
   1.636 +private:
   1.637 +  // |sAmount| can be (implicitly) accessed by multiple threads, so it
   1.638 +  // must be thread-safe.
   1.639 +  static Atomic<size_t> sAmount;
   1.640 +
   1.641 +  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
   1.642 +  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
   1.643 +};
   1.644 +
   1.645 +}
   1.646 +
   1.647 +// This macro assumes the presence of appropriate |aHandleReport| and |aData|
   1.648 +// variables.
   1.649 +#define MOZ_COLLECT_REPORT(path, kind, units, amount, description)            \
   1.650 +  aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(path),           \
   1.651 +                          kind, units, amount,                                \
   1.652 +                          NS_LITERAL_CSTRING(description), aData)
   1.653 +
   1.654 +%}

mercurial