Chromium Code Reviews| Index: src/LinuxMallocProfiling.cpp |
| diff --git a/src/LinuxMallocProfiling.cpp b/src/LinuxMallocProfiling.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..61b123384e5ee162a7866be67065528e3ee82bd2 |
| --- /dev/null |
| +++ b/src/LinuxMallocProfiling.cpp |
| @@ -0,0 +1,106 @@ |
| +//===- subzero/src/LinuxMallocProfiling.cpp - malloc/new tracing ---------===// |
| +// |
| +// The Subzero Code Generator |
| +// |
| +// This file is distributed under the University of Illinois Open Source |
| +// License. See LICENSE.TXT for details. |
| +// |
| +//===----------------------------------------------------------------------===// |
| +/// |
| +/// \file |
| +/// \brief malloc/new/...caller tracing. |
| +/// |
| +//===----------------------------------------------------------------------===// |
| + |
| +#include "LinuxMallocProfiling.h" |
| + |
| +#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.
|
| +#include <dlfcn.h> |
| +#include <malloc.h> |
| +#include <unordered_map> |
| + |
| +extern "C" void *__libc_malloc(size_t size); |
| + |
| +namespace { |
| +// The Callers structure allocates memory, which would perturb the tracing. |
| +// InAllocatorFunction is true when we are tracing a new/malloc/... |
| +bool InAllocatorFunction = false; |
| + |
| +// Keep track of the number of times a particular call site address invoked |
| +// an allocator. NOTE: this is not thread safe, so the user must invoke with |
| +// --threads=0 to enable profiling. |
| +using MallocMap = std::unordered_map<void *, uint64_t>; |
| +MallocMap *Callers; |
| + |
| +void *internalAllocator(size_t size, void *caller) { |
| + if (Callers != nullptr && !InAllocatorFunction) { |
| + InAllocatorFunction = true; |
| + ++(*Callers)[caller]; |
| + InAllocatorFunction = false; |
| + } |
| + return __libc_malloc(size); |
| +} |
| +} // end of anonymous namespace |
| + |
| +// 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.
|
| +// to be overridden by user code. This gives us a convenient place to hook |
| +// allocation tracking, to record the IP of the caller, which we get from the |
| +// call to __builtin_return_address. |
| +void *operator new(size_t size) { |
| + void *caller = __builtin_return_address(0); |
| + return internalAllocator(size, caller); |
| +} |
| + |
| +void *operator new[](size_t size) { |
| + void *caller = __builtin_return_address(0); |
| + return internalAllocator(size, caller); |
| +} |
| + |
| +extern "C" void *malloc(size_t size) { |
| + void *caller = __builtin_return_address(0); |
| + return internalAllocator(size, caller); |
| +} |
| + |
| +namespace Ice { |
| + |
| +LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls) |
| + : Ls(Ls) { |
| + if (NumThreads != 0) { |
| + *Ls << "NOTE: Malloc profiling is not thread safe. " |
| + << "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.
|
| + return; |
| + } |
| + Callers = new MallocMap(); |
| +} |
| + |
| +LinuxMallocProfiling::~LinuxMallocProfiling() { |
| + if (Callers == nullptr) { |
| + return; |
| + } |
| + for (const auto &C : *Callers) { |
| + Dl_info dli; |
| + dladdr(C.first, &dli); |
| + |
| + *Ls << C.second << " "; |
| + if (dli.dli_sname == NULL) { |
| + *Ls << C.first; |
| + } else { |
| + *Ls << dli.dli_sname; |
| + } |
| + *Ls << "\n"; |
| + } |
| + delete Callers; |
| + Callers = nullptr; |
| +} |
| +} // end of namespace Ice |
| +#else // !ALLOW_LINUX_MALLOC_PROFILE |
| +namespace Ice { |
| + |
| +LinuxMallocProfiling::LinuxMallocProfiling(size_t NumThreads, Ostream *Ls) { |
| + (void)NumThreads; |
| + (void)Ls; |
| +} |
| + |
| +LinuxMallocProfiling::~LinuxMallocProfiling() {} |
| +} // end of namespace Ice |
| +#endif // ALLOW_LINUX_MALLOC_PROFILE |