Index: src/LinuxMallocProfiling.cpp |
diff --git a/src/LinuxMallocProfiling.cpp b/src/LinuxMallocProfiling.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..25782cde7574749ed34c64ec161975d04e87cba6 |
--- /dev/null |
+++ b/src/LinuxMallocProfiling.cpp |
@@ -0,0 +1,92 @@ |
+//===- 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/15 15:36:50
I don't like all the #ifdef here.
I think it woul
sehr
2016/03/17 16:47:14
Done.
|
+#include <dlfcn.h> |
+#include <malloc.h> |
+#include <iostream> |
Jim Stichnoth
2016/03/15 15:36:50
LLVM sez iostream is forbidden.
http://llvm.org/d
sehr
2016/03/17 16:47:14
I plumbed through the Ostream that was already use
|
+#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 profilin. |
John
2016/03/15 15:19:06
profiling
sehr
2016/03/17 16:47:14
Done.
|
+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 |
+ |
+void *operator new (size_t size) { |
John
2016/03/15 15:19:06
can you add a comment explaining why this works?
sehr
2016/03/17 16:47:14
Done.
|
+ 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); |
+} |
+#endif // ALLOW_LINUX_MALLOC_PROFILE |
+ |
+namespace Ice { |
+ |
+void LinuxMallocProfiling::start() { |
+#ifdef ALLOW_LINUX_MALLOC_PROFILE |
+ Callers = new MallocMap(); |
+#endif // ALLOW_LINUX_MALLOC_PROFILE |
+} |
+ |
+void LinuxMallocProfiling::end() { |
+#ifdef ALLOW_LINUX_MALLOC_PROFILE |
+ if (Callers == nullptr) { |
+ return; |
+ } |
+ for (auto &C : *Callers) { |
John
2016/03/15 15:19:06
does
const auto &
work?
sehr
2016/03/17 16:47:14
Yes. Done.
|
+ Dl_info dli; |
+ dladdr(C.first, &dli); |
+ |
+ std::cout << C.second << " "; |
+ if (dli.dli_sname == NULL) { |
+ std::cout << C.first; |
+ } else { |
+ std::cout << dli.dli_sname; |
+ } |
+ std::cout << "\n"; |
+ } |
+ delete Callers; |
+ Callers = nullptr; |
+#endif // ALLOW_LINUX_MALLOC_PROFILE |
+} |
+ |
+} // end of namespace Ice |