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 |