| 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 e08b0fcc7cbd233d0b3b73dba2dc7df519f86d16..461b81376260f9af3ea4c44587fc866b09381b1a 100644
|
| --- a/third_party/tcmalloc/chromium/src/heap-profiler.cc
|
| +++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc
|
| @@ -220,6 +220,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
|
| //----------------------------------------------------------------------
|
| @@ -238,6 +241,8 @@ static char* DoGetHeapProfileLocked(const char* reason, char* buf, int buflen) {
|
| (void)stats; // avoid an unused-variable warning in non-debug mode.
|
| if (deep_profile) {
|
| bytes_written = deep_profile->FillOrderedProfile(reason, buf, buflen - 1);
|
| + } else if (pseudo_stack_generator) {
|
| + bytes_written = heap_profile->FillPseudoStackProfile(buf, buflen - 1);
|
| } else {
|
| bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1);
|
| }
|
| @@ -379,6 +384,21 @@ static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) {
|
| }
|
| }
|
|
|
| +// Record an allocation in the profile.
|
| +static void PseudoStackRecordAlloc(const void* ptr,
|
| + size_t bytes,
|
| + int skip_count) {
|
| + // Take the stack trace outside the critical section.
|
| + void* stack[HeapProfileTable::kMaxStackDepth];
|
| + // Generate our pseudo-stack by via callback into the client code.
|
| + int depth = (*pseudo_stack_generator)(stack);
|
| + SpinLockHolder l(&heap_lock);
|
| + if (is_on) {
|
| + heap_profile->RecordAlloc(ptr, bytes, depth, stack);
|
| + MaybeDumpProfileLocked();
|
| + }
|
| +}
|
| +
|
| // Record a deallocation in the profile.
|
| static void RecordFree(const void* ptr) {
|
| SpinLockHolder l(&heap_lock);
|
| @@ -402,6 +422,11 @@ void DeleteHook(const void* ptr) {
|
| if (ptr != NULL) RecordFree(ptr);
|
| }
|
|
|
| +// static
|
| +void PseudoStackNewHook(const void* ptr, size_t size) {
|
| + if (ptr != NULL) PseudoStackRecordAlloc(ptr, size, 0);
|
| +}
|
| +
|
| // TODO(jandrews): Re-enable stack tracing
|
| #ifdef TODO_REENABLE_STACK_TRACING
|
| static void RawInfoStackDumper(const char* message, void*) {
|
| @@ -534,7 +559,11 @@ extern "C" void HeapProfilerStart(const char* prefix) {
|
|
|
| if (FLAGS_only_mmap_profile == false) {
|
| // Now set the hooks that capture new/delete and malloc/free.
|
| - RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
|
| + if (pseudo_stack_generator) {
|
| + RAW_CHECK(MallocHook::AddNewHook(&PseudoStackNewHook), "");
|
| + } else {
|
| + RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
|
| + }
|
| RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), "");
|
| }
|
|
|
| @@ -566,7 +595,11 @@ extern "C" void HeapProfilerStop() {
|
|
|
| if (FLAGS_only_mmap_profile == false) {
|
| // Unset our new/delete hooks, checking they were set:
|
| - RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), "");
|
| + if (pseudo_stack_generator) {
|
| + RAW_CHECK(MallocHook::RemoveNewHook(&PseudoStackNewHook), "");
|
| + } else {
|
| + RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), "");
|
| + }
|
| RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), "");
|
| }
|
| if (FLAGS_mmap_log) {
|
| @@ -638,6 +671,11 @@ extern "C" void HeapProfilerDumpAliveObjects(const char* filename) {
|
| heap_profile->DumpMarkedObjects(HeapProfileTable::MARK_TWO, filename);
|
| }
|
|
|
| +extern "C" void SetPseudoStackGenerator(PseudoStackGenerator callback) {
|
| + SpinLockHolder l(&heap_lock);
|
| + pseudo_stack_generator = callback;
|
| +}
|
| +
|
| //----------------------------------------------------------------------
|
| // Initialization/finalization code
|
| //----------------------------------------------------------------------
|
|
|