| 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/heap_profiler_allocation_context_tracker.h" | 5 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 | 22 |
| 23 subtle::Atomic32 AllocationContextTracker::capture_mode_ = | 23 subtle::Atomic32 AllocationContextTracker::capture_mode_ = |
| 24 static_cast<int32_t>(AllocationContextTracker::CaptureMode::DISABLED); | 24 static_cast<int32_t>(AllocationContextTracker::CaptureMode::DISABLED); |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 const size_t kMaxStackDepth = 128u; | 28 const size_t kMaxStackDepth = 128u; |
| 29 const size_t kMaxTaskDepth = 16u; | 29 const size_t kMaxTaskDepth = 16u; |
| 30 AllocationContextTracker* const kInitializingSentinel = | 30 AllocationContextTracker* const kInitializingSentinel = |
| 31 reinterpret_cast<AllocationContextTracker*>(-1); | 31 reinterpret_cast<AllocationContextTracker*>(-1); |
| 32 const char kTracingOverhead[] = "tracing_overhead"; | |
| 33 | 32 |
| 34 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; | 33 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; |
| 35 | 34 |
| 36 // This function is added to the TLS slot to clean up the instance when the | 35 // This function is added to the TLS slot to clean up the instance when the |
| 37 // thread exits. | 36 // thread exits. |
| 38 void DestructAllocationContextTracker(void* alloc_ctx_tracker) { | 37 void DestructAllocationContextTracker(void* alloc_ctx_tracker) { |
| 39 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); | 38 delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); |
| 40 } | 39 } |
| 41 | 40 |
| 42 // Cannot call ThreadIdNameManager::GetName because it holds a lock and causes | 41 // Cannot call ThreadIdNameManager::GetName because it holds a lock and causes |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // on an empty stack. | 149 // on an empty stack. |
| 151 if (task_contexts_.empty()) | 150 if (task_contexts_.empty()) |
| 152 return; | 151 return; |
| 153 | 152 |
| 154 DCHECK_EQ(context, task_contexts_.back()) | 153 DCHECK_EQ(context, task_contexts_.back()) |
| 155 << "Encountered an unmatched context end"; | 154 << "Encountered an unmatched context end"; |
| 156 task_contexts_.pop_back(); | 155 task_contexts_.pop_back(); |
| 157 } | 156 } |
| 158 | 157 |
| 159 // static | 158 // static |
| 160 AllocationContext AllocationContextTracker::GetContextSnapshot() { | 159 bool AllocationContextTracker::GetContextSnapshot(AllocationContext* ctx) { |
| 161 AllocationContext ctx; | 160 if (ignore_scope_depth_) |
| 162 | 161 return false; |
| 163 if (ignore_scope_depth_) { | |
| 164 ctx.backtrace.frames[0] = StackFrame::FromTraceEventName(kTracingOverhead); | |
| 165 ctx.type_name = kTracingOverhead; | |
| 166 ctx.backtrace.frame_count = 1; | |
| 167 return ctx; | |
| 168 } | |
| 169 | 162 |
| 170 CaptureMode mode = static_cast<CaptureMode>( | 163 CaptureMode mode = static_cast<CaptureMode>( |
| 171 subtle::NoBarrier_Load(&capture_mode_)); | 164 subtle::NoBarrier_Load(&capture_mode_)); |
| 172 | 165 |
| 173 auto* backtrace = std::begin(ctx.backtrace.frames); | 166 auto* backtrace = std::begin(ctx->backtrace.frames); |
| 174 auto* backtrace_end = std::end(ctx.backtrace.frames); | 167 auto* backtrace_end = std::end(ctx->backtrace.frames); |
| 175 | 168 |
| 176 if (!thread_name_) { | 169 if (!thread_name_) { |
| 177 // Ignore the string allocation made by GetAndLeakThreadName to avoid | 170 // Ignore the string allocation made by GetAndLeakThreadName to avoid |
| 178 // reentrancy. | 171 // reentrancy. |
| 179 ignore_scope_depth_++; | 172 ignore_scope_depth_++; |
| 180 thread_name_ = GetAndLeakThreadName(); | 173 thread_name_ = GetAndLeakThreadName(); |
| 181 ANNOTATE_LEAKING_OBJECT_PTR(thread_name_); | 174 ANNOTATE_LEAKING_OBJECT_PTR(thread_name_); |
| 182 DCHECK(thread_name_); | 175 DCHECK(thread_name_); |
| 183 ignore_scope_depth_--; | 176 ignore_scope_depth_--; |
| 184 } | 177 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 0 : | 222 0 : |
| 230 frame_count - backtrace_capacity; | 223 frame_count - backtrace_capacity; |
| 231 for (size_t i = frame_count; i > top_frame_index;) { | 224 for (size_t i = frame_count; i > top_frame_index;) { |
| 232 const void* frame = frames[--i]; | 225 const void* frame = frames[--i]; |
| 233 *backtrace++ = StackFrame::FromProgramCounter(frame); | 226 *backtrace++ = StackFrame::FromProgramCounter(frame); |
| 234 } | 227 } |
| 235 break; | 228 break; |
| 236 } | 229 } |
| 237 } | 230 } |
| 238 | 231 |
| 239 ctx.backtrace.frame_count = backtrace - std::begin(ctx.backtrace.frames); | 232 ctx->backtrace.frame_count = backtrace - std::begin(ctx->backtrace.frames); |
| 240 | 233 |
| 241 // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension | 234 // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension |
| 242 // (component name) in the heap profiler and not piggy back on the type name. | 235 // (component name) in the heap profiler and not piggy back on the type name. |
| 243 if (!task_contexts_.empty()) { | 236 if (!task_contexts_.empty()) { |
| 244 ctx.type_name = task_contexts_.back(); | 237 ctx->type_name = task_contexts_.back(); |
| 245 } else if (!pseudo_stack_.empty()) { | 238 } else if (!pseudo_stack_.empty()) { |
| 246 // If task context was unavailable, then the category names are taken from | 239 // If task context was unavailable, then the category names are taken from |
| 247 // trace events. | 240 // trace events. |
| 248 ctx.type_name = pseudo_stack_.back().trace_event_category; | 241 ctx->type_name = pseudo_stack_.back().trace_event_category; |
| 242 } else { |
| 243 ctx->type_name = nullptr; |
| 249 } | 244 } |
| 250 | 245 |
| 251 return ctx; | 246 return true; |
| 252 } | 247 } |
| 253 | 248 |
| 254 } // namespace trace_event | 249 } // namespace trace_event |
| 255 } // namespace base | 250 } // namespace base |
| OLD | NEW |