[sampling heap profiler] Extract Poisson sampler into a separate class.

Make Poisson sampler a separate class that is responsible for listening
for allocation and doing the sampling with given sampling interval.

SamplingHeapProfiler is now an observer of PoissonAllocationObserver.
Once a sample added it record the native stack and stores the sample
in the map. The list of recorded samples can then be retrieved by clients.

[email protected]
BUG=803276

Change-Id: I1e568b9839d9cc0099704ba1b9f047c14a46a0ee
Reviewed-on: https://chromium-review.googlesource.com/1189713
Reviewed-by: Alexei Filippov <[email protected]>
Reviewed-by: Kentaro Hara <[email protected]>
Reviewed-by: Erik Chen <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Commit-Queue: Alexei Filippov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#586369}
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.h b/base/sampling_heap_profiler/sampling_heap_profiler.h
index 1ef7f3f..194fdd3 100644
--- a/base/sampling_heap_profiler/sampling_heap_profiler.h
+++ b/base/sampling_heap_profiler/sampling_heap_profiler.h
@@ -5,13 +5,12 @@
 #ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
 #define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
 
-#include <memory>
-#include <stack>
 #include <unordered_map>
 #include <vector>
 
 #include "base/base_export.h"
 #include "base/macros.h"
+#include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_local.h"
 
@@ -20,17 +19,13 @@
 template <typename T>
 class NoDestructor;
 
-class LockFreeAddressHashSet;
-
 // The class implements sampling profiling of native memory heap.
-// It hooks on base::allocator and base::PartitionAlloc.
-// When started it selects and records allocation samples based on
-// the sampling_interval parameter.
+// It uses PoissonAllocationSampler to aggregate the heap allocations and
+// record samples.
 // The recorded samples can then be retrieved using GetSamples method.
-class BASE_EXPORT SamplingHeapProfiler {
+class BASE_EXPORT SamplingHeapProfiler
+    : private PoissonAllocationSampler::SamplesObserver {
  public:
-  enum AllocatorType : uint32_t { kMalloc, kPartitionAlloc, kBlinkGC, kMax };
-
   class BASE_EXPORT Sample {
    public:
     Sample(const Sample&);
@@ -48,80 +43,33 @@
     uint32_t ordinal;
   };
 
-  class SamplesObserver {
-   public:
-    virtual ~SamplesObserver() = default;
-    virtual void SampleAdded(void* address,
-                             size_t size,
-                             size_t total,
-                             AllocatorType type,
-                             const char* context) = 0;
-    virtual void SampleRemoved(void* address) = 0;
-  };
-
-  // Must be called early during the process initialization. It creates and
-  // reserves a TLS slot.
-  static void InitTLSSlot();
-
-  // This is an entry point for plugging in an external allocator.
-  // Profiler will invoke the provided callback upon initialization.
-  // The callback should install hooks onto the corresponding memory allocator
-  // and make them invoke SamplingHeapProfiler::RecordAlloc and
-  // SamplingHeapProfiler::RecordFree upon corresponding allocation events.
-  //
-  // If the method is called after profiler is initialized, the callback
-  // is invoked right away.
-  static void SetHooksInstallCallback(void (*hooks_install_callback)());
-
-  void AddSamplesObserver(SamplesObserver*);
-  void RemoveSamplesObserver(SamplesObserver*);
-
   uint32_t Start();
   void Stop();
   void SetSamplingInterval(size_t sampling_interval);
-  void SuppressRandomnessForTest(bool suppress);
 
   std::vector<Sample> GetSamples(uint32_t profile_id);
 
-  static void RecordAlloc(void* address,
-                          size_t,
-                          AllocatorType,
-                          const char* context,
-                          uint32_t skip_frames = 0);
-  static void RecordFree(void* address);
-
-  static SamplingHeapProfiler* GetInstance();
+  static void Init();
+  static SamplingHeapProfiler* Get();
 
  private:
   SamplingHeapProfiler();
-  ~SamplingHeapProfiler() = delete;
+  ~SamplingHeapProfiler() override;
 
-  static void InstallAllocatorHooksOnce();
-  static bool InstallAllocatorHooks();
-  static size_t GetNextSampleInterval(size_t base_interval);
+  // PoissonAllocationSampler::SamplesObserver
+  void SampleAdded(void* address,
+                   size_t size,
+                   size_t total,
+                   PoissonAllocationSampler::AllocatorType type,
+                   const char* context) override;
+  void SampleRemoved(void* address) override;
 
-  void DoRecordAlloc(size_t total_allocated,
-                     size_t allocation_size,
-                     void* address,
-                     AllocatorType type,
-                     const char* context,
-                     uint32_t skip_frames);
-  void DoRecordFree(void* address);
-  void RecordStackTrace(Sample*, uint32_t skip_frames);
-  static LockFreeAddressHashSet& sampled_addresses_set();
-
-  void BalanceAddressesHashSet();
-
-  base::ThreadLocalBoolean entered_;
-  base::Lock mutex_;
-  std::stack<std::unique_ptr<LockFreeAddressHashSet>> sampled_addresses_stack_;
+  ThreadLocalBoolean entered_;
+  Lock mutex_;
   std::unordered_map<void*, Sample> samples_;
-  std::vector<SamplesObserver*> observers_;
   uint32_t last_sample_ordinal_ = 1;
 
-  static SamplingHeapProfiler* instance_;
-
-  friend class base::NoDestructor<SamplingHeapProfiler>;
+  friend class NoDestructor<SamplingHeapProfiler>;
 
   DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler);
 };