OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/LinuxMallocProfiling.cpp - malloc/new tracing ---------===// | |
2 // | |
3 // The Subzero Code Generator | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 /// | |
10 /// \file | |
11 /// \brief malloc/new/...caller tracing. | |
12 /// | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "LinuxMallocProfiling.h" | |
16 | |
17 #ifdef ALLOW_LINUX_MALLOC_PROFILE | |
Jim Stichnoth
2016/03/17 20:09:06
I would be happier with a blank line before and af
sehr
2016/03/17 20:58:21
Done.
| |
18 #include <dlfcn.h> | |
19 #include <malloc.h> | |
20 #include <unordered_map> | |
21 | |
22 extern "C" void *__libc_malloc(size_t size); | |
23 | |
24 namespace { | |
25 // The Callers structure allocates memory, which would perturb the tracing. | |
26 // InAllocatorFunction is true when we are tracing a new/malloc/... | |
27 bool InAllocatorFunction = false; | |
28 | |
29 // Keep track of the number of times a particular call site address invoked | |
30 // an allocator. NOTE: this is not thread safe, so the user must invoke with | |
31 // --threads=0 to enable profiling. | |
32 using MallocMap = std::unordered_map<void *, uint64_t>; | |
33 MallocMap *Callers; | |
34 | |
35 void *internalAllocator(size_t size, void *caller) { | |
36 if (Callers != nullptr && !InAllocatorFunction) { | |
37 InAllocatorFunction = true; | |
38 ++(*Callers)[caller]; | |
39 InAllocatorFunction = false; | |
40 } | |
41 return __libc_malloc(size); | |
42 } | |
43 } // end of anonymous namespace | |
44 | |
45 // new, new[], and malloc are all defined as weak symbols to allow them | |
Jim Stichnoth
2016/03/17 20:09:05
reflow comment to 80-col
sehr
2016/03/17 20:58:21
Done.
| |
46 // to be overridden by user code. This gives us a convenient place to hook | |
47 // allocation tracking, to record the IP of the caller, which we get from the | |
48 // call to __builtin_return_address. | |
49 void *operator new(size_t size) { | |
50 void *caller = __builtin_return_address(0); | |
51 return internalAllocator(size, caller); | |
52 } | |
53 | |
54 void *operator new[](size_t size) { | |
55 void *caller = __builtin_return_address(0); | |
56 return internalAllocator(size, caller); | |
57 } | |
58 | |
59 extern "C" void *malloc(size_t size) { | |
60 void *caller = __builtin_return_address(0); | |
61 return internalAllocator(size, caller); | |
62 } | |
63 | |
64 namespace Ice { | |
65 | |
66 LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls) | |
67 : Ls(Ls) { | |
68 if (NumThreads != 0) { | |
69 *Ls << "NOTE: Malloc profiling is not thread safe. " | |
70 << "Use --threads=0 to enable.\n"; | |
Jim Stichnoth
2016/03/17 20:09:06
Tiny nit: omit the last "<<" and take advantage of
sehr
2016/03/17 20:58:21
Done.
| |
71 return; | |
72 } | |
73 Callers = new MallocMap(); | |
74 } | |
75 | |
76 LinuxMallocProfiling::~LinuxMallocProfiling() { | |
77 if (Callers == nullptr) { | |
78 return; | |
79 } | |
80 for (const auto &C : *Callers) { | |
81 Dl_info dli; | |
82 dladdr(C.first, &dli); | |
83 | |
84 *Ls << C.second << " "; | |
85 if (dli.dli_sname == NULL) { | |
86 *Ls << C.first; | |
87 } else { | |
88 *Ls << dli.dli_sname; | |
89 } | |
90 *Ls << "\n"; | |
91 } | |
92 delete Callers; | |
93 Callers = nullptr; | |
94 } | |
95 } // end of namespace Ice | |
96 #else // !ALLOW_LINUX_MALLOC_PROFILE | |
97 namespace Ice { | |
98 | |
99 LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls) { | |
100 (void)NumThreads; | |
101 (void)Ls; | |
102 } | |
103 | |
104 LinuxMallocProfiling::~LinuxMallocProfiling() {} | |
105 } // end of namespace Ice | |
106 #endif // ALLOW_LINUX_MALLOC_PROFILE | |
OLD | NEW |