Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/CountingAllocatorBase.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#ifndef CountingAllocatorBase_h
8
#define CountingAllocatorBase_h
9
10
#include "mozilla/Assertions.h"
11
#include "mozilla/Atomics.h"
12
#include "nsIMemoryReporter.h"
13
14
namespace mozilla {
15
16
// This CRTP class handles several details of wrapping allocators and should
17
// be preferred to manually counting with MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC
18
// and MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE.  The typical use is in a memory
19
// reporter for a particular third party library:
20
//
21
//   class MyMemoryReporter : public CountingAllocatorBase<MyMemoryReporter>
22
//   {
23
//     ...
24
//     NS_IMETHOD
25
//     CollectReports(nsIHandleReportCallback* aHandleReport,
26
//                    nsISupports* aData, bool aAnonymize) override
27
//     {
28
//        MOZ_COLLECT_REPORT(
29
//          "explicit/path/to/somewhere", KIND_HEAP, UNITS_BYTES,
30
//          MemoryAllocated(),
31
//          "A description of what we are reporting.");
32
//
33
//        return NS_OK;
34
//     }
35
//   };
36
//
37
//   ...somewhere later in the code...
38
//   SetThirdPartyMemoryFunctions(MyMemoryReporter::CountingAlloc,
39
//                                MyMemoryReporter::CountingFree);
40
template<typename T>
41
class CountingAllocatorBase
42
{
43
public:
44
  CountingAllocatorBase()
45
6
  {
46
#ifdef DEBUG
47
    // There must be only one instance of this class, due to |sAmount| being
48
    // static.
49
    static bool hasRun = false;
50
    MOZ_ASSERT(!hasRun);
51
    hasRun = true;
52
#endif
53
  }
mozilla::CountingAllocatorBase<ICUReporter>::CountingAllocatorBase()
Line
Count
Source
45
3
  {
46
#ifdef DEBUG
47
    // There must be only one instance of this class, due to |sAmount| being
48
    // static.
49
    static bool hasRun = false;
50
    MOZ_ASSERT(!hasRun);
51
    hasRun = true;
52
#endif
53
  }
mozilla::CountingAllocatorBase<OggReporter>::CountingAllocatorBase()
Line
Count
Source
45
3
  {
46
#ifdef DEBUG
47
    // There must be only one instance of this class, due to |sAmount| being
48
    // static.
49
    static bool hasRun = false;
50
    MOZ_ASSERT(!hasRun);
51
    hasRun = true;
52
#endif
53
  }
54
55
  static size_t
56
  MemoryAllocated()
57
0
  {
58
0
    return sAmount;
59
0
  }
Unexecuted instantiation: mozilla::CountingAllocatorBase<ICUReporter>::MemoryAllocated()
Unexecuted instantiation: mozilla::CountingAllocatorBase<OggReporter>::MemoryAllocated()
Unexecuted instantiation: mozilla::CountingAllocatorBase<HunspellAllocator>::MemoryAllocated()
60
61
  static void*
62
  CountingMalloc(size_t size)
63
2.52k
  {
64
2.52k
    void* p = malloc(size);
65
2.52k
    sAmount += MallocSizeOfOnAlloc(p);
66
2.52k
    return p;
67
2.52k
  }
mozilla::CountingAllocatorBase<ICUReporter>::CountingMalloc(unsigned long)
Line
Count
Source
63
2.52k
  {
64
2.52k
    void* p = malloc(size);
65
2.52k
    sAmount += MallocSizeOfOnAlloc(p);
66
2.52k
    return p;
67
2.52k
  }
Unexecuted instantiation: mozilla::CountingAllocatorBase<OggReporter>::CountingMalloc(unsigned long)
Unexecuted instantiation: mozilla::CountingAllocatorBase<HunspellAllocator>::CountingMalloc(unsigned long)
68
69
  static void*
70
  CountingCalloc(size_t nmemb, size_t size)
71
0
  {
72
0
    void* p = calloc(nmemb, size);
73
0
    sAmount += MallocSizeOfOnAlloc(p);
74
0
    return p;
75
0
  }
Unexecuted instantiation: mozilla::CountingAllocatorBase<OggReporter>::CountingCalloc(unsigned long, unsigned long)
Unexecuted instantiation: mozilla::CountingAllocatorBase<HunspellAllocator>::CountingCalloc(unsigned long, unsigned long)
76
77
  static void*
78
  CountingRealloc(void* p, size_t size)
79
0
  {
80
0
    size_t oldsize = MallocSizeOfOnFree(p);
81
0
    void *pnew = realloc(p, size);
82
0
    if (pnew) {
83
0
      size_t newsize = MallocSizeOfOnAlloc(pnew);
84
0
      sAmount += newsize - oldsize;
85
0
    } else if (size == 0) {
86
0
      // We asked for a 0-sized (re)allocation of some existing pointer
87
0
      // and received NULL in return.  0-sized allocations are permitted
88
0
      // to either return NULL or to allocate a unique object per call (!).
89
0
      // For a malloc implementation that chooses the second strategy,
90
0
      // that allocation may fail (unlikely, but possible).
91
0
      //
92
0
      // Given a NULL return value and an allocation size of 0, then, we
93
0
      // don't know if that means the original pointer was freed or if
94
0
      // the allocation of the unique object failed.  If the original
95
0
      // pointer was freed, then we have nothing to do here.  If the
96
0
      // allocation of the unique object failed, the original pointer is
97
0
      // still valid and we ought to undo the decrement from above.
98
0
      // However, we have no way of knowing how the underlying realloc
99
0
      // implementation is behaving.  Assuming that the original pointer
100
0
      // was freed is the safest course of action.  We do, however, need
101
0
      // to note that we freed memory.
102
0
      sAmount -= oldsize;
103
0
    } else {
104
0
      // realloc failed.  The amount allocated hasn't changed.
105
0
    }
106
0
    return pnew;
107
0
  }
Unexecuted instantiation: mozilla::CountingAllocatorBase<ICUReporter>::CountingRealloc(void*, unsigned long)
Unexecuted instantiation: mozilla::CountingAllocatorBase<OggReporter>::CountingRealloc(void*, unsigned long)
Unexecuted instantiation: mozilla::CountingAllocatorBase<HunspellAllocator>::CountingRealloc(void*, unsigned long)
108
109
  // Some library code expects that realloc(x, 0) will free x, which is not
110
  // the behavior of the version of jemalloc we're using, so this wrapped
111
  // version of realloc is needed.
112
  static void*
113
  CountingFreeingRealloc(void* p, size_t size)
114
  {
115
    if (size == 0) {
116
      CountingFree(p);
117
      return nullptr;
118
    }
119
    return CountingRealloc(p, size);
120
  }
121
122
  static void
123
  CountingFree(void* p)
124
2.47k
  {
125
2.47k
    sAmount -= MallocSizeOfOnFree(p);
126
2.47k
    free(p);
127
2.47k
  }
mozilla::CountingAllocatorBase<ICUReporter>::CountingFree(void*)
Line
Count
Source
124
2.47k
  {
125
2.47k
    sAmount -= MallocSizeOfOnFree(p);
126
2.47k
    free(p);
127
2.47k
  }
Unexecuted instantiation: mozilla::CountingAllocatorBase<OggReporter>::CountingFree(void*)
Unexecuted instantiation: mozilla::CountingAllocatorBase<HunspellAllocator>::CountingFree(void*)
128
129
private:
130
  // |sAmount| can be (implicitly) accessed by multiple threads, so it
131
  // must be thread-safe. It may be written during GC, so accesses are not
132
  // recorded.
133
  typedef Atomic<size_t, SequentiallyConsistent, recordreplay::Behavior::DontPreserve> AmountType;
134
  static AmountType sAmount;
135
136
  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
137
  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
138
};
139
140
} // namespace mozilla
141
142
#endif // CountingAllocatorBase_h