LCOV - code coverage report
Current view: top level - src/libsampler - sampler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 3 3 100.0 %
Date: 2019-04-19 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2016 the V8 project 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 V8_LIBSAMPLER_SAMPLER_H_
       6             : #define V8_LIBSAMPLER_SAMPLER_H_
       7             : 
       8             : #include <atomic>
       9             : #include <unordered_map>
      10             : 
      11             : #include "include/v8.h"
      12             : #include "src/base/lazy-instance.h"
      13             : #include "src/base/macros.h"
      14             : 
      15             : #if V8_OS_POSIX && !V8_OS_CYGWIN && !V8_OS_FUCHSIA
      16             : #define USE_SIGNALS
      17             : #endif
      18             : 
      19             : namespace v8 {
      20             : namespace sampler {
      21             : 
      22             : // ----------------------------------------------------------------------------
      23             : // Sampler
      24             : //
      25             : // A sampler periodically samples the state of the VM and optionally
      26             : // (if used for profiling) the program counter and stack pointer for
      27             : // the thread that created it.
      28             : 
      29             : class V8_EXPORT_PRIVATE Sampler {
      30             :  public:
      31             :   static const int kMaxFramesCountLog2 = 8;
      32             :   static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
      33             : 
      34             :   // Initialize sampler.
      35             :   explicit Sampler(Isolate* isolate);
      36             :   virtual ~Sampler();
      37             : 
      38             :   Isolate* isolate() const { return isolate_; }
      39             : 
      40             :   // Performs stack sampling.
      41             :   // Clients should override this method in order to do something on samples,
      42             :   // for example buffer samples in a queue.
      43             :   virtual void SampleStack(const v8::RegisterState& regs) = 0;
      44             : 
      45             :   // Start and stop sampler.
      46             :   void Start();
      47             :   void Stop();
      48             : 
      49             :   // Whether the sampler is running (start has been called).
      50             :   bool IsActive() const { return active_.load(std::memory_order_relaxed); }
      51             : 
      52             :   // Returns true and consumes the pending sample bit if a sample should be
      53             :   // dispatched to this sampler.
      54             :   bool ShouldRecordSample() {
      55             :     return record_sample_.exchange(false, std::memory_order_relaxed);
      56             :   }
      57             : 
      58             :   void DoSample();
      59             : 
      60             :   // Used in tests to make sure that stack sampling is performed.
      61             :   unsigned js_sample_count() const { return js_sample_count_; }
      62             :   unsigned external_sample_count() const { return external_sample_count_; }
      63             :   void StartCountingSamples() {
      64         560 :     js_sample_count_ = 0;
      65         560 :     external_sample_count_ = 0;
      66         560 :     is_counting_samples_ = true;
      67             :   }
      68             : 
      69             :   class PlatformData;
      70             :   PlatformData* platform_data() const { return data_.get(); }
      71             : 
      72             :  protected:
      73             :   // Counts stack samples taken in various VM states.
      74             :   bool is_counting_samples_ = 0;
      75             :   unsigned js_sample_count_ = 0;
      76             :   unsigned external_sample_count_ = 0;
      77             : 
      78             :   void SetActive(bool value) {
      79             :     active_.store(value, std::memory_order_relaxed);
      80             :   }
      81             : 
      82             :   void SetShouldRecordSample() {
      83             :     record_sample_.store(true, std::memory_order_relaxed);
      84             :   }
      85             : 
      86             :   Isolate* isolate_;
      87             :   std::atomic_bool active_{false};
      88             :   std::atomic_bool record_sample_{false};
      89             :   std::unique_ptr<PlatformData> data_;  // Platform specific data.
      90             :   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
      91             : };
      92             : 
      93             : #ifdef USE_SIGNALS
      94             : 
      95             : typedef std::atomic_bool AtomicMutex;
      96             : 
      97             : // A helper that uses an std::atomic_bool to create a lock that is obtained on
      98             : // construction and released on destruction.
      99             : class V8_EXPORT_PRIVATE AtomicGuard {
     100             :  public:
     101             :   // Attempt to obtain the lock represented by |atomic|. |is_blocking|
     102             :   // determines whether we will block to obtain the lock, or only make one
     103             :   // attempt to gain the lock and then stop. If we fail to gain the lock,
     104             :   // is_success will be false.
     105             :   explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true);
     106             : 
     107             :   // Releases the lock represented by atomic, if it is held by this guard.
     108             :   ~AtomicGuard();
     109             : 
     110             :   // Whether the lock was successfully obtained in the constructor. This will
     111             :   // always be true if is_blocking was true.
     112             :   bool is_success() const;
     113             : 
     114             :  private:
     115             :   AtomicMutex* const atomic_;
     116             :   bool is_success_;
     117             : };
     118             : 
     119             : // SamplerManager keeps a list of Samplers per thread, and allows the caller to
     120             : // take a sample for every Sampler on the current thread.
     121             : class V8_EXPORT_PRIVATE SamplerManager {
     122             :  public:
     123             :   typedef std::vector<Sampler*> SamplerList;
     124             : 
     125             :   // Add |sampler| to the map if it is not already present.
     126             :   void AddSampler(Sampler* sampler);
     127             : 
     128             :   // If |sampler| exists in the map, remove it and delete the SamplerList if
     129             :   // |sampler| was the last sampler in the list.
     130             :   void RemoveSampler(Sampler* sampler);
     131             : 
     132             :   // Take a sample for every sampler on the current thread. This function can
     133             :   // return without taking samples if AddSampler or RemoveSampler are being
     134             :   // concurrently called on any thread.
     135             :   void DoSample(const v8::RegisterState& state);
     136             : 
     137             :   // Get the lazily instantiated, global SamplerManager instance.
     138             :   static SamplerManager* instance();
     139             : 
     140             :  private:
     141             :   SamplerManager() = default;
     142             :   // Must be a friend so that it can access the private constructor for the
     143             :   // global lazy instance.
     144             :   friend class base::LeakyObject<SamplerManager>;
     145             : 
     146             :   std::unordered_map<pthread_t, SamplerList> sampler_map_;
     147             :   AtomicMutex samplers_access_counter_{false};
     148             : 
     149             :   DISALLOW_COPY_AND_ASSIGN(SamplerManager);
     150             : };
     151             : 
     152             : #endif  // USE_SIGNALS
     153             : 
     154             : }  // namespace sampler
     155             : }  // namespace v8
     156             : 
     157             : #endif  // V8_LIBSAMPLER_SAMPLER_H_

Generated by: LCOV version 1.10