1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TRACE_EVENT_HEAP_PROFILER_H 6 #define BASE_TRACE_EVENT_HEAP_PROFILER_H 7 8 #include "base/compiler_specific.h" 9 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" 10 11 // This header file defines the set of macros that are used to track memory 12 // usage in the heap profiler. This is in addition to the macros defined in 13 // trace_event.h and are specific to heap profiler. This file also defines 14 // implementation details of these macros. 15 16 // Implementation detail: heap profiler macros create temporary variables to 17 // keep instrumentation overhead low. These macros give each temporary variable 18 // a unique name based on the line number to prevent name collisions. 19 #define INTERNAL_HEAP_PROFILER_UID3(a, b) heap_profiler_unique_##a##b 20 #define INTERNAL_HEAP_PROFILER_UID2(a, b) INTERNAL_HEAP_PROFILER_UID3(a, b) 21 #define INTERNAL_HEAP_PROFILER_UID(name_prefix) \ 22 INTERNAL_HEAP_PROFILER_UID2(name_prefix, __LINE__) 23 24 // Scoped tracker for task execution context in the heap profiler. 25 #define TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION \ 26 trace_event_internal::HeapProfilerScopedTaskExecutionTracker 27 28 // Scoped tracker that tracks the given program counter as a native stack frame 29 // in the heap profiler. 30 #define TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \ 31 trace_event_internal::HeapProfilerScopedStackFrame 32 33 // Returns the current task context (c-string) tracked by heap profiler. This is 34 // useful along with TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION if a async 35 // system needs to track client's allocation context across post tasks. Use this 36 // macro to get the current context and use 37 // TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION in the posted task which 38 // allocates memory for a client. 39 #define TRACE_HEAP_PROFILER_API_GET_CURRENT_TASK_CONTEXT \ 40 trace_event_internal::HeapProfilerCurrentTaskContext 41 42 // A scoped ignore event used to tell heap profiler to ignore all the 43 // allocations in the scope. It is useful to exclude allocations made for 44 // tracing from the heap profiler dumps. 45 #define HEAP_PROFILER_SCOPED_IGNORE \ 46 trace_event_internal::HeapProfilerScopedIgnore INTERNAL_HEAP_PROFILER_UID( \ 47 scoped_ignore) 48 49 namespace trace_event_internal { 50 51 // HeapProfilerScopedTaskExecutionTracker records the current task's context in 52 // the heap profiler. 53 class HeapProfilerScopedTaskExecutionTracker { 54 public: HeapProfilerScopedTaskExecutionTracker(const char * task_context)55 inline explicit HeapProfilerScopedTaskExecutionTracker( 56 const char* task_context) 57 : context_(task_context) { 58 using base::trace_event::AllocationContextTracker; 59 if (UNLIKELY(AllocationContextTracker::capture_mode() != 60 AllocationContextTracker::CaptureMode::DISABLED)) { 61 AllocationContextTracker::GetInstanceForCurrentThread() 62 ->PushCurrentTaskContext(context_); 63 } 64 } 65 ~HeapProfilerScopedTaskExecutionTracker()66 inline ~HeapProfilerScopedTaskExecutionTracker() { 67 using base::trace_event::AllocationContextTracker; 68 if (UNLIKELY(AllocationContextTracker::capture_mode() != 69 AllocationContextTracker::CaptureMode::DISABLED)) { 70 AllocationContextTracker::GetInstanceForCurrentThread() 71 ->PopCurrentTaskContext(context_); 72 } 73 } 74 75 private: 76 const char* context_; 77 }; 78 79 class HeapProfilerScopedStackFrame { 80 public: HeapProfilerScopedStackFrame(const void * program_counter)81 inline explicit HeapProfilerScopedStackFrame(const void* program_counter) 82 : program_counter_(program_counter) { 83 using base::trace_event::AllocationContextTracker; 84 if (UNLIKELY(AllocationContextTracker::capture_mode() == 85 AllocationContextTracker::CaptureMode::MIXED_STACK)) { 86 AllocationContextTracker::GetInstanceForCurrentThread() 87 ->PushNativeStackFrame(program_counter_); 88 } 89 } 90 ~HeapProfilerScopedStackFrame()91 inline ~HeapProfilerScopedStackFrame() { 92 using base::trace_event::AllocationContextTracker; 93 if (UNLIKELY(AllocationContextTracker::capture_mode() == 94 AllocationContextTracker::CaptureMode::MIXED_STACK)) { 95 AllocationContextTracker::GetInstanceForCurrentThread() 96 ->PopNativeStackFrame(program_counter_); 97 } 98 } 99 100 private: 101 const void* const program_counter_; 102 }; 103 HeapProfilerCurrentTaskContext()104inline const char* HeapProfilerCurrentTaskContext() { 105 return base::trace_event::AllocationContextTracker:: 106 GetInstanceForCurrentThread() 107 ->TaskContext(); 108 } 109 110 class BASE_EXPORT HeapProfilerScopedIgnore { 111 public: HeapProfilerScopedIgnore()112 inline HeapProfilerScopedIgnore() { 113 using base::trace_event::AllocationContextTracker; 114 if (UNLIKELY( 115 AllocationContextTracker::capture_mode() != 116 AllocationContextTracker::CaptureMode::DISABLED)) { 117 AllocationContextTracker::GetInstanceForCurrentThread() 118 ->begin_ignore_scope(); 119 } 120 } ~HeapProfilerScopedIgnore()121 inline ~HeapProfilerScopedIgnore() { 122 using base::trace_event::AllocationContextTracker; 123 if (UNLIKELY( 124 AllocationContextTracker::capture_mode() != 125 AllocationContextTracker::CaptureMode::DISABLED)) { 126 AllocationContextTracker::GetInstanceForCurrentThread() 127 ->end_ignore_scope(); 128 } 129 } 130 }; 131 132 } // namespace trace_event_internal 133 134 #endif // BASE_TRACE_EVENT_HEAP_PROFILER_H 135