Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/trace_event/memory_profiler_allocation_context.h" | 5 #include "base/trace_event/memory_profiler_allocation_context.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | |
| 8 | 9 |
| 10 #include "base/hash.h" | |
| 9 #include "base/threading/thread_local_storage.h" | 11 #include "base/threading/thread_local_storage.h" |
| 10 | 12 |
| 11 namespace base { | 13 namespace base { |
| 12 namespace trace_event { | 14 namespace trace_event { |
| 13 | 15 |
| 14 subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0; | 16 subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0; |
| 15 | 17 |
| 16 namespace { | 18 namespace { |
| 17 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; | 19 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; |
| 18 } | 20 } |
| 19 | 21 |
| 20 AllocationStack::AllocationStack() {} | 22 AllocationStack::AllocationStack() {} |
| 21 AllocationStack::~AllocationStack() {} | 23 AllocationStack::~AllocationStack() {} |
| 22 | 24 |
| 23 // This function is added to the TLS slot to clean up the instance when the | 25 bool operator==(const Backtrace& lhs, const Backtrace& rhs) { |
| 24 // thread exits. | 26 // Pointer equality of the stack frames is assumed, so instead of doing a deep |
| 25 void DestructAllocationContextTracker(void* alloc_ctx_tracker) { | 27 // string comparison on all of the frames, a |memcmp| suffices. |
| 26 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); | 28 return std::memcmp(lhs.frames, rhs.frames, sizeof(lhs.frames)) == 0; |
| 27 } | 29 } |
| 28 | 30 |
| 29 AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { | 31 uint32_t BacktraceHash::operator()(const Backtrace& backtrace) const { |
| 30 auto tracker = | 32 return SuperFastHash(reinterpret_cast<const char*>(backtrace.frames), |
|
Primiano Tucci (use gerrit)
2015/10/26 11:52:06
be really careful with SuperFastHash. I got bitten
Ruud van Asseldonk
2015/10/26 14:51:26
I saw that discussion. Insertion in the hash table
Primiano Tucci (use gerrit)
2015/10/26 20:57:57
Ok, didn't realize that after all, if you end up h
| |
| 31 static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); | 33 sizeof(backtrace.frames)); |
| 32 | |
| 33 if (!tracker) { | |
| 34 tracker = new AllocationContextTracker(); | |
| 35 g_tls_alloc_ctx_tracker.Set(tracker); | |
| 36 } | |
| 37 | |
| 38 return tracker; | |
| 39 } | 34 } |
| 40 | 35 |
| 41 StackFrameDeduplicator::FrameNode::FrameNode(StackFrame frame, | 36 StackFrameDeduplicator::FrameNode::FrameNode(StackFrame frame, |
| 42 int parent_frame_index) | 37 int parent_frame_index) |
| 43 : frame(frame), parent_frame_index(parent_frame_index) {} | 38 : frame(frame), parent_frame_index(parent_frame_index) {} |
| 44 StackFrameDeduplicator::FrameNode::~FrameNode() {} | 39 StackFrameDeduplicator::FrameNode::~FrameNode() {} |
| 45 | 40 |
| 46 StackFrameDeduplicator::StackFrameDeduplicator() {} | 41 StackFrameDeduplicator::StackFrameDeduplicator() {} |
| 47 StackFrameDeduplicator::~StackFrameDeduplicator() {} | 42 StackFrameDeduplicator::~StackFrameDeduplicator() {} |
| 48 | 43 |
| 49 int StackFrameDeduplicator::Insert(const AllocationContext::Backtrace& bt) { | 44 int StackFrameDeduplicator::Insert(const Backtrace& bt) { |
| 50 int frame_index = -1; | 45 int frame_index = -1; |
| 51 std::map<StackFrame, int>* nodes = &roots_; | 46 std::map<StackFrame, int>* nodes = &roots_; |
| 52 | 47 |
| 53 for (size_t i = 0; i < arraysize(bt.frames); i++) { | 48 for (size_t i = 0; i < arraysize(bt.frames); i++) { |
| 54 if (!bt.frames[i]) | 49 if (!bt.frames[i]) |
| 55 break; | 50 break; |
| 56 | 51 |
| 57 auto node = nodes->find(bt.frames[i]); | 52 auto node = nodes->find(bt.frames[i]); |
| 58 if (node == nodes->end()) { | 53 if (node == nodes->end()) { |
| 59 // There is no tree node for this frame yet, create it. The parent node | 54 // There is no tree node for this frame yet, create it. The parent node |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 74 // A tree node for this frame exists. Look for the next one. | 69 // A tree node for this frame exists. Look for the next one. |
| 75 frame_index = node->second; | 70 frame_index = node->second; |
| 76 } | 71 } |
| 77 | 72 |
| 78 nodes = &frames_[frame_index].children; | 73 nodes = &frames_[frame_index].children; |
| 79 } | 74 } |
| 80 | 75 |
| 81 return frame_index; | 76 return frame_index; |
| 82 } | 77 } |
| 83 | 78 |
| 79 // This function is added to the TLS slot to clean up the instance when the | |
| 80 // thread exits. | |
| 81 void DestructAllocationContextTracker(void* alloc_ctx_tracker) { | |
| 82 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); | |
| 83 } | |
| 84 | |
| 85 AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { | |
| 86 auto tracker = | |
| 87 static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); | |
| 88 | |
| 89 if (!tracker) { | |
| 90 tracker = new AllocationContextTracker(); | |
| 91 g_tls_alloc_ctx_tracker.Set(tracker); | |
| 92 } | |
| 93 | |
| 94 return tracker; | |
| 95 } | |
| 96 | |
| 84 AllocationContextTracker::AllocationContextTracker() {} | 97 AllocationContextTracker::AllocationContextTracker() {} |
| 85 AllocationContextTracker::~AllocationContextTracker() {} | 98 AllocationContextTracker::~AllocationContextTracker() {} |
| 86 | 99 |
| 87 // static | 100 // static |
| 88 void AllocationContextTracker::SetCaptureEnabled(bool enabled) { | 101 void AllocationContextTracker::SetCaptureEnabled(bool enabled) { |
| 89 // When enabling capturing, also initialize the TLS slot. This does not create | 102 // When enabling capturing, also initialize the TLS slot. This does not create |
| 90 // a TLS instance yet. | 103 // a TLS instance yet. |
| 91 if (enabled && !g_tls_alloc_ctx_tracker.initialized()) | 104 if (enabled && !g_tls_alloc_ctx_tracker.initialized()) |
| 92 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker); | 105 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker); |
| 93 | 106 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 // If there is room for more, fill the remaining slots with nullptr keys. | 179 // If there is room for more, fill the remaining slots with nullptr keys. |
| 167 for (; dst != dst_end; dst++) | 180 for (; dst != dst_end; dst++) |
| 168 dst->first = nullptr; | 181 dst->first = nullptr; |
| 169 } | 182 } |
| 170 | 183 |
| 171 return ctx; | 184 return ctx; |
| 172 } | 185 } |
| 173 | 186 |
| 174 } // namespace trace_event | 187 } // namespace trace_event |
| 175 } // namespace base | 188 } // namespace base |
| OLD | NEW |