Commit 7a2ff0d9 authored by Etienne Pierre-doray's avatar Etienne Pierre-doray Committed by Commit Bot

[Clank SSM]: StackSampler construction takes std::vector of unwinders.

To allow construction with multiple unwinder. This is necessary on android
to provide native and chrome unwinders and will be used in a follow in
stack_sampling_profiler_unittest.cc
https://chromium-review.googlesource.com/c/chromium/src/+/2201658

Bug: 989102
Change-Id: I05ef97403668d82dc7e6e4e9505be95e941174dd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2211862
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Reviewed-by: default avatarMike Wittman <wittman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773353}
parent 427a928a
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define BASE_PROFILER_STACK_SAMPLER_H_ #define BASE_PROFILER_STACK_SAMPLER_H_
#include <memory> #include <memory>
#include <vector>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/macros.h" #include "base/macros.h"
...@@ -28,12 +29,14 @@ class BASE_EXPORT StackSampler { ...@@ -28,12 +29,14 @@ class BASE_EXPORT StackSampler {
virtual ~StackSampler(); virtual ~StackSampler();
// Creates a stack sampler that records samples for thread with // Creates a stack sampler that records samples for thread with
// |thread_token|. Returns null if this platform does not support stack // |thread_token|. Unwinders in |unwinders| must be stored in increasing
// sampling. // priority to guide unwind attempts. Only the unwinder with the lowest
// priority is allowed to return with UnwindResult::COMPLETED. Returns null if
// this platform does not support stack sampling.
static std::unique_ptr<StackSampler> Create( static std::unique_ptr<StackSampler> Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate); StackSamplerTestDelegate* test_delegate);
// Gets the required size of the stack buffer. // Gets the required size of the stack buffer.
...@@ -47,9 +50,8 @@ class BASE_EXPORT StackSampler { ...@@ -47,9 +50,8 @@ class BASE_EXPORT StackSampler {
// thread being sampled). // thread being sampled).
// Adds an auxiliary unwinder to handle additional, non-native-code unwind // Adds an auxiliary unwinder to handle additional, non-native-code unwind
// scenarios. When attempting to unwind, the relative priority of auxiliary // scenarios. Unwinders must be inserted in increasing priority, following
// unwinders is the inverse of the order of insertion, and the native // |unwinders| provided in Create(), to guide unwind attempts.
// unwinder is given the lowest priority
virtual void AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder) = 0; virtual void AddAuxUnwinder(std::unique_ptr<Unwinder> unwinder) = 0;
// Records a set of frames and returns them. // Records a set of frames and returns them.
......
...@@ -18,13 +18,15 @@ namespace base { ...@@ -18,13 +18,15 @@ namespace base {
std::unique_ptr<StackSampler> StackSampler::Create( std::unique_ptr<StackSampler> StackSampler::Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
DCHECK(native_unwinder); // |core_unwinders| must contain NativeUnwinderAndroid and
// ChromeUnwinderAndroid, respectively.
DCHECK_EQ(2U, core_unwinders.size());
return std::make_unique<StackSamplerImpl>( return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSignal>( std::make_unique<StackCopierSignal>(
std::make_unique<ThreadDelegatePosix>(thread_token)), std::make_unique<ThreadDelegatePosix>(thread_token)),
std::move(native_unwinder), module_cache, test_delegate); std::move(core_unwinders), module_cache, test_delegate);
} }
size_t StackSampler::GetStackBufferSize() { size_t StackSampler::GetStackBufferSize() {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "base/profiler/stack_sampler_impl.h" #include "base/profiler/stack_sampler_impl.h"
#include <iterator>
#include <utility> #include <utility>
#include "base/check.h" #include "base/check.h"
...@@ -64,15 +65,20 @@ class StackCopierDelegate : public StackCopier::Delegate { ...@@ -64,15 +65,20 @@ class StackCopierDelegate : public StackCopier::Delegate {
} // namespace } // namespace
StackSamplerImpl::StackSamplerImpl(std::unique_ptr<StackCopier> stack_copier, // |core_unwinders| is iterated backward since |core_unwinders| is passed in
std::unique_ptr<Unwinder> native_unwinder, // increasing priority order while |unwinders_| is stored in decreasing priority
ModuleCache* module_cache, // order.
StackSamplerTestDelegate* test_delegate) StackSamplerImpl::StackSamplerImpl(
std::unique_ptr<StackCopier> stack_copier,
std::vector<std::unique_ptr<Unwinder>> core_unwinders,
ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate)
: stack_copier_(std::move(stack_copier)), : stack_copier_(std::move(stack_copier)),
unwinders_(std::make_move_iterator(core_unwinders.rbegin()),
std::make_move_iterator(core_unwinders.rend())),
module_cache_(module_cache), module_cache_(module_cache),
test_delegate_(test_delegate) { test_delegate_(test_delegate) {
DCHECK(native_unwinder); DCHECK(!unwinders_.empty());
unwinders_.push_front(std::move(native_unwinder));
} }
StackSamplerImpl::~StackSamplerImpl() = default; StackSamplerImpl::~StackSamplerImpl() = default;
...@@ -155,8 +161,8 @@ std::vector<Frame> StackSamplerImpl::WalkStack( ...@@ -155,8 +161,8 @@ std::vector<Frame> StackSamplerImpl::WalkStack(
result = unwinder->get()->TryUnwind(thread_context, stack_top, module_cache, result = unwinder->get()->TryUnwind(thread_context, stack_top, module_cache,
&stack); &stack);
// The native unwinder should be the only one that returns COMPLETED // The unwinder with the lowest priority should be the only one that returns
// since the stack starts in native code. // COMPLETED since the stack starts in native code.
DCHECK(result != UnwindResult::COMPLETED || DCHECK(result != UnwindResult::COMPLETED ||
unwinder->get() == unwinders.back().get()); unwinder->get() == unwinders.back().get());
} while (result != UnwindResult::ABORTED && } while (result != UnwindResult::ABORTED &&
......
...@@ -23,7 +23,7 @@ class Unwinder; ...@@ -23,7 +23,7 @@ class Unwinder;
class BASE_EXPORT StackSamplerImpl : public StackSampler { class BASE_EXPORT StackSamplerImpl : public StackSampler {
public: public:
StackSamplerImpl(std::unique_ptr<StackCopier> stack_copier, StackSamplerImpl(std::unique_ptr<StackCopier> stack_copier,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
ModuleCache* module_cache, ModuleCache* module_cache,
StackSamplerTestDelegate* test_delegate = nullptr); StackSamplerTestDelegate* test_delegate = nullptr);
~StackSamplerImpl() override; ~StackSamplerImpl() override;
......
...@@ -268,14 +268,21 @@ class FakeTestUnwinder : public Unwinder { ...@@ -268,14 +268,21 @@ class FakeTestUnwinder : public Unwinder {
std::vector<Result> results_; std::vector<Result> results_;
}; };
base::circular_deque<std::unique_ptr<Unwinder>> MakeUnwinderList( std::vector<std::unique_ptr<Unwinder>> MakeUnwinderVector(
std::unique_ptr<Unwinder> unwinder) {
std::vector<std::unique_ptr<Unwinder>> unwinders;
unwinders.push_back(std::move(unwinder));
return unwinders;
}
base::circular_deque<std::unique_ptr<Unwinder>> MakeUnwinderCircularDeque(
std::unique_ptr<Unwinder> native_unwinder, std::unique_ptr<Unwinder> native_unwinder,
std::unique_ptr<Unwinder> aux_unwinder) { std::unique_ptr<Unwinder> aux_unwinder) {
base::circular_deque<std::unique_ptr<Unwinder>> unwinders; base::circular_deque<std::unique_ptr<Unwinder>> unwinders;
if (aux_unwinder)
unwinders.push_back(std::move(aux_unwinder));
if (native_unwinder) if (native_unwinder)
unwinders.push_back(std::move(native_unwinder)); unwinders.push_front(std::move(native_unwinder));
if (aux_unwinder)
unwinders.push_front(std::move(aux_unwinder));
return unwinders; return unwinders;
} }
...@@ -294,7 +301,9 @@ TEST(StackSamplerImplTest, MAYBE_CopyStack) { ...@@ -294,7 +301,9 @@ TEST(StackSamplerImplTest, MAYBE_CopyStack) {
std::vector<uintptr_t> stack_copy; std::vector<uintptr_t> stack_copy;
StackSamplerImpl stack_sampler_impl( StackSamplerImpl stack_sampler_impl(
std::make_unique<TestStackCopier>(stack), std::make_unique<TestStackCopier>(stack),
std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache); MakeUnwinderVector(
std::make_unique<TestUnwinder>(stack.size(), &stack_copy)),
&module_cache);
std::unique_ptr<StackBuffer> stack_buffer = std::unique_ptr<StackBuffer> stack_buffer =
std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t)); std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
...@@ -312,7 +321,9 @@ TEST(StackSamplerImplTest, CopyStackTimestamp) { ...@@ -312,7 +321,9 @@ TEST(StackSamplerImplTest, CopyStackTimestamp) {
TimeTicks timestamp = TimeTicks::UnixEpoch(); TimeTicks timestamp = TimeTicks::UnixEpoch();
StackSamplerImpl stack_sampler_impl( StackSamplerImpl stack_sampler_impl(
std::make_unique<TestStackCopier>(stack, timestamp), std::make_unique<TestStackCopier>(stack, timestamp),
std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache); MakeUnwinderVector(
std::make_unique<TestUnwinder>(stack.size(), &stack_copy)),
&module_cache);
std::unique_ptr<StackBuffer> stack_buffer = std::unique_ptr<StackBuffer> stack_buffer =
std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t)); std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
...@@ -330,7 +341,7 @@ TEST(StackSamplerImplTest, UnwinderInvokedWhileRecordingStackFrames) { ...@@ -330,7 +341,7 @@ TEST(StackSamplerImplTest, UnwinderInvokedWhileRecordingStackFrames) {
TestProfileBuilder profile_builder(&module_cache); TestProfileBuilder profile_builder(&module_cache);
StackSamplerImpl stack_sampler_impl( StackSamplerImpl stack_sampler_impl(
std::make_unique<DelegateInvokingStackCopier>(), std::make_unique<DelegateInvokingStackCopier>(),
std::move(owned_unwinder), &module_cache); MakeUnwinderVector(std::move(owned_unwinder)), &module_cache);
stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder); stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder);
...@@ -344,7 +355,8 @@ TEST(StackSamplerImplTest, AuxUnwinderInvokedWhileRecordingStackFrames) { ...@@ -344,7 +355,8 @@ TEST(StackSamplerImplTest, AuxUnwinderInvokedWhileRecordingStackFrames) {
TestProfileBuilder profile_builder(&module_cache); TestProfileBuilder profile_builder(&module_cache);
StackSamplerImpl stack_sampler_impl( StackSamplerImpl stack_sampler_impl(
std::make_unique<DelegateInvokingStackCopier>(), std::make_unique<DelegateInvokingStackCopier>(),
std::make_unique<CallRecordingUnwinder>(), &module_cache); MakeUnwinderVector(std::make_unique<CallRecordingUnwinder>()),
&module_cache);
auto owned_aux_unwinder = std::make_unique<CallRecordingUnwinder>(); auto owned_aux_unwinder = std::make_unique<CallRecordingUnwinder>();
CallRecordingUnwinder* aux_unwinder = owned_aux_unwinder.get(); CallRecordingUnwinder* aux_unwinder = owned_aux_unwinder.get();
...@@ -367,7 +379,7 @@ TEST(StackSamplerImplTest, WalkStack_Completed) { ...@@ -367,7 +379,7 @@ TEST(StackSamplerImplTest, WalkStack_Completed) {
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(std::move(native_unwinder), nullptr)); MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
ASSERT_EQ(2u, stack.size()); ASSERT_EQ(2u, stack.size());
EXPECT_EQ(1u, stack[1].instruction_pointer); EXPECT_EQ(1u, stack[1].instruction_pointer);
...@@ -384,7 +396,7 @@ TEST(StackSamplerImplTest, WalkStack_Aborted) { ...@@ -384,7 +396,7 @@ TEST(StackSamplerImplTest, WalkStack_Aborted) {
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(std::move(native_unwinder), nullptr)); MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
ASSERT_EQ(2u, stack.size()); ASSERT_EQ(2u, stack.size());
EXPECT_EQ(1u, stack[1].instruction_pointer); EXPECT_EQ(1u, stack[1].instruction_pointer);
...@@ -400,7 +412,7 @@ TEST(StackSamplerImplTest, WalkStack_NotUnwound) { ...@@ -400,7 +412,7 @@ TEST(StackSamplerImplTest, WalkStack_NotUnwound) {
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(std::move(native_unwinder), nullptr)); MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
ASSERT_EQ(1u, stack.size()); ASSERT_EQ(1u, stack.size());
} }
...@@ -421,7 +433,7 @@ TEST(StackSamplerImplTest, WalkStack_AuxUnwind) { ...@@ -421,7 +433,7 @@ TEST(StackSamplerImplTest, WalkStack_AuxUnwind) {
WrapUnique(new FakeTestUnwinder({{UnwindResult::ABORTED, {1u}}})); WrapUnique(new FakeTestUnwinder({{UnwindResult::ABORTED, {1u}}}));
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(nullptr, std::move(aux_unwinder))); MakeUnwinderCircularDeque(nullptr, std::move(aux_unwinder)));
ASSERT_EQ(2u, stack.size()); ASSERT_EQ(2u, stack.size());
EXPECT_EQ(GetTestInstructionPointer(), stack[0].instruction_pointer); EXPECT_EQ(GetTestInstructionPointer(), stack[0].instruction_pointer);
...@@ -447,7 +459,8 @@ TEST(StackSamplerImplTest, WalkStack_AuxThenNative) { ...@@ -447,7 +459,8 @@ TEST(StackSamplerImplTest, WalkStack_AuxThenNative) {
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(std::move(native_unwinder), std::move(aux_unwinder))); MakeUnwinderCircularDeque(std::move(native_unwinder),
std::move(aux_unwinder)));
ASSERT_EQ(3u, stack.size()); ASSERT_EQ(3u, stack.size());
EXPECT_EQ(0u, stack[0].instruction_pointer); EXPECT_EQ(0u, stack[0].instruction_pointer);
...@@ -477,7 +490,8 @@ TEST(StackSamplerImplTest, WalkStack_NativeThenAux) { ...@@ -477,7 +490,8 @@ TEST(StackSamplerImplTest, WalkStack_NativeThenAux) {
std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting( std::vector<Frame> stack = StackSamplerImpl::WalkStackForTesting(
&module_cache, &thread_context, 0u, &module_cache, &thread_context, 0u,
MakeUnwinderList(std::move(native_unwinder), std::move(aux_unwinder))); MakeUnwinderCircularDeque(std::move(native_unwinder),
std::move(aux_unwinder)));
ASSERT_EQ(4u, stack.size()); ASSERT_EQ(4u, stack.size());
EXPECT_EQ(0u, stack[0].instruction_pointer); EXPECT_EQ(0u, stack[0].instruction_pointer);
......
...@@ -13,7 +13,7 @@ namespace base { ...@@ -13,7 +13,7 @@ namespace base {
std::unique_ptr<StackSampler> StackSampler::Create( std::unique_ptr<StackSampler> StackSampler::Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
return nullptr; return nullptr;
} }
......
...@@ -16,14 +16,14 @@ namespace base { ...@@ -16,14 +16,14 @@ namespace base {
std::unique_ptr<StackSampler> StackSampler::Create( std::unique_ptr<StackSampler> StackSampler::Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
DCHECK(!native_unwinder); DCHECK(core_unwinders.empty());
core_unwinders.push_back(std::make_unique<NativeUnwinderMac>(module_cache));
return std::make_unique<StackSamplerImpl>( return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSuspend>( std::make_unique<StackCopierSuspend>(
std::make_unique<SuspendableThreadDelegateMac>(thread_token)), std::make_unique<SuspendableThreadDelegateMac>(thread_token)),
std::make_unique<NativeUnwinderMac>(module_cache), module_cache, std::move(core_unwinders), module_cache, test_delegate);
test_delegate);
} }
// static // static
......
...@@ -14,7 +14,7 @@ namespace base { ...@@ -14,7 +14,7 @@ namespace base {
std::unique_ptr<StackSampler> StackSampler::Create( std::unique_ptr<StackSampler> StackSampler::Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
return nullptr; return nullptr;
} }
......
...@@ -17,14 +17,15 @@ namespace base { ...@@ -17,14 +17,15 @@ namespace base {
std::unique_ptr<StackSampler> StackSampler::Create( std::unique_ptr<StackSampler> StackSampler::Create(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
ModuleCache* module_cache, ModuleCache* module_cache,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> core_unwinders,
StackSamplerTestDelegate* test_delegate) { StackSamplerTestDelegate* test_delegate) {
DCHECK(!native_unwinder); DCHECK(core_unwinders.empty());
#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64) #if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64)
core_unwinders.push_back(std::make_unique<NativeUnwinderWin>());
return std::make_unique<StackSamplerImpl>( return std::make_unique<StackSamplerImpl>(
std::make_unique<StackCopierSuspend>( std::make_unique<StackCopierSuspend>(
std::make_unique<SuspendableThreadDelegateWin>(thread_token)), std::make_unique<SuspendableThreadDelegateWin>(thread_token)),
std::make_unique<NativeUnwinderWin>(), module_cache, test_delegate); std::move(core_unwinders), module_cache, test_delegate);
#else #else
return nullptr; return nullptr;
#endif #endif
......
...@@ -733,12 +733,12 @@ StackSamplingProfiler::StackSamplingProfiler( ...@@ -733,12 +733,12 @@ StackSamplingProfiler::StackSamplingProfiler(
SamplingProfilerThreadToken thread_token, SamplingProfilerThreadToken thread_token,
const SamplingParams& params, const SamplingParams& params,
std::unique_ptr<ProfileBuilder> profile_builder, std::unique_ptr<ProfileBuilder> profile_builder,
std::unique_ptr<Unwinder> native_unwinder, std::vector<std::unique_ptr<Unwinder>> unwinders,
StackSamplerTestDelegate* test_delegate) StackSamplerTestDelegate* test_delegate)
: StackSamplingProfiler(params, std::move(profile_builder), nullptr) { : StackSamplingProfiler(params, std::move(profile_builder), nullptr) {
sampler_ = sampler_ =
StackSampler::Create(thread_token, profile_builder_->GetModuleCache(), StackSampler::Create(thread_token, profile_builder_->GetModuleCache(),
std::move(native_unwinder), test_delegate); std::move(unwinders), test_delegate);
} }
StackSamplingProfiler::StackSamplingProfiler( StackSamplingProfiler::StackSamplingProfiler(
......
...@@ -74,18 +74,20 @@ class BASE_EXPORT StackSamplingProfiler { ...@@ -74,18 +74,20 @@ class BASE_EXPORT StackSamplingProfiler {
TimeDelta sampling_interval = TimeDelta::FromMilliseconds(100); TimeDelta sampling_interval = TimeDelta::FromMilliseconds(100);
}; };
// Creates a profiler for the specified thread. |native_unwinder| is required // Creates a profiler for the specified thread. |unwinders| is required on
// on Android since the unwinder is provided outside StackSamplingProfiler, // Android since the unwinder is provided outside StackSamplingProfiler, but
// but must be null on other platforms. An optional |test_delegate| can be // must be empty on other platforms. When attempting to unwind, the relative
// supplied by tests. // priority of unwinders is the inverse of the order in |unwinders|. An
// optional |test_delegate| can be supplied by tests.
// //
// The caller must ensure that this object gets destroyed before the thread // The caller must ensure that this object gets destroyed before the thread
// exits. // exits.
StackSamplingProfiler(SamplingProfilerThreadToken thread_token, StackSamplingProfiler(
const SamplingParams& params, SamplingProfilerThreadToken thread_token,
std::unique_ptr<ProfileBuilder> profile_builder, const SamplingParams& params,
std::unique_ptr<Unwinder> native_unwinder = nullptr, std::unique_ptr<ProfileBuilder> profile_builder,
StackSamplerTestDelegate* test_delegate = nullptr); std::vector<std::unique_ptr<Unwinder>> core_unwinders = {},
StackSamplerTestDelegate* test_delegate = nullptr);
// Same as above function, with custom |sampler| implementation. The sampler // Same as above function, with custom |sampler| implementation. The sampler
// on Android is not implemented in base. // on Android is not implemented in base.
......
...@@ -213,7 +213,7 @@ struct TestProfilerInfo { ...@@ -213,7 +213,7 @@ struct TestProfilerInfo {
profile = std::move(result_profile); profile = std::move(result_profile);
completed.Signal(); completed.Signal();
})), })),
nullptr, {},
delegate) {} delegate) {}
// The order here is important to ensure objects being referenced don't get // The order here is important to ensure objects being referenced don't get
...@@ -347,7 +347,7 @@ void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) { ...@@ -347,7 +347,7 @@ void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) {
profile = std::move(result_profile); profile = std::move(result_profile);
sampling_thread_completed.Signal(); sampling_thread_completed.Signal();
})), })),
nullptr, &test_delegate); {}, &test_delegate);
profiler.Start(); profiler.Start();
...@@ -1427,7 +1427,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, ...@@ -1427,7 +1427,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest,
BindLambdaForTesting([&profile](Profile result_profile) { BindLambdaForTesting([&profile](Profile result_profile) {
profile = std::move(result_profile); profile = std::move(result_profile);
})), })),
nullptr, &post_sample_invoker); {}, &post_sample_invoker);
profiler.Start(); profiler.Start();
// Wait for 5 samples to be collected. // Wait for 5 samples to be collected.
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
...@@ -72,9 +73,9 @@ CallStackProfileParams::Process GetProcess() { ...@@ -72,9 +73,9 @@ CallStackProfileParams::Process GetProcess() {
return CallStackProfileParams::UNKNOWN_PROCESS; return CallStackProfileParams::UNKNOWN_PROCESS;
} }
const base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>& const base::RepeatingCallback<std::vector<std::unique_ptr<base::Unwinder>>()>&
GetNativeUnwinderFactory() { GetCoreUnwindersFactory() {
const auto create_native_unwinder_factory = []() { const auto create_unwinders_factory = []() {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// The module is loadable if the profiler is enabled for the current // The module is loadable if the profiler is enabled for the current
// process. // process.
...@@ -85,30 +86,31 @@ GetNativeUnwinderFactory() { ...@@ -85,30 +86,31 @@ GetNativeUnwinderFactory() {
std::unique_ptr<stack_unwinder::Module> module; std::unique_ptr<stack_unwinder::Module> module;
std::unique_ptr<stack_unwinder::MemoryRegionsMap> memory_regions_map; std::unique_ptr<stack_unwinder::MemoryRegionsMap> memory_regions_map;
}; };
const auto create_native_unwinder = const auto create_unwinders = [](UnwinderCreationState* creation_state) {
[](UnwinderCreationState* creation_state) { std::vector<std::unique_ptr<base::Unwinder>> unwinders;
return creation_state->module->CreateNativeUnwinder( unwinders.push_back(creation_state->module->CreateNativeUnwinder(
creation_state->memory_regions_map.get(), creation_state->memory_regions_map.get(),
reinterpret_cast<uintptr_t>(&__executable_start)); reinterpret_cast<uintptr_t>(&__executable_start)));
}; return unwinders;
};
std::unique_ptr<stack_unwinder::Module> module = std::unique_ptr<stack_unwinder::Module> module =
stack_unwinder::Module::Load(); stack_unwinder::Module::Load();
std::unique_ptr<stack_unwinder::MemoryRegionsMap> memory_regions_map = std::unique_ptr<stack_unwinder::MemoryRegionsMap> memory_regions_map =
module->CreateMemoryRegionsMap(); module->CreateMemoryRegionsMap();
return base::BindRepeating( return base::BindRepeating(
create_native_unwinder, create_unwinders,
base::Owned(new UnwinderCreationState{std::move(module), base::Owned(new UnwinderCreationState{std::move(module),
std::move(memory_regions_map)})); std::move(memory_regions_map)}));
#else #else
return base::BindRepeating( return base::BindRepeating(
[]() -> std::unique_ptr<base::Unwinder> { return nullptr; }); []() -> std::vector<std::unique_ptr<base::Unwinder>> { return {}; });
#endif #endif
}; };
static base::NoDestructor< static base::NoDestructor<
base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>> base::RepeatingCallback<std::vector<std::unique_ptr<base::Unwinder>>()>>
native_unwinder_factory(create_native_unwinder_factory()); native_unwinder_factory(create_unwinders_factory());
return *native_unwinder_factory; return *native_unwinder_factory;
} }
...@@ -285,13 +287,14 @@ ThreadProfiler::ThreadProfiler( ...@@ -285,13 +287,14 @@ ThreadProfiler::ThreadProfiler(
const base::StackSamplingProfiler::SamplingParams sampling_params = const base::StackSamplingProfiler::SamplingParams sampling_params =
StackSamplingConfiguration::Get()->GetSamplingParams(); StackSamplingConfiguration::Get()->GetSamplingParams();
startup_profiler_ = std::make_unique<StackSamplingProfiler>( startup_profiler_ = std::make_unique<StackSamplingProfiler>(
base::GetSamplingProfilerCurrentThreadToken(), sampling_params, base::GetSamplingProfilerCurrentThreadToken(), sampling_params,
std::make_unique<CallStackProfileBuilder>( std::make_unique<CallStackProfileBuilder>(
CallStackProfileParams(GetProcess(), thread, CallStackProfileParams(GetProcess(), thread,
CallStackProfileParams::PROCESS_STARTUP), CallStackProfileParams::PROCESS_STARTUP),
work_id_recorder_.get()), work_id_recorder_.get()),
GetNativeUnwinderFactory().Run()); GetCoreUnwindersFactory().Run());
startup_profiler_->Start(); startup_profiler_->Start();
...@@ -356,7 +359,7 @@ void ThreadProfiler::StartPeriodicSamplingCollection() { ...@@ -356,7 +359,7 @@ void ThreadProfiler::StartPeriodicSamplingCollection() {
base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted, base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted,
owning_thread_task_runner_, owning_thread_task_runner_,
weak_factory_.GetWeakPtr())), weak_factory_.GetWeakPtr())),
GetNativeUnwinderFactory().Run()); GetCoreUnwindersFactory().Run());
if (aux_unwinder_factory_) if (aux_unwinder_factory_)
periodic_profiler_->AddAuxUnwinder(aux_unwinder_factory_.Run()); periodic_profiler_->AddAuxUnwinder(aux_unwinder_factory_.Run());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment