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// A scoped ignore event used to tell heap profiler to ignore all the
29// allocations in the scope. It is useful to exclude allocations made for
30// tracing from the heap profiler dumps.
31#define HEAP_PROFILER_SCOPED_IGNORE                                          \
32  trace_event_internal::HeapProfilerScopedIgnore INTERNAL_HEAP_PROFILER_UID( \
33      scoped_ignore)
34
35namespace trace_event_internal {
36
37// HeapProfilerScopedTaskExecutionTracker records the current task's context in
38// the heap profiler.
39class HeapProfilerScopedTaskExecutionTracker {
40 public:
41  inline explicit HeapProfilerScopedTaskExecutionTracker(
42      const char* task_context)
43      : context_(task_context) {
44    using base::trace_event::AllocationContextTracker;
45    if (UNLIKELY(AllocationContextTracker::capture_mode() !=
46                 AllocationContextTracker::CaptureMode::DISABLED)) {
47      AllocationContextTracker::GetInstanceForCurrentThread()
48          ->PushCurrentTaskContext(context_);
49    }
50  }
51
52  inline ~HeapProfilerScopedTaskExecutionTracker() {
53    using base::trace_event::AllocationContextTracker;
54    if (UNLIKELY(AllocationContextTracker::capture_mode() !=
55                 AllocationContextTracker::CaptureMode::DISABLED)) {
56      AllocationContextTracker::GetInstanceForCurrentThread()
57          ->PopCurrentTaskContext(context_);
58    }
59  }
60
61 private:
62  const char* context_;
63};
64
65class BASE_EXPORT HeapProfilerScopedIgnore {
66 public:
67  inline HeapProfilerScopedIgnore() {
68    using base::trace_event::AllocationContextTracker;
69    if (UNLIKELY(
70            AllocationContextTracker::capture_mode() !=
71            AllocationContextTracker::CaptureMode::DISABLED)) {
72      AllocationContextTracker::GetInstanceForCurrentThread()
73          ->begin_ignore_scope();
74    }
75  }
76  inline ~HeapProfilerScopedIgnore() {
77    using base::trace_event::AllocationContextTracker;
78    if (UNLIKELY(
79            AllocationContextTracker::capture_mode() !=
80            AllocationContextTracker::CaptureMode::DISABLED)) {
81      AllocationContextTracker::GetInstanceForCurrentThread()
82          ->end_ignore_scope();
83    }
84  }
85};
86
87}  // namespace trace_event_internal
88
89#endif  // BASE_TRACE_EVENT_HEAP_PROFILER_H
90