Index: third_party/tcmalloc/chromium/src/heap-profile-table.h |
diff --git a/third_party/tcmalloc/chromium/src/heap-profile-table.h b/third_party/tcmalloc/chromium/src/heap-profile-table.h |
index 61493fc3013cabd73f3b4ca94838e2ffe828fb07..34697a0392b6a424a2d003be3882287dd07af7e0 100644 |
--- a/third_party/tcmalloc/chromium/src/heap-profile-table.h |
+++ b/third_party/tcmalloc/chromium/src/heap-profile-table.h |
@@ -71,6 +71,15 @@ class HeapProfileTable { |
} |
}; |
+ // Possible marks for MarkCurrentAllocations and MarkUnmarkedAllocations. New |
+ // allocations are marked with UNMARKED by default. |
+ enum AllocationMark { |
+ UNMARKED = 0, |
+ MARK_ONE, |
+ MARK_TWO, |
+ MARK_THREE |
+ }; |
+ |
// Info we can return about an allocation. |
struct AllocInfo { |
size_t object_size; // size of the allocation |
@@ -138,6 +147,13 @@ class HeapProfileTable { |
// are skipped in heap checking reports. |
void MarkAsIgnored(const void* ptr); |
+ // Mark all currently known allocations with the given AllocationMark. |
+ void MarkCurrentAllocations(AllocationMark mark); |
+ |
+ // Mark all unmarked (i.e. marked with AllocationMark::UNMARKED) with the |
+ // given mark. |
+ void MarkUnmarkedAllocations(AllocationMark mark); |
+ |
// Return current total (de)allocation statistics. It doesn't contain |
// mmap'ed regions. |
const Stats& total() const { return total_; } |
@@ -203,6 +219,25 @@ class HeapProfileTable { |
// calling ClearMMapData. |
void ClearMMapData(); |
+ // Dump a list of allocations marked as "live" along with their creation |
+ // stack traces and sizes to a file named |file_name|. Together with |
+ // MarkCurrentAllocatiosn and MarkUnmarkedAllocations this can be used |
+ // to find objects that are created in a certain time span: |
+ // 1. Invoke MarkCurrentAllocations(MARK_ONE) to mark the start of the |
+ // timespan. |
+ // 2. Perform whatever action you suspect allocates memory that is not |
+ // correctly freed. |
+ // 3. Invoke MarkUnmarkedAllocations(MARK_TWO). |
+ // 4. Perform whatever action is supposed to free the memory again. New |
+ // allocations are not marked. So all allocations that are marked as |
+ // "live" where created during step 2. |
+ // 5. Invoke DumpMarkedObjects(MARK_TWO) to get the list of allocations that |
+ // were created during step 2, but survived step 4. |
+ // |
+ // Note that this functionality cannot be used if the HeapProfileTable is |
+ // used for leak checking (using HeapLeakChecker). |
+ void DumpMarkedObjects(AllocationMark mark, const char* file_name); |
+ |
private: |
friend class DeepHeapProfile; |
@@ -238,6 +273,12 @@ class HeapProfileTable { |
void set_ignore(bool r) { |
bucket_rep = (bucket_rep & ~uintptr_t(kIgnore)) | (r ? kIgnore : 0); |
} |
+ AllocationMark mark() const { |
+ return static_cast<AllocationMark>(bucket_rep & uintptr_t(kMask)); |
+ } |
+ void set_mark(AllocationMark mark) { |
+ bucket_rep = (bucket_rep & ~uintptr_t(kMask)) | uintptr_t(mark); |
+ } |
private: |
// We store a few bits in the bottom bits of bucket_rep. |
@@ -263,6 +304,23 @@ class HeapProfileTable { |
: fd(a), profile_stats(d) { } |
}; |
+ // Arguments that need to be passed DumpMarkedIterator callback below. |
+ struct DumpMarkedArgs { |
+ RawFD fd; // file to write to. |
+ AllocationMark mark; // The mark of the allocations to process. |
+ |
+ DumpMarkedArgs(RawFD a, AllocationMark m) : fd(a), mark(m) { } |
+ }; |
+ |
+ // Arguments that need to be passed MarkIterator callback below. |
+ struct MarkArgs { |
+ AllocationMark mark; // The mark to put on allocations. |
+ bool mark_all; // True if all allocations should be marked. Otherwise just |
+ // mark unmarked allocations. |
+ |
+ MarkArgs(AllocationMark m, bool a) : mark(m), mark_all(a) { } |
+ }; |
+ |
// helpers ---------------------------- |
// Unparse bucket b and print its portion of profile dump into buf. |
@@ -307,11 +365,20 @@ class HeapProfileTable { |
callback(ptr, info); |
} |
+ // Helper for MarkCurrentAllocations and MarkUnmarkedAllocations. |
+ inline static void MarkIterator(const void* ptr, AllocValue* v, |
+ const MarkArgs& args); |
+ |
// Helper for DumpNonLiveProfile to do object-granularity |
// heap profile dumping. It gets passed to AllocationMap::Iterate. |
inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v, |
const DumpArgs& args); |
+ // Helper for DumpMarkedObjects to dump all allocations with a given mark. It |
+ // gets passed to AllocationMap::Iterate. |
+ inline static void DumpMarkedIterator(const void* ptr, AllocValue* v, |
+ const DumpMarkedArgs& args); |
+ |
// Helper for filling size variables in buckets by zero. |
inline static void ZeroBucketCountsIterator( |
const void* ptr, AllocValue* v, HeapProfileTable* heap_profile); |