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..8a4dbc7d8ca8f22f698ed0de63c4b9a408dd57e1 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); |
petrcermak
2016/03/11 11:09:23
Is this really a safe thing to do? Wouldn't it be
Primiano Tucci (use gerrit)
2016/03/11 13:57:57
It's extremely unlikely that a pointer would end u
|
+ |
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,19 +32,40 @@ void DestructAllocationContextTracker(void* alloc_ctx_tracker) { |
} // namespace |
-AllocationContextTracker::AllocationContextTracker() {} |
+AllocationContextTracker::AllocationContextTracker() { |
+ pseudo_stack_.reserve(kMaxStackDepth); |
+} |
AllocationContextTracker::~AllocationContextTracker() {} |
// static |
-AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { |
+AllocationContextTracker::InitializationState |
+AllocationContextTracker::GetStateForCurrentThread() { |
auto tracker = |
static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); |
+ if (!tracker) |
+ return kNotInitialized; |
+ if (tracker == kInitializingSentinel) |
+ return kInitializing; |
+ return kInitialized; |
+} |
- if (!tracker) { |
- tracker = new AllocationContextTracker(); |
- g_tls_alloc_ctx_tracker.Set(tracker); |
- } |
+// static |
+AllocationContextTracker* |
+AllocationContextTracker::InitializeForCurrentThread() { |
+ DCHECK_EQ(kNotInitialized, GetStateForCurrentThread()); |
+ g_tls_alloc_ctx_tracker.Set(kInitializingSentinel); |
+ AllocationContextTracker* tracker = new AllocationContextTracker(); |
+ g_tls_alloc_ctx_tracker.Set(tracker); |
+ return tracker; |
+} |
+// static |
+AllocationContextTracker* AllocationContextTracker::GetThreadLocalTracker() { |
+ auto tracker = |
+ static_cast<AllocationContextTracker*>(g_tls_alloc_ctx_tracker.Get()); |
+ DCHECK_NE(kInitializingSentinel, tracker); |
+ if (!tracker) |
+ tracker = InitializeForCurrentThread(); |
return tracker; |
} |
@@ -62,8 +87,10 @@ void AllocationContextTracker::PushPseudoStackFrame(StackFrame frame) { |
// 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 (tracker->pseudo_stack_.size() < kMaxStackDepth) |
+ tracker->pseudo_stack_.push_back(frame); |
+ else |
+ NOTREACHED(); |
} |
// static |