xref: /aosp_15_r20/external/cronet/base/profiler/stack_sampler.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_sampler.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <iterator>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/profiler/metadata_recorder.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/profiler/profile_builder.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/profiler/sample_metadata.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_buffer.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_copier.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/profiler/suspendable_thread_delegate.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/profiler/unwinder.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker // IMPORTANT NOTE: Some functions within this implementation are invoked while
26*6777b538SAndroid Build Coastguard Worker // the target thread is suspended so it must not do any allocation from the
27*6777b538SAndroid Build Coastguard Worker // heap, including indirectly via use of DCHECK/CHECK or other logging
28*6777b538SAndroid Build Coastguard Worker // statements. Otherwise this code can deadlock on heap locks acquired by the
29*6777b538SAndroid Build Coastguard Worker // target thread before it was suspended. These functions are commented with "NO
30*6777b538SAndroid Build Coastguard Worker // HEAP ALLOCATIONS".
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker namespace base {
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker namespace {
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker // Notifies the unwinders about the stack capture, and records metadata, while
37*6777b538SAndroid Build Coastguard Worker // the thread is suspended.
38*6777b538SAndroid Build Coastguard Worker class StackCopierDelegate : public StackCopier::Delegate {
39*6777b538SAndroid Build Coastguard Worker  public:
StackCopierDelegate(const base::circular_deque<std::unique_ptr<Unwinder>> * unwinders,ProfileBuilder * profile_builder,MetadataRecorder::MetadataProvider * metadata_provider)40*6777b538SAndroid Build Coastguard Worker   StackCopierDelegate(
41*6777b538SAndroid Build Coastguard Worker       const base::circular_deque<std::unique_ptr<Unwinder>>* unwinders,
42*6777b538SAndroid Build Coastguard Worker       ProfileBuilder* profile_builder,
43*6777b538SAndroid Build Coastguard Worker       MetadataRecorder::MetadataProvider* metadata_provider)
44*6777b538SAndroid Build Coastguard Worker       : unwinders_(unwinders),
45*6777b538SAndroid Build Coastguard Worker         profile_builder_(profile_builder),
46*6777b538SAndroid Build Coastguard Worker         metadata_provider_(metadata_provider) {}
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   StackCopierDelegate(const StackCopierDelegate&) = delete;
49*6777b538SAndroid Build Coastguard Worker   StackCopierDelegate& operator=(const StackCopierDelegate&) = delete;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   // StackCopier::Delegate:
52*6777b538SAndroid Build Coastguard Worker   // IMPORTANT NOTE: to avoid deadlock this function must not invoke any
53*6777b538SAndroid Build Coastguard Worker   // non-reentrant code that is also invoked by the target thread. In
54*6777b538SAndroid Build Coastguard Worker   // particular, it may not perform any heap allocation or deallocation,
55*6777b538SAndroid Build Coastguard Worker   // including indirectly via use of DCHECK/CHECK or other logging statements.
OnStackCopy()56*6777b538SAndroid Build Coastguard Worker   void OnStackCopy() override {
57*6777b538SAndroid Build Coastguard Worker     for (const auto& unwinder : *unwinders_)
58*6777b538SAndroid Build Coastguard Worker       unwinder->OnStackCapture();
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker     profile_builder_->RecordMetadata(*metadata_provider_);
61*6777b538SAndroid Build Coastguard Worker   }
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker  private:
64*6777b538SAndroid Build Coastguard Worker   raw_ptr<const base::circular_deque<std::unique_ptr<Unwinder>>> unwinders_;
65*6777b538SAndroid Build Coastguard Worker   const raw_ptr<ProfileBuilder> profile_builder_;
66*6777b538SAndroid Build Coastguard Worker   const raw_ptr<const MetadataRecorder::MetadataProvider> metadata_provider_;
67*6777b538SAndroid Build Coastguard Worker };
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker }  // namespace
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker StackSampler::~StackSampler() = default;
72*6777b538SAndroid Build Coastguard Worker 
CreateStackBuffer()73*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> StackSampler::CreateStackBuffer() {
74*6777b538SAndroid Build Coastguard Worker   size_t size = GetStackBufferSize();
75*6777b538SAndroid Build Coastguard Worker   if (size == 0)
76*6777b538SAndroid Build Coastguard Worker     return nullptr;
77*6777b538SAndroid Build Coastguard Worker   return std::make_unique<StackBuffer>(size);
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
Initialize()80*6777b538SAndroid Build Coastguard Worker void StackSampler::Initialize() {
81*6777b538SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Unwinder>> unwinders =
82*6777b538SAndroid Build Coastguard Worker       std::move(unwinders_factory_).Run();
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   // |unwinders| is iterated backward since |unwinders_factory_| generates
85*6777b538SAndroid Build Coastguard Worker   // unwinders in increasing priority order. |unwinders_| is stored in
86*6777b538SAndroid Build Coastguard Worker   // decreasing priority order for ease of use within the class.
87*6777b538SAndroid Build Coastguard Worker   unwinders_.insert(unwinders_.end(),
88*6777b538SAndroid Build Coastguard Worker                     std::make_move_iterator(unwinders.rbegin()),
89*6777b538SAndroid Build Coastguard Worker                     std::make_move_iterator(unwinders.rend()));
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   for (const auto& unwinder : unwinders_)
92*6777b538SAndroid Build Coastguard Worker     unwinder->Initialize(module_cache_);
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker   was_initialized_ = true;
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker 
AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder)97*6777b538SAndroid Build Coastguard Worker void StackSampler::AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder) {
98*6777b538SAndroid Build Coastguard Worker   // Initialize() invokes Initialize() on the unwinders that are present
99*6777b538SAndroid Build Coastguard Worker   // at the time. If it hasn't occurred yet, we allow it to add the initial
100*6777b538SAndroid Build Coastguard Worker   // modules, otherwise we do it here.
101*6777b538SAndroid Build Coastguard Worker   if (was_initialized_)
102*6777b538SAndroid Build Coastguard Worker     unwinder->Initialize(module_cache_);
103*6777b538SAndroid Build Coastguard Worker   unwinders_.push_front(std::move(unwinder));
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker 
RecordStackFrames(StackBuffer * stack_buffer,ProfileBuilder * profile_builder,PlatformThreadId thread_id)106*6777b538SAndroid Build Coastguard Worker void StackSampler::RecordStackFrames(StackBuffer* stack_buffer,
107*6777b538SAndroid Build Coastguard Worker                                      ProfileBuilder* profile_builder,
108*6777b538SAndroid Build Coastguard Worker                                      PlatformThreadId thread_id) {
109*6777b538SAndroid Build Coastguard Worker   DCHECK(stack_buffer);
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   if (record_sample_callback_)
112*6777b538SAndroid Build Coastguard Worker     record_sample_callback_.Run();
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker   RegisterContext thread_context;
115*6777b538SAndroid Build Coastguard Worker   uintptr_t stack_top;
116*6777b538SAndroid Build Coastguard Worker   TimeTicks timestamp;
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   bool copy_stack_succeeded;
119*6777b538SAndroid Build Coastguard Worker   {
120*6777b538SAndroid Build Coastguard Worker     // Make this scope as small as possible because |metadata_provider| is
121*6777b538SAndroid Build Coastguard Worker     // holding a lock.
122*6777b538SAndroid Build Coastguard Worker     MetadataRecorder::MetadataProvider metadata_provider(
123*6777b538SAndroid Build Coastguard Worker         GetSampleMetadataRecorder(), thread_id);
124*6777b538SAndroid Build Coastguard Worker     StackCopierDelegate delegate(&unwinders_, profile_builder,
125*6777b538SAndroid Build Coastguard Worker                                  &metadata_provider);
126*6777b538SAndroid Build Coastguard Worker     copy_stack_succeeded = stack_copier_->CopyStack(
127*6777b538SAndroid Build Coastguard Worker         stack_buffer, &stack_top, &timestamp, &thread_context, &delegate);
128*6777b538SAndroid Build Coastguard Worker   }
129*6777b538SAndroid Build Coastguard Worker   if (!copy_stack_succeeded) {
130*6777b538SAndroid Build Coastguard Worker     profile_builder->OnSampleCompleted(
131*6777b538SAndroid Build Coastguard Worker         {}, timestamp.is_null() ? TimeTicks::Now() : timestamp);
132*6777b538SAndroid Build Coastguard Worker     return;
133*6777b538SAndroid Build Coastguard Worker   }
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   for (const auto& unwinder : unwinders_)
136*6777b538SAndroid Build Coastguard Worker     unwinder->UpdateModules();
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker   if (test_delegate_)
139*6777b538SAndroid Build Coastguard Worker     test_delegate_->OnPreStackWalk();
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   profile_builder->OnSampleCompleted(
142*6777b538SAndroid Build Coastguard Worker       WalkStack(module_cache_, &thread_context, stack_top, unwinders_),
143*6777b538SAndroid Build Coastguard Worker       timestamp);
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
146*6777b538SAndroid Build Coastguard Worker   ptrdiff_t stack_size = reinterpret_cast<uint8_t*>(stack_top) -
147*6777b538SAndroid Build Coastguard Worker                          reinterpret_cast<uint8_t*>(stack_buffer->buffer());
148*6777b538SAndroid Build Coastguard Worker   constexpr int kBytesPerKilobyte = 1024;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   if ((++stack_size_histogram_sampling_counter_ %
151*6777b538SAndroid Build Coastguard Worker        kUMAHistogramDownsampleAmount) == 0) {
152*6777b538SAndroid Build Coastguard Worker     // Record the size of the stack to tune kLargeStackSize.
153*6777b538SAndroid Build Coastguard Worker     // UmaHistogramMemoryKB has a min of 1000, which isn't useful for our
154*6777b538SAndroid Build Coastguard Worker     // purposes, so call UmaHistogramCustomCounts directly.
155*6777b538SAndroid Build Coastguard Worker     // Min is 4KB, since that's the normal pagesize and setting kLargeStackSize
156*6777b538SAndroid Build Coastguard Worker     // smaller than that would be pointless. Max is 8MB since that's the
157*6777b538SAndroid Build Coastguard Worker     // current ChromeOS stack size; we shouldn't be able to get a number
158*6777b538SAndroid Build Coastguard Worker     // larger than that.
159*6777b538SAndroid Build Coastguard Worker     UmaHistogramCustomCounts(
160*6777b538SAndroid Build Coastguard Worker         "Memory.StackSamplingProfiler.StackSampleSize2",
161*6777b538SAndroid Build Coastguard Worker         saturated_cast<int>(stack_size / kBytesPerKilobyte), 4, 8 * 1024, 50);
162*6777b538SAndroid Build Coastguard Worker   }
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker   // We expect to very rarely see stacks larger than kLargeStackSize. If we see
165*6777b538SAndroid Build Coastguard Worker   // a stack larger than kLargeStackSize, we tell the kernel to discard the
166*6777b538SAndroid Build Coastguard Worker   // contents of the buffer (using madvise(MADV_DONTNEED)) after the first
167*6777b538SAndroid Build Coastguard Worker   // kLargeStackSize bytes to avoid permanently allocating memory that we won't
168*6777b538SAndroid Build Coastguard Worker   // use again. We don't want kLargeStackSize to be too small, however; for if
169*6777b538SAndroid Build Coastguard Worker   // we are constantly calling madvise(MADV_DONTNEED) and then writing to the
170*6777b538SAndroid Build Coastguard Worker   // same parts of the buffer, we're not saving memory and we'll cause extra
171*6777b538SAndroid Build Coastguard Worker   // page faults.
172*6777b538SAndroid Build Coastguard Worker   constexpr ptrdiff_t kLargeStackSize = 32 * kBytesPerKilobyte;
173*6777b538SAndroid Build Coastguard Worker   if (stack_size > kLargeStackSize) {
174*6777b538SAndroid Build Coastguard Worker     stack_buffer->MarkUpperBufferContentsAsUnneeded(kLargeStackSize);
175*6777b538SAndroid Build Coastguard Worker   }
176*6777b538SAndroid Build Coastguard Worker #endif  // #if BUILDFLAG(IS_CHROMEOS)
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker // static
WalkStackForTesting(ModuleCache * module_cache,RegisterContext * thread_context,uintptr_t stack_top,const base::circular_deque<std::unique_ptr<Unwinder>> & unwinders)180*6777b538SAndroid Build Coastguard Worker std::vector<Frame> StackSampler::WalkStackForTesting(
181*6777b538SAndroid Build Coastguard Worker     ModuleCache* module_cache,
182*6777b538SAndroid Build Coastguard Worker     RegisterContext* thread_context,
183*6777b538SAndroid Build Coastguard Worker     uintptr_t stack_top,
184*6777b538SAndroid Build Coastguard Worker     const base::circular_deque<std::unique_ptr<Unwinder>>& unwinders) {
185*6777b538SAndroid Build Coastguard Worker   return WalkStack(module_cache, thread_context, stack_top, unwinders);
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker // static
CreateForTesting(std::unique_ptr<StackCopier> stack_copier,UnwindersFactory core_unwinders_factory,ModuleCache * module_cache,RepeatingClosure record_sample_callback,StackSamplerTestDelegate * test_delegate)189*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> StackSampler::CreateForTesting(
190*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<StackCopier> stack_copier,
191*6777b538SAndroid Build Coastguard Worker     UnwindersFactory core_unwinders_factory,
192*6777b538SAndroid Build Coastguard Worker     ModuleCache* module_cache,
193*6777b538SAndroid Build Coastguard Worker     RepeatingClosure record_sample_callback,
194*6777b538SAndroid Build Coastguard Worker     StackSamplerTestDelegate* test_delegate) {
195*6777b538SAndroid Build Coastguard Worker   return base::WrapUnique(new StackSampler(
196*6777b538SAndroid Build Coastguard Worker       std::move(stack_copier), std::move(core_unwinders_factory), module_cache,
197*6777b538SAndroid Build Coastguard Worker       record_sample_callback, test_delegate));
198*6777b538SAndroid Build Coastguard Worker }
199*6777b538SAndroid Build Coastguard Worker 
StackSampler(std::unique_ptr<StackCopier> stack_copier,UnwindersFactory core_unwinders_factory,ModuleCache * module_cache,RepeatingClosure record_sample_callback,StackSamplerTestDelegate * test_delegate)200*6777b538SAndroid Build Coastguard Worker StackSampler::StackSampler(std::unique_ptr<StackCopier> stack_copier,
201*6777b538SAndroid Build Coastguard Worker                            UnwindersFactory core_unwinders_factory,
202*6777b538SAndroid Build Coastguard Worker                            ModuleCache* module_cache,
203*6777b538SAndroid Build Coastguard Worker                            RepeatingClosure record_sample_callback,
204*6777b538SAndroid Build Coastguard Worker                            StackSamplerTestDelegate* test_delegate)
205*6777b538SAndroid Build Coastguard Worker     : stack_copier_(std::move(stack_copier)),
206*6777b538SAndroid Build Coastguard Worker       unwinders_factory_(std::move(core_unwinders_factory)),
207*6777b538SAndroid Build Coastguard Worker       module_cache_(module_cache),
208*6777b538SAndroid Build Coastguard Worker       record_sample_callback_(std::move(record_sample_callback)),
209*6777b538SAndroid Build Coastguard Worker       test_delegate_(test_delegate) {
210*6777b538SAndroid Build Coastguard Worker   CHECK(unwinders_factory_);
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker // static
WalkStack(ModuleCache * module_cache,RegisterContext * thread_context,uintptr_t stack_top,const base::circular_deque<std::unique_ptr<Unwinder>> & unwinders)214*6777b538SAndroid Build Coastguard Worker std::vector<Frame> StackSampler::WalkStack(
215*6777b538SAndroid Build Coastguard Worker     ModuleCache* module_cache,
216*6777b538SAndroid Build Coastguard Worker     RegisterContext* thread_context,
217*6777b538SAndroid Build Coastguard Worker     uintptr_t stack_top,
218*6777b538SAndroid Build Coastguard Worker     const base::circular_deque<std::unique_ptr<Unwinder>>& unwinders) {
219*6777b538SAndroid Build Coastguard Worker   std::vector<Frame> stack;
220*6777b538SAndroid Build Coastguard Worker   // Reserve enough memory for most stacks, to avoid repeated
221*6777b538SAndroid Build Coastguard Worker   // allocations. Approximately 99.9% of recorded stacks are 128 frames or
222*6777b538SAndroid Build Coastguard Worker   // fewer.
223*6777b538SAndroid Build Coastguard Worker   stack.reserve(128);
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker   // Record the first frame from the context values.
226*6777b538SAndroid Build Coastguard Worker   stack.emplace_back(RegisterContextInstructionPointer(thread_context),
227*6777b538SAndroid Build Coastguard Worker                      module_cache->GetModuleForAddress(
228*6777b538SAndroid Build Coastguard Worker                          RegisterContextInstructionPointer(thread_context)));
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   size_t prior_stack_size;
231*6777b538SAndroid Build Coastguard Worker   UnwindResult result;
232*6777b538SAndroid Build Coastguard Worker   do {
233*6777b538SAndroid Build Coastguard Worker     // Choose an authoritative unwinder for the current module. Use the first
234*6777b538SAndroid Build Coastguard Worker     // unwinder that thinks it can unwind from the current frame.
235*6777b538SAndroid Build Coastguard Worker     auto unwinder = ranges::find_if(
236*6777b538SAndroid Build Coastguard Worker         unwinders, [&stack](const std::unique_ptr<Unwinder>& unwinder) {
237*6777b538SAndroid Build Coastguard Worker           return unwinder->CanUnwindFrom(stack.back());
238*6777b538SAndroid Build Coastguard Worker         });
239*6777b538SAndroid Build Coastguard Worker     if (unwinder == unwinders.end())
240*6777b538SAndroid Build Coastguard Worker       return stack;
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker     prior_stack_size = stack.size();
243*6777b538SAndroid Build Coastguard Worker     result = unwinder->get()->TryUnwind(thread_context, stack_top, &stack);
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker     // The unwinder with the lowest priority should be the only one that returns
246*6777b538SAndroid Build Coastguard Worker     // COMPLETED since the stack starts in native code.
247*6777b538SAndroid Build Coastguard Worker     DCHECK(result != UnwindResult::kCompleted ||
248*6777b538SAndroid Build Coastguard Worker            unwinder->get() == unwinders.back().get());
249*6777b538SAndroid Build Coastguard Worker   } while (result != UnwindResult::kAborted &&
250*6777b538SAndroid Build Coastguard Worker            result != UnwindResult::kCompleted &&
251*6777b538SAndroid Build Coastguard Worker            // Give up if the authoritative unwinder for the module was unable to
252*6777b538SAndroid Build Coastguard Worker            // unwind.
253*6777b538SAndroid Build Coastguard Worker            stack.size() > prior_stack_size);
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker   return stack;
256*6777b538SAndroid Build Coastguard Worker }
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker StackSamplerTestDelegate::~StackSamplerTestDelegate() = default;
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker StackSamplerTestDelegate::StackSamplerTestDelegate() = default;
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker }  // namespace base
263