Chromium Code Reviews| Index: base/trace_event/heap_profiler_allocation_context_tracker.cc |
| diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc |
| index 791ab7a6fe1d46f6dbda2cc3f5bdaa849a5a5b6d..2877d2af91b27ace28839ebaac7468322cf4823f 100644 |
| --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc |
| +++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc |
| @@ -18,6 +18,10 @@ subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0; |
| namespace { |
| +const size_t kMaxStackDepth = 128u; |
| +AllocationContextTracker* const kInitializingSentinel = |
| + reinterpret_cast<AllocationContextTracker*>(-1); |
| + |
| ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; |
| // This function is added to the TLS slot to clean up the instance when the |
| @@ -28,15 +32,16 @@ void DestructAllocationContextTracker(void* alloc_ctx_tracker) { |
| } // namespace |
| -AllocationContextTracker::AllocationContextTracker() {} |
| -AllocationContextTracker::~AllocationContextTracker() {} |
| - |
| // static |
| -AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { |
| - auto tracker = |
| +AllocationContextTracker* |
| +AllocationContextTracker::GetInstanceForCurrentThread() { |
| + AllocationContextTracker* tracker = |
| static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); |
| + if (tracker == kInitializingSentinel) |
| + return nullptr; // Re-entrancy case. |
| if (!tracker) { |
| + g_tls_alloc_ctx_tracker.Set(kInitializingSentinel); |
| tracker = new AllocationContextTracker(); |
| g_tls_alloc_ctx_tracker.Set(tracker); |
| } |
| @@ -44,6 +49,11 @@ AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { |
| return tracker; |
| } |
| +AllocationContextTracker::AllocationContextTracker() { |
| + pseudo_stack_.reserve(kMaxStackDepth); |
| +} |
| +AllocationContextTracker::~AllocationContextTracker() {} |
| + |
| // static |
| void AllocationContextTracker::SetCaptureEnabled(bool enabled) { |
| // When enabling capturing, also initialize the TLS slot. This does not create |
| @@ -56,45 +66,41 @@ void AllocationContextTracker::SetCaptureEnabled(bool enabled) { |
| subtle::Release_Store(&capture_enabled_, enabled); |
| } |
| -// static |
| void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) { |
| - auto tracker = AllocationContextTracker::GetThreadLocalTracker(); |
| - |
| // Impose a limit on the height to verify that every push is popped, because |
| // in practice the pseudo stack never grows higher than ~20 frames. |
| - DCHECK_LT(tracker->pseudo_stack_.size(), 128u); |
| - tracker->pseudo_stack_.push_back(frame); |
| + if (pseudo_stack_.size() < kMaxStackDepth) |
| + pseudo_stack_.push_back(frame); |
| + else |
| + NOTREACHED(); |
| } |
| // static |
|
Dmitry Skiba
2016/03/22 19:23:40
This method (and others below) is not static anymo
|
| void AllocationContextTracker::PopPseudoStackFrame(StackFrame frame) { |
| - auto tracker = AllocationContextTracker::GetThreadLocalTracker(); |
| - |
| // Guard for stack underflow. If tracing was started with a TRACE_EVENT in |
| // scope, the frame was never pushed, so it is possible that pop is called |
| // on an empty stack. |
| - if (tracker->pseudo_stack_.empty()) |
| + if (pseudo_stack_.empty()) |
| return; |
| // Assert that pushes and pops are nested correctly. This DCHECK can be |
| // hit if some TRACE_EVENT macro is unbalanced (a TRACE_EVENT_END* call |
| // without a corresponding TRACE_EVENT_BEGIN). |
| - DCHECK_EQ(frame, tracker->pseudo_stack_.back()) |
| + DCHECK_EQ(frame, pseudo_stack_.back()) |
| << "Encountered an unmatched TRACE_EVENT_END"; |
| - tracker->pseudo_stack_.pop_back(); |
| + pseudo_stack_.pop_back(); |
| } |
| // static |
| AllocationContext AllocationContextTracker::GetContextSnapshot() { |
| - AllocationContextTracker* tracker = GetThreadLocalTracker(); |
| AllocationContext ctx; |
| // Fill the backtrace. |
| { |
| - auto src = tracker->pseudo_stack_.begin(); |
| + auto src = pseudo_stack_.begin(); |
| auto dst = std::begin(ctx.backtrace.frames); |
| - auto src_end = tracker->pseudo_stack_.end(); |
| + auto src_end = pseudo_stack_.end(); |
| auto dst_end = std::end(ctx.backtrace.frames); |
| // Copy as much of the bottom of the pseudo stack into the backtrace as |