Index: third_party/tcmalloc/chromium/src/heap-profiler.cc |
diff --git a/third_party/tcmalloc/chromium/src/heap-profiler.cc b/third_party/tcmalloc/chromium/src/heap-profiler.cc |
index 0b07a5e8662da230e481839dcb5f62b521f9359d..1085303789d7f7e2bea424558aabd24d1d6659e0 100644 |
--- a/third_party/tcmalloc/chromium/src/heap-profiler.cc |
+++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc |
@@ -222,6 +222,9 @@ static int64 last_dump_time = 0; // The time of the last dump |
static HeapProfileTable* heap_profile = NULL; // the heap profile table |
static DeepHeapProfile* deep_profile = NULL; // deep memory profiler |
+// Callback an appplication can use to generate its own "stacks". |
+static PseudoStackGenerator pseudo_stack_generator = NULL; |
+ |
//---------------------------------------------------------------------- |
// Profile generation |
//---------------------------------------------------------------------- |
@@ -374,7 +377,11 @@ static void MaybeDumpProfileLocked() { |
static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) { |
// Take the stack trace outside the critical section. |
void* stack[HeapProfileTable::kMaxStackDepth]; |
- int depth = HeapProfileTable::GetCallerStackTrace(skip_count + 1, stack); |
+ // If using pseudo-stacks then use a callback to get the stack, otherwise |
+ // use normal stack unwinding. |
+ int depth = pseudo_stack_generator ? |
+ (*pseudo_stack_generator)(stack) : |
+ HeapProfileTable::GetCallerStackTrace(skip_count + 1, stack); |
SpinLockHolder l(&heap_lock); |
if (is_on) { |
heap_profile->RecordAlloc(ptr, bytes, depth, stack); |
@@ -542,12 +549,25 @@ extern "C" void HeapProfilerStart(const char* prefix) { |
RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); |
} |
- // Copy filename prefix |
- RAW_DCHECK(filename_prefix == NULL, ""); |
- const int prefix_length = strlen(prefix); |
- filename_prefix = reinterpret_cast<char*>(ProfilerMalloc(prefix_length + 1)); |
- memcpy(filename_prefix, prefix, prefix_length); |
- filename_prefix[prefix_length] = '\0'; |
+ // Copy filename prefix if provided. |
+ if (prefix) { |
+ RAW_DCHECK(filename_prefix == NULL, ""); |
+ const int prefix_length = strlen(prefix); |
+ filename_prefix = |
+ reinterpret_cast<char*>(ProfilerMalloc(prefix_length + 1)); |
+ memcpy(filename_prefix, prefix, prefix_length); |
+ filename_prefix[prefix_length] = '\0'; |
+ } |
+} |
+ |
+extern "C" void HeapProfilerWithPseudoStackStart( |
+ PseudoStackGenerator callback) { |
+ { |
+ // Ensure the callback is set before allocations can be recorded. |
+ SpinLockHolder l(&heap_lock); |
+ pseudo_stack_generator = callback; |
+ } |
+ HeapProfilerStart(NULL); |
} |
extern "C" void IterateAllocatedObjects(AddressVisitor visitor, void* data) { |