| 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 #include <cstring> |
| 9 | 9 |
| 10 #include "base/hash.h" | 10 #include "base/hash.h" |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); | 146 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); |
| 147 tracker->pseudo_stack_.push(frame); | 147 tracker->pseudo_stack_.push(frame); |
| 148 } | 148 } |
| 149 | 149 |
| 150 // static | 150 // static |
| 151 void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) { | 151 void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) { |
| 152 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); | 152 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); |
| 153 tracker->pseudo_stack_.pop(frame); | 153 tracker->pseudo_stack_.pop(frame); |
| 154 } | 154 } |
| 155 | 155 |
| 156 // static | |
| 157 void AllocationContextTracker::SetContextField(const char* key, | |
| 158 const char* value) { | |
| 159 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); | |
| 160 tracker->context_[key] = value; | |
| 161 } | |
| 162 | |
| 163 // static | |
| 164 void AllocationContextTracker::UnsetContextField(const char* key) { | |
| 165 auto tracker = AllocationContextTracker::GetThreadLocalTracker(); | |
| 166 tracker->context_.erase(key); | |
| 167 } | |
| 168 | |
| 169 // Returns a pointer past the end of the fixed-size array |array| of |T| of | 156 // Returns a pointer past the end of the fixed-size array |array| of |T| of |
| 170 // length |N|, identical to C++11 |std::end|. | 157 // length |N|, identical to C++11 |std::end|. |
| 171 template <typename T, int N> | 158 template <typename T, int N> |
| 172 T* End(T(&array)[N]) { | 159 T* End(T(&array)[N]) { |
| 173 return array + N; | 160 return array + N; |
| 174 } | 161 } |
| 175 | 162 |
| 176 // static | 163 // static |
| 177 AllocationContext AllocationContextTracker::GetContextSnapshot() { | 164 AllocationContext AllocationContextTracker::GetContextSnapshot() { |
| 178 AllocationContextTracker* tracker = GetThreadLocalTracker(); | 165 AllocationContextTracker* tracker = GetThreadLocalTracker(); |
| 179 AllocationContext ctx; | 166 AllocationContext ctx; |
| 180 | 167 |
| 181 // Fill the backtrace. | 168 // Fill the backtrace. |
| 182 { | 169 { |
| 183 auto src = tracker->pseudo_stack_.bottom(); | 170 auto src = tracker->pseudo_stack_.bottom(); |
| 184 auto dst = ctx.backtrace.frames; | 171 auto dst = ctx.backtrace.frames; |
| 185 auto src_end = tracker->pseudo_stack_.top(); | 172 auto src_end = tracker->pseudo_stack_.top(); |
| 186 auto dst_end = End(ctx.backtrace.frames); | 173 auto dst_end = End(ctx.backtrace.frames); |
| 187 | 174 |
| 188 // Copy as much of the bottom of the pseudo stack into the backtrace as | 175 // Copy as much of the bottom of the pseudo stack into the backtrace as |
| 189 // possible. | 176 // possible. |
| 190 for (; src != src_end && dst != dst_end; src++, dst++) | 177 for (; src != src_end && dst != dst_end; src++, dst++) |
| 191 *dst = *src; | 178 *dst = *src; |
| 192 | 179 |
| 193 // If there is room for more, fill the remaining slots with empty frames. | 180 // If there is room for more, fill the remaining slots with empty frames. |
| 194 std::fill(dst, dst_end, nullptr); | 181 std::fill(dst, dst_end, nullptr); |
| 195 } | 182 } |
| 196 | 183 |
| 197 // Fill the context fields. | |
| 198 { | |
| 199 auto src = tracker->context_.begin(); | |
| 200 auto dst = ctx.fields; | |
| 201 auto src_end = tracker->context_.end(); | |
| 202 auto dst_end = End(ctx.fields); | |
| 203 | |
| 204 // Copy as much (key, value) pairs as possible. | |
| 205 for (; src != src_end && dst != dst_end; src++, dst++) | |
| 206 *dst = *src; | |
| 207 | |
| 208 // If there is room for more, fill the remaining slots with nullptr keys. | |
| 209 for (; dst != dst_end; dst++) | |
| 210 dst->first = nullptr; | |
| 211 } | |
| 212 | |
| 213 return ctx; | 184 return ctx; |
| 214 } | 185 } |
| 215 | 186 |
| 216 } // namespace trace_event | 187 } // namespace trace_event |
| 217 } // namespace base | 188 } // namespace base |
| 218 | 189 |
| 219 namespace BASE_HASH_NAMESPACE { | 190 namespace BASE_HASH_NAMESPACE { |
| 220 using base::trace_event::Backtrace; | 191 using base::trace_event::Backtrace; |
| 221 | 192 |
| 222 size_t hash<Backtrace>::operator()(const Backtrace& backtrace) const { | 193 size_t hash<Backtrace>::operator()(const Backtrace& backtrace) const { |
| 223 return base::SuperFastHash(reinterpret_cast<const char*>(backtrace.frames), | 194 return base::SuperFastHash(reinterpret_cast<const char*>(backtrace.frames), |
| 224 sizeof(backtrace.frames)); | 195 sizeof(backtrace.frames)); |
| 225 } | 196 } |
| 226 | 197 |
| 227 } // BASE_HASH_NAMESPACE | 198 } // BASE_HASH_NAMESPACE |
| OLD | NEW |