| 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 85d1aadf7148b80f2a8b8d3c0096cf697dd5f81e..73f31f743f6146a6108b75c2ef0b2f8a821e4e4e 100644
|
| --- a/third_party/tcmalloc/chromium/src/heap-profiler.cc
|
| +++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc
|
| @@ -143,7 +143,7 @@ static SpinLock heap_lock(SpinLock::LINKER_INITIALIZED);
|
| // Simple allocator for heap profiler's internal memory
|
| //----------------------------------------------------------------------
|
|
|
| -static LowLevelAlloc::Arena *heap_profiler_memory;
|
| +static LowLevelAlloc::Arena* heap_profiler_memory;
|
|
|
| static void* ProfilerMalloc(size_t bytes) {
|
| return LowLevelAlloc::AllocWithArena(bytes, heap_profiler_memory);
|
| @@ -152,6 +152,36 @@ static void ProfilerFree(void* p) {
|
| LowLevelAlloc::Free(p);
|
| }
|
|
|
| +//----------------------------------------------------------------------
|
| +// Another allocator for heap profiler's internal mmap address map
|
| +//
|
| +// Large amount of memory is consumed if we use an arena 'heap_profiler_memory'
|
| +// for the internal mmap address map. It looks like memory fragmentation
|
| +// because of repeated allocation/deallocation in the arena.
|
| +//
|
| +// 'mmap_heap_profiler_memory' is a dedicated arena for the mmap address map.
|
| +// This arena is reserved for every construction of the mmap address map, and
|
| +// disposed after every use.
|
| +//----------------------------------------------------------------------
|
| +
|
| +static LowLevelAlloc::Arena* mmap_heap_profiler_memory = NULL;
|
| +
|
| +static void* MMapProfilerMalloc(size_t bytes) {
|
| + return LowLevelAlloc::AllocWithArena(bytes, mmap_heap_profiler_memory);
|
| +}
|
| +static void MMapProfilerFree(void* p) {
|
| + LowLevelAlloc::Free(p);
|
| +}
|
| +
|
| +// This function should be called from a locked scope.
|
| +// It returns false if failed in deleting the arena.
|
| +static bool DeleteMMapProfilerArenaIfExistsLocked() {
|
| + if (mmap_heap_profiler_memory == NULL) return true;
|
| + if (!LowLevelAlloc::DeleteArena(mmap_heap_profiler_memory)) return false;
|
| + mmap_heap_profiler_memory = NULL;
|
| + return true;
|
| +}
|
| +
|
| // We use buffers of this size in DoGetHeapProfile.
|
| // The size is 1 << 20 in the original google-perftools. Changed it to
|
| // 5 << 20 since a larger buffer is requried for deeper profiling in Chromium.
|
| @@ -200,7 +230,12 @@ static char* DoGetHeapProfileLocked(char* buf, int buflen) {
|
| int bytes_written = 0;
|
| if (is_on) {
|
| if (FLAGS_mmap_profile) {
|
| - heap_profile->RefreshMMapData();
|
| + if (!DeleteMMapProfilerArenaIfExistsLocked()) {
|
| + RAW_LOG(FATAL, "Memory leak in HeapProfiler:");
|
| + }
|
| + mmap_heap_profiler_memory =
|
| + LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
|
| + heap_profile->RefreshMMapData(MMapProfilerMalloc, MMapProfilerFree);
|
| }
|
| if (deep_profile) {
|
| bytes_written = deep_profile->FillOrderedProfile(buf, buflen - 1);
|
| @@ -209,6 +244,9 @@ static char* DoGetHeapProfileLocked(char* buf, int buflen) {
|
| }
|
| if (FLAGS_mmap_profile) {
|
| heap_profile->ClearMMapData();
|
| + if (!DeleteMMapProfilerArenaIfExistsLocked()) {
|
| + RAW_LOG(FATAL, "Memory leak in HeapProfiler:");
|
| + }
|
| }
|
| }
|
| buf[bytes_written] = '\0';
|
| @@ -532,6 +570,9 @@ extern "C" void HeapProfilerStop() {
|
|
|
| // free profile
|
| heap_profile->~HeapProfileTable();
|
| + if (!DeleteMMapProfilerArenaIfExistsLocked()) {
|
| + RAW_LOG(FATAL, "Memory leak in HeapProfiler:");
|
| + }
|
| ProfilerFree(heap_profile);
|
| heap_profile = NULL;
|
|
|
| @@ -553,7 +594,7 @@ extern "C" void HeapProfilerStop() {
|
| is_on = false;
|
| }
|
|
|
| -extern "C" void HeapProfilerDump(const char *reason) {
|
| +extern "C" void HeapProfilerDump(const char* reason) {
|
| SpinLockHolder l(&heap_lock);
|
| if (is_on && !dumping) {
|
| DumpProfileLocked(reason);
|
|
|