Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2655)

Unified Diff: base/trace_event/heap_profiler_allocation_context_tracker.cc

Issue 1839503002: [tracing] Add native allocation tracing mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WalkStackFrames (wants frame pointers) Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/trace_event/heap_profiler_allocation_context_tracker.cc
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc
index 2877d2af91b27ace28839ebaac7468322cf4823f..607d500d2dfcbaebaec42a61578a4fd271a593e6 100644
--- a/base/trace_event/heap_profiler_allocation_context_tracker.cc
+++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -7,7 +7,9 @@
#include <algorithm>
#include <iterator>
+#include "base/allocator/features.h"
#include "base/atomicops.h"
+#include "base/debug/stack_trace.h"
#include "base/threading/thread_local_storage.h"
#include "base/trace_event/heap_profiler_allocation_context.h"
@@ -30,6 +32,63 @@ void DestructAllocationContextTracker(void* alloc_ctx_tracker) {
delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker);
}
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATION_TRACING) && !defined(OS_NACL)
+
+// Walks stack frames and collects a trace. Unlike base::debug::StackTrace
+// (which uses unwinding) this function uses frame pointers and is fast.
+// However, by default frame pointers are not enabled in optimized builds
+// unless -fno-omit-frame-pointer flag is specified.
+// Adapted from TCMalloc's stacktrace_x86-inl.h
+size_t WalkStackFrames(const void** trace,
Primiano Tucci (use gerrit) 2016/04/01 15:56:28 would be nice to make this available as a general
Dmitry Skiba 2016/04/04 22:38:34 Yes, I would prefer to make it available through S
+ size_t max_depth,
+ size_t skip_count) {
+ uintptr_t sp = reinterpret_cast<uintptr_t>(
+ __builtin_frame_address(0));
+
+ size_t n = 0;
+ while (sp && n < max_depth) {
+ if (reinterpret_cast<void**>(sp)[1] == nullptr) {
+ // In 64-bit code, we often see a frame that
+ // points to itself and has a return address of 0.
+ break;
+ }
+
+ if (skip_count > 0) {
+ skip_count--;
+ } else {
+ trace[n] = reinterpret_cast<void**>(sp)[1];
+ n++;
+ }
+
+ {
+ uintptr_t next_sp = reinterpret_cast<uintptr_t*>(sp)[0];
+
+ // With the stack growing downwards, older stack frame must be
+ // at a greater address that the current one.
+ if (next_sp <= sp) break;
+
+ // Assume stack frames larger than 100,000 bytes are bogus.
+ if (next_sp - sp > 100000) break;
+
+ // Check alignment.
+ if (next_sp & (sizeof(void*) - 1)) break;
+
+#ifdef __i386__
+ // On 64-bit machines, the stack pointer can be very close to
+ // 0xffffffff, so we explicitly check for a pointer into the
+ // last two pages in the address space
+ if (next_sp >= 0xffffe000) break;
+#endif
+
+ sp = next_sp;
+ }
+ }
+
+ return n;
+}
+
+#endif // USE_EXPERIMENTAL_ALLOCATION_TRACING
+
} // namespace
// static
@@ -64,6 +123,14 @@ void AllocationContextTracker::SetCaptureEnabled(bool enabled) {
// Release ordering ensures that when a thread observes |capture_enabled_| to
// be true through an acquire load, the TLS slot has been initialized.
subtle::Release_Store(&capture_enabled_, enabled);
+
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATION_TRACING) && !defined(OS_NACL)
+ if (enabled) {
+ // Dummy StackTrace usage, just in case stack trace machinery needs to
+ // allocate memory during initialization (e.g. backtrace() does that).
Primiano Tucci (use gerrit) 2016/04/01 15:56:28 where is backtrace() called from?
Dmitry Skiba 2016/04/04 22:38:34 From StackTrace constructor. StackTrace is actuall
+ debug::StackTrace warmup;
+ }
+#endif
}
void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) {
@@ -75,7 +142,6 @@ void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) {
NOTREACHED();
}
-// static
void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) {
// Guard for stack underflow. If tracing was started with a TRACE_EVENT in
// scope, the frame was never pushed, so it is possible that pop is called
@@ -92,11 +158,36 @@ void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) {
pseudo_stack_.pop_back();
}
-// static
AllocationContext AllocationContextTracker::GetContextSnapshot() {
AllocationContext ctx;
- // Fill the backtrace.
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATION_TRACING) && !defined(OS_NACL)
+ // Ignore pseudo stack and return the real thing
+
+ // base::debug::StackTrace::StackTrace()
+ // base::trace_event::AllocationContextTracker::GetContextSnapshot()
+ // base::trace_event::MallocDumpProvider::InsertAllocation(...)
+ // base::trace_event::(anonymous namespace)::HookXXX(...)
+ // ShimXXX
+ const size_t known_frame_count = 5;
+
+ const size_t max_backtrace_count = arraysize(ctx.backtrace.frames);
+ size_t backtrace_count = WalkStackFrames(ctx.backtrace.frames,
+ max_backtrace_count,
+ known_frame_count + 1);
+
+ std::reverse(ctx.backtrace.frames,
Primiano Tucci (use gerrit) 2016/04/01 15:56:28 I wonder if we could avoid this reverse and just w
Dmitry Skiba 2016/04/04 22:38:34 OK
+ ctx.backtrace.frames + backtrace_count);
+
+ std::fill(ctx.backtrace.frames + backtrace_count,
+ ctx.backtrace.frames + max_backtrace_count,
+ nullptr);
+
+ ctx.backtrace.frame_type = STACK_FRAME_TYPE_PC;
+
+#else
+ // Return pseudo stack trace
+
{
auto src = pseudo_stack_.begin();
auto dst = std::begin(ctx.backtrace.frames);
@@ -112,6 +203,10 @@ AllocationContext AllocationContextTracker::GetContextSnapshot() {
std::fill(dst, dst_end, nullptr);
}
+ ctx.backtrace.frame_type = STACK_FRAME_TYPE_SYMBOL;
+
+#endif // USE_EXPERIMENTAL_ALLOCATION_TRACING
+
ctx.type_name = nullptr;
return ctx;

Powered by Google App Engine
This is Rietveld 408576698