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 #include "base/trace_event/heap_profiler_event_filter.h"
6 
7 #include "base/trace_event/category_registry.h"
8 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
9 #include "base/trace_event/trace_category.h"
10 #include "base/trace_event/trace_event.h"
11 #include "base/trace_event/trace_event_impl.h"
12 
13 namespace base {
14 namespace trace_event {
15 
16 namespace {
17 
IsPseudoStackEnabled()18 inline bool IsPseudoStackEnabled() {
19   // Only PSEUDO_STACK and MIXED_STACK modes require trace events.
20   return AllocationContextTracker::capture_mode() ==
21              AllocationContextTracker::CaptureMode::PSEUDO_STACK ||
22          AllocationContextTracker::capture_mode() ==
23              AllocationContextTracker::CaptureMode::MIXED_STACK;
24 }
25 
GetThreadLocalTracker()26 inline AllocationContextTracker* GetThreadLocalTracker() {
27   return AllocationContextTracker::GetInstanceForCurrentThread();
28 }
29 
30 }  // namespace
31 
32 // static
33 const char HeapProfilerEventFilter::kName[] = "heap_profiler_predicate";
34 
35 HeapProfilerEventFilter::HeapProfilerEventFilter() = default;
36 HeapProfilerEventFilter::~HeapProfilerEventFilter() = default;
37 
FilterTraceEvent(const TraceEvent & trace_event) const38 bool HeapProfilerEventFilter::FilterTraceEvent(
39     const TraceEvent& trace_event) const {
40   if (!IsPseudoStackEnabled())
41     return true;
42 
43   // TODO(primiano): Add support for events with copied name crbug.com/581079.
44   if (trace_event.flags() & TRACE_EVENT_FLAG_COPY)
45     return true;
46 
47   const auto* category = CategoryRegistry::GetCategoryByStatePtr(
48       trace_event.category_group_enabled());
49   AllocationContextTracker::PseudoStackFrame frame = {category->name(),
50                                                       trace_event.name()};
51   if (trace_event.phase() == TRACE_EVENT_PHASE_BEGIN ||
52       trace_event.phase() == TRACE_EVENT_PHASE_COMPLETE) {
53     GetThreadLocalTracker()->PushPseudoStackFrame(frame);
54   } else if (trace_event.phase() == TRACE_EVENT_PHASE_END) {
55     // The pop for |TRACE_EVENT_PHASE_COMPLETE| events is in |EndEvent|.
56     GetThreadLocalTracker()->PopPseudoStackFrame(frame);
57   }
58   // Do not filter-out any events and always return true. TraceLog adds the
59   // event only if it is enabled for recording.
60   return true;
61 }
62 
EndEvent(const char * category_name,const char * event_name) const63 void HeapProfilerEventFilter::EndEvent(const char* category_name,
64                                        const char* event_name) const {
65   if (IsPseudoStackEnabled())
66     GetThreadLocalTracker()->PopPseudoStackFrame({category_name, event_name});
67 }
68 
69 }  // namespace trace_event
70 }  // namespace base
71