Chromium Code Reviews| 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 47130e8bc5fa8e593a9378a4671a89175ab83884..94eb548f81d49c12b6a8a2e7b7b295952197d340 100644 |
| --- a/third_party/tcmalloc/chromium/src/heap-profiler.cc |
| +++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc |
| @@ -216,6 +216,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 |
| //---------------------------------------------------------------------- |
| @@ -232,7 +235,11 @@ static char* DoGetHeapProfileLocked(char* buf, int buflen) { |
| if (is_on) { |
| HeapProfileTable::Stats const stats = heap_profile->total(); |
| (void)stats; // avoid an unused-variable warning in non-debug mode. |
| - bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); |
| + if (pseudo_stack_generator) { |
| + bytes_written = heap_profile->FillPseudoStackProfile(buf, buflen - 1); |
| + } else { |
| + bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); |
| + } |
| // FillOrderedProfile should not reduce the set of active mmap-ed regions, |
| // hence MemoryRegionMap will let us remove everything we've added above: |
| RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); |
| @@ -376,6 +383,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) { |
|
Dai Mikurube (NOT FULLTIME)
2013/06/19 04:34:03
It's almost the same with RecordAlloc(). Why do w
James Cook
2013/06/29 00:02:42
I elected to copy the function because this is per
|
| + // 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); |
| @@ -399,6 +421,11 @@ void DeleteHook(const void* ptr) { |
| if (ptr != NULL) RecordFree(ptr); |
| } |
| +// static |
| +void PseudoStackNewHook(const void* ptr, size_t size) { |
|
Dai Mikurube (NOT FULLTIME)
2013/06/19 04:34:03
ditto.
|
| + 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*) { |
| @@ -531,16 +558,22 @@ 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), ""); |
| } |
| - // 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)); |
|
Dai Mikurube (NOT FULLTIME)
2013/06/19 04:34:03
Over 80?
|
| + memcpy(filename_prefix, prefix, prefix_length); |
| + filename_prefix[prefix_length] = '\0'; |
| + } |
| } |
| extern "C" void IterateAllocatedObjects(AddressVisitor visitor, void* data) { |
| @@ -563,7 +596,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) { |
| @@ -635,6 +672,11 @@ extern "C" void HeapProfilerDumpAliveObjects(const char* filename) { |
| heap_profile->DumpMarkedObjects(HeapProfileTable::MARK_TWO, filename); |
| } |
| +extern "C" void SetPseudoStackGenerator(PseudoStackGenerator callback) { |
|
Dai Mikurube (NOT FULLTIME)
2013/06/19 04:34:03
The function name should contain HeapProfiler or s
James Cook
2013/06/29 00:02:42
Good idea. Done.
|
| + SpinLockHolder l(&heap_lock); |
| + pseudo_stack_generator = callback; |
| +} |
| + |
| //---------------------------------------------------------------------- |
| // Initialization/finalization code |
| //---------------------------------------------------------------------- |