Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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 "nsISupports.idl"
9 interface nsIDOMWindow;
10 interface nsIRunnable;
11 interface nsISimpleEnumerator;
13 /*
14 * Memory reporters measure Firefox's memory usage. They are primarily used to
15 * generate the about:memory page. You should read
16 * https://wiki.mozilla.org/Memory_Reporting before writing a memory
17 * reporter.
18 */
20 [scriptable, function, uuid(3a61be3b-b93b-461a-a4f8-388214f558b1)]
21 interface nsIMemoryReporterCallback : nsISupports
22 {
23 /*
24 * The arguments to the callback are as follows.
25 *
26 *
27 * |process| The name of the process containing this reporter. Each
28 * reporter initially has "" in this field, indicating that it applies to the
29 * current process. (This is true even for reporters in a child process.)
30 * When a reporter from a child process is copied into the main process, the
31 * copy has its 'process' field set appropriately.
32 *
33 *
34 * |path| The path that this memory usage should be reported under. Paths
35 * are '/'-delimited, eg. "a/b/c".
36 *
37 * Each reporter can be viewed as representing a leaf node in a tree.
38 * Internal nodes of the tree don't have reporters. So, for example, the
39 * reporters "explicit/a/b", "explicit/a/c", "explicit/d/e", and
40 * "explicit/d/f" define this tree:
41 *
42 * explicit
43 * |--a
44 * | |--b [*]
45 * | \--c [*]
46 * \--d
47 * |--e [*]
48 * \--f [*]
49 *
50 * Nodes marked with a [*] have a reporter. Notice that the internal
51 * nodes are implicitly defined by the paths.
52 *
53 * Nodes within a tree should not overlap measurements, otherwise the
54 * parent node measurements will be double-counted. So in the example
55 * above, |b| should not count any allocations counted by |c|, and vice
56 * versa.
57 *
58 * All nodes within each tree must have the same units.
59 *
60 * If you want to include a '/' not as a path separator, e.g. because the
61 * path contains a URL, you need to convert each '/' in the URL to a '\'.
62 * Consumers of the path will undo this change. Any other '\' character
63 * in a path will also be changed. This is clumsy but hasn't caused any
64 * problems so far.
65 *
66 * The paths of all reporters form a set of trees. Trees can be
67 * "degenerate", i.e. contain a single entry with no '/'.
68 *
69 *
70 * |kind| There are three kinds of memory reporters.
71 *
72 * - HEAP: reporters measuring memory allocated by the heap allocator,
73 * e.g. by calling malloc, calloc, realloc, memalign, operator new, or
74 * operator new[]. Reporters in this category must have units
75 * UNITS_BYTES.
76 *
77 * - NONHEAP: reporters measuring memory which the program explicitly
78 * allocated, but does not live on the heap. Such memory is commonly
79 * allocated by calling one of the OS's memory-mapping functions (e.g.
80 * mmap, VirtualAlloc, or vm_allocate). Reporters in this category
81 * must have units UNITS_BYTES.
82 *
83 * - OTHER: reporters which don't fit into either of these categories.
84 * They can have any units.
85 *
86 * The kind only matters for reporters in the "explicit" tree;
87 * aboutMemory.js uses it to calculate "heap-unclassified".
88 *
89 *
90 * |units| The units on the reporter's amount. One of the following.
91 *
92 * - BYTES: The amount contains a number of bytes.
93 *
94 * - COUNT: The amount is an instantaneous count of things currently in
95 * existence. For instance, the number of tabs currently open would have
96 * units COUNT.
97 *
98 * - COUNT_CUMULATIVE: The amount contains the number of times some event
99 * has occurred since the application started up. For instance, the
100 * number of times the user has opened a new tab would have units
101 * COUNT_CUMULATIVE.
102 *
103 * The amount returned by a reporter with units COUNT_CUMULATIVE must
104 * never decrease over the lifetime of the application.
105 *
106 * - PERCENTAGE: The amount contains a fraction that should be expressed as
107 * a percentage. NOTE! The |amount| field should be given a value 100x
108 * the actual percentage; this number will be divided by 100 when shown.
109 * This allows a fractional percentage to be shown even though |amount| is
110 * an integer. E.g. if the actual percentage is 12.34%, |amount| should
111 * be 1234.
112 *
113 * Values greater than 100% are allowed.
114 *
115 *
116 * |amount| The numeric value reported by this memory reporter. Accesses
117 * can fail if something goes wrong when getting the amount.
118 *
119 *
120 * |description| A human-readable description of this memory usage report.
121 */
122 void callback(in ACString process, in AUTF8String path, in int32_t kind,
123 in int32_t units, in int64_t amount,
124 in AUTF8String description, in nsISupports data);
125 };
127 /*
128 * An nsIMemoryReporter reports one or more memory measurements via a
129 * callback function which is called once for each measurement.
130 *
131 * An nsIMemoryReporter that reports a single measurement is sometimes called a
132 * "uni-reporter". One that reports multiple measurements is sometimes called
133 * a "multi-reporter".
134 *
135 * aboutMemory.js is the most important consumer of memory reports. It
136 * places the following constraints on reports.
137 *
138 * - All reports within a single sub-tree must have the same units.
139 *
140 * - There may be an "explicit" tree. If present, it represents
141 * non-overlapping regions of memory that have been explicitly allocated with
142 * an OS-level allocation (e.g. mmap/VirtualAlloc/vm_allocate) or a
143 * heap-level allocation (e.g. malloc/calloc/operator new). Reporters in
144 * this tree must have kind HEAP or NONHEAP, units BYTES.
145 *
146 * It is preferred, but not required, that report descriptions use complete
147 * sentences (i.e. start with a capital letter and end with a period, or
148 * similar).
149 */
150 [scriptable, uuid(0884cd0f-5829-4381-979b-0f53904030ed)]
151 interface nsIMemoryReporter : nsISupports
152 {
153 /*
154 * Run the reporter.
155 */
156 void collectReports(in nsIMemoryReporterCallback callback,
157 in nsISupports data);
159 /*
160 * Kinds. See the |kind| comment in nsIMemoryReporterCallback.
161 */
162 const int32_t KIND_NONHEAP = 0;
163 const int32_t KIND_HEAP = 1;
164 const int32_t KIND_OTHER = 2;
166 /*
167 * Units. See the |units| comment in nsIMemoryReporterCallback.
168 */
169 const int32_t UNITS_BYTES = 0;
170 const int32_t UNITS_COUNT = 1;
171 const int32_t UNITS_COUNT_CUMULATIVE = 2;
172 const int32_t UNITS_PERCENTAGE = 3;
173 };
175 [scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)]
176 interface nsIFinishReportingCallback : nsISupports
177 {
178 void callback(in nsISupports data);
179 };
181 [scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)]
182 interface nsIMemoryReporterManager : nsISupports
183 {
184 /*
185 * Initialize.
186 */
187 void init();
189 /*
190 * Register the given nsIMemoryReporter. The Manager service will hold a
191 * strong reference to the given reporter, and will be responsible for freeing
192 * the reporter at shutdown. You may manually unregister the reporter with
193 * unregisterStrongReporter() at any point.
194 */
195 void registerStrongReporter(in nsIMemoryReporter reporter);
197 /*
198 * Like registerReporter, but the Manager service will hold a weak reference
199 * via a raw pointer to the given reporter. The reporter should be
200 * unregistered before shutdown.
201 * You cannot register JavaScript components with this function! Always
202 * register your JavaScript components with registerStrongReporter().
203 */
204 void registerWeakReporter(in nsIMemoryReporter reporter);
206 /*
207 * Unregister the given memory reporter, which must have been registered with
208 * registerStrongReporter(). You normally don't need to unregister your
209 * strong reporters, as nsIMemoryReporterManager will take care of that at
210 * shutdown.
211 */
212 void unregisterStrongReporter(in nsIMemoryReporter reporter);
214 /*
215 * Unregister the given memory reporter, which must have been registered with
216 * registerWeakReporter().
217 */
218 void unregisterWeakReporter(in nsIMemoryReporter reporter);
220 /*
221 * These functions should only be used for testing purposes.
222 */
223 void blockRegistrationAndHideExistingReporters();
224 void unblockRegistrationAndRestoreOriginalReporters();
225 void registerStrongReporterEvenIfBlocked(in nsIMemoryReporter aReporter);
227 /*
228 * Get memory reports for the current process and all child processes.
229 * |handleReport| is called for each report, and |finishReporting| is called
230 * once all reports have been handled.
231 *
232 * |finishReporting| is called even if, for example, some child processes
233 * fail to report back. However, calls to this method will silently and
234 * immediately abort -- and |finishReporting| will not be called -- if a
235 * previous getReports() call is still in flight, i.e. if it has not yet
236 * finished invoking |finishReporting|. The silent abort is because the
237 * in-flight request will finish soon, and the caller would very likely just
238 * catch and ignore any error anyway.
239 */
240 void getReports(in nsIMemoryReporterCallback handleReport,
241 in nsISupports handleReportData,
242 in nsIFinishReportingCallback finishReporting,
243 in nsISupports finishReportingData);
245 /*
246 * As above, but: If |minimizeMemoryUsage| is true, then each process will
247 * minimize its memory usage (see the |minimizeMemoryUsage| method) before
248 * gathering its report. If DMD is enabled and |DMDDumpIdent| is non-empty
249 * then write a DMD report to a file in the usual temporary directory (see
250 * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
251 */
252 [noscript] void
253 getReportsExtended(in nsIMemoryReporterCallback handleReport,
254 in nsISupports handleReportData,
255 in nsIFinishReportingCallback finishReporting,
256 in nsISupports finishReportingData,
257 in boolean minimizeMemoryUsage,
258 in AString DMDDumpIdent);
260 /*
261 * Get memory reports in the current process only. |handleReport| is called
262 * for each report.
263 */
264 void getReportsForThisProcess(in nsIMemoryReporterCallback handleReport,
265 in nsISupports handleReportData);
267 /*
268 * As above, but if DMD is enabled and |DMDDumpIdent| is non-empty
269 * then write a DMD report to a file in the usual temporary directory (see
270 * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
271 */
272 [noscript] void
273 getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport,
274 in nsISupports handleReportData,
275 in AString DMDDumpIdent);
277 /*
278 * The memory reporter manager, for the most part, treats reporters
279 * registered with it as a black box. However, there are some
280 * "distinguished" amounts (as could be reported by a memory reporter) that
281 * the manager provides as attributes, because they are sufficiently
282 * interesting that we want external code (e.g. telemetry) to be able to rely
283 * on them.
284 *
285 * Note that these are not reporters and so getReports() and
286 * getReportsForThisProcess() do not look at them. However, distinguished
287 * amounts can be embedded in a reporter.
288 *
289 * Access to these attributes can fail. In particular, some of them are not
290 * available on all platforms.
291 *
292 * If you add a new distinguished amount, please update
293 * toolkit/components/aboutmemory/tests/test_memoryReporters.xul.
294 *
295 * |explicit| (UNITS_BYTES) The total size of explicit memory allocations,
296 * both at the OS-level (eg. via mmap, VirtualAlloc) and at the heap level
297 * (eg. via malloc, calloc, operator new). It covers all heap allocations,
298 * but will miss any OS-level ones not covered by memory reporters.
299 *
300 * |vsize| (UNITS_BYTES) The virtual size, i.e. the amount of address space
301 * taken up.
302 *
303 * |vsizeMaxContiguous| (UNITS_BYTES) The size of the largest contiguous
304 * block of virtual memory.
305 *
306 * |resident| (UNITS_BYTES) The resident size (a.k.a. RSS or physical memory
307 * used).
308 *
309 * |residentFast| (UNITS_BYTES) This is like |resident|, but on Mac OS
310 * |resident| can purge pages, which is slow. It also affects the result of
311 * |residentFast|, and so |resident| and |residentFast| should not be used
312 * together.
313 *
314 * |heapAllocated| (UNITS_BYTES) Memory mapped by the heap allocator.
315 *
316 * |heapOverheadRatio| (UNITS_PERCENTAGE) In the heap allocator, this is the
317 * ratio of committed, unused bytes to allocated bytes. Like all
318 * UNITS_PERCENTAGE measurements, its amount is multiplied by 100x so it can
319 * be represented by an int64_t.
320 *
321 * |JSMainRuntimeGCHeap| (UNITS_BYTES) Size of the main JS runtime's GC
322 * heap.
323 *
324 * |JSMainRuntimeTemporaryPeak| (UNITS_BYTES) Peak size of the transient
325 * storage in the main JSRuntime.
326 *
327 * |JSMainRuntimeCompartments{System,User}| (UNITS_COUNT) The number of
328 * {system,user} compartments in the main JS runtime.
329 *
330 * |imagesContentUsedUncompressed| (UNITS_BYTES) Memory used for decoded
331 * images in content.
332 *
333 * |storageSQLite| (UNITS_BYTES) Memory used by SQLite.
334 *
335 * |lowMemoryEvents{Virtual,Physical}| (UNITS_COUNT_CUMULATIVE) The number
336 * of low-{virtual,physical}-memory events that have occurred since the
337 * process started.
338 *
339 * |ghostWindows| (UNITS_COUNT) The number of ghost windows.
340 *
341 * |pageFaultsHard| (UNITS_COUNT_CUMULATIVE) The number of hard (a.k.a.
342 * major) page faults that have occurred since the process started.
343 */
344 readonly attribute int64_t explicit;
345 readonly attribute int64_t vsize;
346 readonly attribute int64_t vsizeMaxContiguous;
347 readonly attribute int64_t resident;
348 readonly attribute int64_t residentFast;
350 readonly attribute int64_t heapAllocated;
351 readonly attribute int64_t heapOverheadRatio;
353 readonly attribute int64_t JSMainRuntimeGCHeap;
354 readonly attribute int64_t JSMainRuntimeTemporaryPeak;
355 readonly attribute int64_t JSMainRuntimeCompartmentsSystem;
356 readonly attribute int64_t JSMainRuntimeCompartmentsUser;
358 readonly attribute int64_t imagesContentUsedUncompressed;
360 readonly attribute int64_t storageSQLite;
362 readonly attribute int64_t lowMemoryEventsVirtual;
363 readonly attribute int64_t lowMemoryEventsPhysical;
365 readonly attribute int64_t ghostWindows;
367 readonly attribute int64_t pageFaultsHard;
369 /*
370 * This attribute indicates if moz_malloc_usable_size() works.
371 */
372 [infallible] readonly attribute boolean hasMozMallocUsableSize;
374 /*
375 * Run a series of GC/CC's in an attempt to minimize the application's memory
376 * usage. When we're finished, we invoke the given runnable if it's not
377 * null.
378 */
379 void minimizeMemoryUsage(in nsIRunnable callback);
381 /*
382 * Measure the memory that is known to be owned by this tab, split up into
383 * several broad categories. Note that this will be an underestimate of the
384 * true number, due to imperfect memory reporter coverage (corresponding to
385 * about:memory's "heap-unclassified"), and due to some memory shared between
386 * tabs not being counted.
387 *
388 * The time taken for the measurement (split into JS and non-JS parts) is
389 * also returned.
390 */
391 void sizeOfTab(in nsIDOMWindow window,
392 out int64_t jsObjectsSize, out int64_t jsStringsSize,
393 out int64_t jsOtherSize, out int64_t domSize,
394 out int64_t styleSize, out int64_t otherSize,
395 out int64_t totalSize,
396 out double jsMilliseconds, out double nonJSMilliseconds);
397 };
399 %{C++
401 #include "js/TypeDecls.h"
402 #include "nsStringGlue.h"
403 #include "nsTArray.h"
404 #include "mozilla/Atomics.h"
406 class nsPIDOMWindow;
408 // nsIHandleReportCallback is a better name, but keep nsIMemoryReporterCallback
409 // around for backwards compatibility.
410 typedef nsIMemoryReporterCallback nsIHandleReportCallback;
412 namespace mozilla {
414 // Register a memory reporter. The manager service will hold a strong
415 // reference to this reporter.
416 XPCOM_API(nsresult) RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter);
418 // Register a memory reporter. The manager service will hold a weak reference
419 // to this reporter.
420 XPCOM_API(nsresult) RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
422 // Unregister a weak memory reporter.
423 XPCOM_API(nsresult) UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
425 // The memory reporter manager provides access to several distinguished
426 // amounts via attributes. Some of these amounts are provided by Gecko
427 // components that cannot be accessed directly from XPCOM code. So we provide
428 // the following functions for those components to be registered with the
429 // manager.
431 typedef int64_t (*InfallibleAmountFn)();
432 typedef nsresult (*FallibleAmountFn)(int64_t* aAmount);
434 #define DECL_REGISTER_DISTINGUISHED_AMOUNT(kind, name) \
435 nsresult Register##name##DistinguishedAmount(kind##AmountFn aAmountFn);
436 #define DECL_UNREGISTER_DISTINGUISHED_AMOUNT(name) \
437 nsresult Unregister##name##DistinguishedAmount();
439 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeGCHeap)
440 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeTemporaryPeak)
441 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsSystem)
442 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsUser)
444 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, ImagesContentUsedUncompressed)
446 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, StorageSQLite)
447 DECL_UNREGISTER_DISTINGUISHED_AMOUNT(StorageSQLite)
449 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsVirtual)
450 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsPhysical)
452 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, GhostWindows)
454 #undef DECL_REGISTER_DISTINGUISHED_AMOUNT
455 #undef DECL_UNREGISTER_DISTINGUISHED_AMOUNT
457 // Likewise for per-tab measurement.
459 typedef nsresult (*JSSizeOfTabFn)(JSObject* aObj,
460 size_t* aJsObjectsSize,
461 size_t* aJsStringSize,
462 size_t* aJsPrivateSize,
463 size_t* aJsOtherSize);
464 typedef nsresult (*NonJSSizeOfTabFn)(nsPIDOMWindow* aWindow,
465 size_t* aDomSize,
466 size_t* aStyleSize,
467 size_t* aOtherSize);
469 nsresult RegisterJSSizeOfTab(JSSizeOfTabFn aSizeOfTabFn);
470 nsresult RegisterNonJSSizeOfTab(NonJSSizeOfTabFn aSizeOfTabFn);
472 }
474 #if defined(MOZ_DMD)
475 namespace mozilla {
476 namespace dmd {
477 // This runs all the memory reporters in the current process but does nothing
478 // with the results; i.e. it does the minimal amount of work possible for DMD
479 // to do its thing. It does nothing with child processes.
480 void RunReportersForThisProcess();
481 }
482 }
484 #if !defined(MOZ_MEMORY)
485 #error "MOZ_DMD requires MOZ_MEMORY"
486 #endif
488 #include "DMD.h"
490 #define MOZ_REPORT(ptr) mozilla::dmd::Report(ptr)
491 #define MOZ_REPORT_ON_ALLOC(ptr) mozilla::dmd::ReportOnAlloc(ptr)
493 #else
495 #define MOZ_REPORT(ptr)
496 #define MOZ_REPORT_ON_ALLOC(ptr)
498 #endif // defined(MOZ_DMD)
500 // Functions generated via this macro should be used by all traversal-based
501 // memory reporters. Such functions return |moz_malloc_size_of(ptr)|; this
502 // will always be zero on some obscure platforms.
503 //
504 // You might be wondering why we have a macro that creates multiple functions
505 // that differ only in their name, instead of a single MallocSizeOf function.
506 // It's mostly to help with DMD integration, though it sometimes also helps
507 // with debugging and temporary ad hoc profiling. The function name chosen
508 // doesn't matter greatly, but it's best to make it similar to the path used by
509 // the relevant memory reporter(s).
510 #define MOZ_DEFINE_MALLOC_SIZE_OF(fn) \
511 static size_t fn(const void* aPtr) \
512 { \
513 MOZ_REPORT(aPtr); \
514 return moz_malloc_size_of(aPtr); \
515 }
517 // Functions generated by the next two macros should be used by wrapping
518 // allocators that report heap blocks as soon as they are allocated and
519 // unreport them as soon as they are freed. Such allocators are used in cases
520 // where we have third-party code that we cannot modify. The two functions
521 // must always be used in tandem.
522 #define MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(fn) \
523 static size_t fn(const void* aPtr) \
524 { \
525 MOZ_REPORT_ON_ALLOC(aPtr); \
526 return moz_malloc_size_of(aPtr); \
527 }
528 #define MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(fn) \
529 static size_t fn(const void* aPtr) \
530 { \
531 return moz_malloc_size_of(aPtr); \
532 }
534 namespace mozilla {
536 // This CRTP class handles several details of wrapping allocators and should
537 // be preferred to manually counting with MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC
538 // and MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE. The typical use is in a memory
539 // reporter for a particular third party library:
540 //
541 // class MyMemoryReporter : public CountingAllocatorBase<MyMemoryReporter>
542 // {
543 // ...
544 // NS_IMETHODIMP
545 // CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
546 // {
547 // return MOZ_COLLECT_REPORTER(
548 // "explicit/path/to/somewhere", KIND_HEAP, UNITS_BYTES,
549 // MemoryAllocated(),
550 // "A description of what we are reporting."
551 // }
552 // };
553 //
554 // ...somewhere later in the code...
555 // SetThirdPartyMemoryFunctions(MyMemoryReporter::CountingAlloc,
556 // MyMemoryReporter::CountingFree);
557 template<typename T>
558 class CountingAllocatorBase
559 {
560 public:
561 CountingAllocatorBase()
562 {
563 #ifdef DEBUG
564 // There must be only one instance of this class, due to |sAmount| being
565 // static.
566 static bool hasRun = false;
567 MOZ_ASSERT(!hasRun);
568 hasRun = true;
569 #endif
570 }
572 static size_t
573 MemoryAllocated()
574 {
575 return sAmount;
576 }
578 static void*
579 CountingMalloc(size_t size)
580 {
581 void* p = malloc(size);
582 sAmount += MallocSizeOfOnAlloc(p);
583 return p;
584 }
586 static void*
587 CountingCalloc(size_t nmemb, size_t size)
588 {
589 void* p = calloc(nmemb, size);
590 sAmount += MallocSizeOfOnAlloc(p);
591 return p;
592 }
594 static void*
595 CountingRealloc(void* p, size_t size)
596 {
597 size_t oldsize = MallocSizeOfOnFree(p);
598 void *pnew = realloc(p, size);
599 if (pnew) {
600 size_t newsize = MallocSizeOfOnAlloc(pnew);
601 sAmount += newsize - oldsize;
602 } else if (size == 0) {
603 // We asked for a 0-sized (re)allocation of some existing pointer
604 // and received NULL in return. 0-sized allocations are permitted
605 // to either return NULL or to allocate a unique object per call (!).
606 // For a malloc implementation that chooses the second strategy,
607 // that allocation may fail (unlikely, but possible).
608 //
609 // Given a NULL return value and an allocation size of 0, then, we
610 // don't know if that means the original pointer was freed or if
611 // the allocation of the unique object failed. If the original
612 // pointer was freed, then we have nothing to do here. If the
613 // allocation of the unique object failed, the original pointer is
614 // still valid and we ought to undo the decrement from above.
615 // However, we have no way of knowing how the underlying realloc
616 // implementation is behaving. Assuming that the original pointer
617 // was freed is the safest course of action. We do, however, need
618 // to note that we freed memory.
619 sAmount -= oldsize;
620 } else {
621 // realloc failed. The amount allocated hasn't changed.
622 }
623 return pnew;
624 }
626 static void
627 CountingFree(void* p)
628 {
629 sAmount -= MallocSizeOfOnFree(p);
630 free(p);
631 }
633 private:
634 // |sAmount| can be (implicitly) accessed by multiple threads, so it
635 // must be thread-safe.
636 static Atomic<size_t> sAmount;
638 MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
639 MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
640 };
642 }
644 // This macro assumes the presence of appropriate |aHandleReport| and |aData|
645 // variables.
646 #define MOZ_COLLECT_REPORT(path, kind, units, amount, description) \
647 aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(path), \
648 kind, units, amount, \
649 NS_LITERAL_CSTRING(description), aData)
651 %}