// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_LIBSAMPLER_SAMPLER_H_
#define V8_LIBSAMPLER_SAMPLER_H_

#include <atomic>
#include <memory>
#include <unordered_map>

#include "include/v8.h"
#include "src/base/lazy-instance.h"
#include "src/base/macros.h"

#if V8_OS_POSIX && !V8_OS_CYGWIN && !V8_OS_FUCHSIA
#define USE_SIGNALS
#endif

namespace v8 {
namespace sampler {

// ----------------------------------------------------------------------------
// Sampler
//
// A sampler periodically samples the state of the VM and optionally
// (if used for profiling) the program counter and stack pointer for
// the thread that created it.

class V8_EXPORT_PRIVATE Sampler {
 public:
  static const int kMaxFramesCountLog2 = 8;
  static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;

  // Initialize sampler.
  explicit Sampler(Isolate* isolate);
  virtual ~Sampler();

  Isolate* isolate() const { return isolate_; }

  // Performs stack sampling.
  // Clients should override this method in order to do something on samples,
  // for example buffer samples in a queue.
  virtual void SampleStack(const v8::RegisterState& regs) = 0;

  // Start and stop sampler.
  void Start();
  void Stop();

  // Whether the sampler is running (start has been called).
  bool IsActive() const { return active_.load(std::memory_order_relaxed); }

  // Returns true and consumes the pending sample bit if a sample should be
  // dispatched to this sampler.
  bool ShouldRecordSample() {
    return record_sample_.exchange(false, std::memory_order_relaxed);
  }

  void DoSample();

  // Used in tests to make sure that stack sampling is performed.
  unsigned js_sample_count() const { return js_sample_count_; }
  unsigned external_sample_count() const { return external_sample_count_; }
  void StartCountingSamples() {
    js_sample_count_ = 0;
    external_sample_count_ = 0;
    is_counting_samples_ = true;
  }

  class PlatformData;
  PlatformData* platform_data() const { return data_.get(); }

 protected:
  // Counts stack samples taken in various VM states.
  bool is_counting_samples_ = false;
  unsigned js_sample_count_ = 0;
  unsigned external_sample_count_ = 0;

  void SetActive(bool value) {
    active_.store(value, std::memory_order_relaxed);
  }

  void SetShouldRecordSample() {
    record_sample_.store(true, std::memory_order_relaxed);
  }

  Isolate* isolate_;
  std::atomic_bool active_{false};
  std::atomic_bool record_sample_{false};
  std::unique_ptr<PlatformData> data_;  // Platform specific data.
  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
};

#ifdef USE_SIGNALS

using AtomicMutex = std::atomic_bool;

// A helper that uses an std::atomic_bool to create a lock that is obtained on
// construction and released on destruction.
class V8_EXPORT_PRIVATE AtomicGuard {
 public:
  // Attempt to obtain the lock represented by |atomic|. |is_blocking|
  // determines whether we will block to obtain the lock, or only make one
  // attempt to gain the lock and then stop. If we fail to gain the lock,
  // is_success will be false.
  explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true);

  // Releases the lock represented by atomic, if it is held by this guard.
  ~AtomicGuard();

  // Whether the lock was successfully obtained in the constructor. This will
  // always be true if is_blocking was true.
  bool is_success() const;

 private:
  AtomicMutex* const atomic_;
  bool is_success_;
};

// SamplerManager keeps a list of Samplers per thread, and allows the caller to
// take a sample for every Sampler on the current thread.
class V8_EXPORT_PRIVATE SamplerManager {
 public:
  using SamplerList = std::vector<Sampler*>;

  // Add |sampler| to the map if it is not already present.
  void AddSampler(Sampler* sampler);

  // If |sampler| exists in the map, remove it and delete the SamplerList if
  // |sampler| was the last sampler in the list.
  void RemoveSampler(Sampler* sampler);

  // Take a sample for every sampler on the current thread. This function can
  // return without taking samples if AddSampler or RemoveSampler are being
  // concurrently called on any thread.
  void DoSample(const v8::RegisterState& state);

  // Get the lazily instantiated, global SamplerManager instance.
  static SamplerManager* instance();

 private:
  SamplerManager() = default;
  // Must be a friend so that it can access the private constructor for the
  // global lazy instance.
  friend class base::LeakyObject<SamplerManager>;

  std::unordered_map<pthread_t, SamplerList> sampler_map_;
  AtomicMutex samplers_access_counter_{false};

  DISALLOW_COPY_AND_ASSIGN(SamplerManager);
};

#endif  // USE_SIGNALS

}  // namespace sampler
}  // namespace v8

#endif  // V8_LIBSAMPLER_SAMPLER_H_
