// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_PROFILER_H_
#define RUNTIME_VM_PROFILER_H_

#include "platform/atomic.h"

#include "vm/allocation.h"
#include "vm/bitfield.h"
#include "vm/code_observers.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/tags.h"
#include "vm/thread_interrupter.h"

// Profiler sampling and stack walking support.
// NOTE: For service related code, see profile_service.h.

namespace dart {

// Forward declarations.
class ProcessedSample;
class ProcessedSampleBuffer;

class Sample;
class SampleBlock;

#define PROFILER_COUNTERS(V)                                                   \
  V(bail_out_unknown_task)                                                     \
  V(bail_out_jump_to_exception_handler)                                        \
  V(bail_out_check_isolate)                                                    \
  V(single_frame_sample_deoptimizing)                                          \
  V(single_frame_sample_get_and_validate_stack_bounds)                         \
  V(stack_walker_native)                                                       \
  V(stack_walker_dart_exit)                                                    \
  V(stack_walker_dart)                                                         \
  V(stack_walker_none)                                                         \
  V(incomplete_sample_fp_bounds)                                               \
  V(incomplete_sample_fp_step)                                                 \
  V(incomplete_sample_bad_pc)                                                  \
  V(sample_allocation_failure)

struct ProfilerCounters {
#define DECLARE_PROFILER_COUNTER(name) RelaxedAtomic<int64_t> name;
  PROFILER_COUNTERS(DECLARE_PROFILER_COUNTER)
#undef DECLARE_PROFILER_COUNTER
};

class Profiler : public AllStatic {
 public:
  static void Init();
  static void Cleanup();

  static void SetSampleDepth(intptr_t depth);
  static void SetSamplePeriod(intptr_t period);
  // Restarts sampling with a given profile period. This is called after the
  // profile period is changed via the service protocol.
  static void UpdateSamplePeriod();
  // Starts or shuts down the profiler after --profiler is changed via the
  // service protocol.
  static void UpdateRunningState();

  static SampleBlockBuffer* sample_block_buffer() {
    return sample_block_buffer_;
  }
  static void set_sample_block_buffer(SampleBlockBuffer* buffer) {
    sample_block_buffer_ = buffer;
  }

  static void DumpStackTrace(void* context);
  static void DumpStackTrace(bool for_crash = true);

  static void SampleAllocation(Thread* thread,
                               intptr_t cid,
                               uint32_t identity_hash);

  // SampleThread is called from inside the signal handler and hence it is very
  // critical that the implementation of SampleThread does not do any of the
  // following:
  //   * Accessing TLS -- Because on Fuchsia, Mac and Windows the callback will
  //                      be running in a different thread.
  //   * Allocating memory -- Because this takes locks which may already be
  //                          held, resulting in a dead lock.
  //   * Taking a lock -- See above.
  static void SampleThread(Thread* thread, const InterruptedThreadState& state);

  static ProfilerCounters counters() {
    // Copies the counter values.
    return counters_;
  }
  inline static intptr_t Size();

  static void ProcessCompletedBlocks(Isolate* isolate);
  static void IsolateShutdown(Thread* thread);

 private:
  static void DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash);

  // Calculates the sample buffer capacity. Returns
  // SampleBuffer::kDefaultBufferCapacity if --sample-buffer-duration is not
  // provided. Otherwise, the capacity is based on the sample rate, maximum
  // sample stack depth, and the number of seconds of samples the sample buffer
  // should be able to accomodate.
  static intptr_t CalculateSampleBufferCapacity();

  // Does not walk the thread's stack.
  static void SampleThreadSingleFrame(Thread* thread,
                                      Sample* sample,
                                      uintptr_t pc);
  static RelaxedAtomic<bool> initialized_;

  static SampleBlockBuffer* sample_block_buffer_;

  static ProfilerCounters counters_;

  friend class Thread;
};

class SampleVisitor : public ValueObject {
 public:
  explicit SampleVisitor(Dart_Port port) : port_(port), visited_(0) {}
  virtual ~SampleVisitor() {}

  virtual void VisitSample(Sample* sample) = 0;

  virtual void Reset() { visited_ = 0; }

  intptr_t visited() const { return visited_; }

  void IncrementVisited() { visited_++; }

  Dart_Port port() const { return port_; }

 private:
  Dart_Port port_;
  intptr_t visited_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(SampleVisitor);
};

class SampleFilter : public ValueObject {
 public:
  SampleFilter(Dart_Port port,
               intptr_t thread_task_mask,
               int64_t time_origin_micros,
               int64_t time_extent_micros,
               bool take_samples = false)
      : port_(port),
        thread_task_mask_(thread_task_mask),
        time_origin_micros_(time_origin_micros),
        time_extent_micros_(time_extent_micros),
        take_samples_(take_samples) {
    ASSERT(thread_task_mask != 0);
    ASSERT(time_origin_micros_ >= -1);
    ASSERT(time_extent_micros_ >= -1);
  }
  virtual ~SampleFilter() {}

  // Override this function.
  // Return |true| if |sample| passes the filter.
  virtual bool FilterSample(Sample* sample) { return true; }

  Dart_Port port() const { return port_; }

  // Returns |true| if |sample| passes the time filter.
  bool TimeFilterSample(Sample* sample);

  // Returns |true| if |sample| passes the thread task filter.
  bool TaskFilterSample(Sample* sample);

  bool take_samples() const { return take_samples_; }

  static constexpr intptr_t kNoTaskFilter = -1;

 private:
  Dart_Port port_;
  intptr_t thread_task_mask_;
  int64_t time_origin_micros_;
  int64_t time_extent_micros_;
  bool take_samples_;
};

class ClearProfileVisitor : public SampleVisitor {
 public:
  explicit ClearProfileVisitor(Isolate* isolate);

  virtual void VisitSample(Sample* sample);
};

// Each Sample holds a stack trace from an isolate.
class Sample {
 public:
  Sample() = default;

  void Init(Dart_Port port, int64_t timestamp, ThreadId tid) {
    Clear();
    timestamp_ = timestamp;
    tid_ = tid;
    port_ = port;
    next_ = nullptr;
  }

  Dart_Port port() const { return port_; }

  // Thread sample was taken on.
  ThreadId tid() const { return tid_; }

  void Clear() {
    timestamp_ = 0;
    port_ = ILLEGAL_PORT;
    tid_ = OSThread::kInvalidThreadId;
    for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) {
      stack_buffer_[i] = 0;
    }
    for (intptr_t i = 0; i < kPCArraySizeInWords; i++) {
      pc_array_[i] = 0;
    }
    vm_tag_ = VMTag::kInvalidTagId;
    user_tag_ = UserTags::kDefaultUserTag;
    state_ = 0;
    next_ = nullptr;
    allocation_identity_hash_ = 0;
    set_head_sample(true);
  }

  // Timestamp sample was taken at.
  int64_t timestamp() const { return timestamp_; }

  // Top most pc.
  uword pc() const { return At(0); }

  // Get stack trace entry.
  uword At(intptr_t i) const {
    ASSERT(i >= 0);
    ASSERT(i < kPCArraySizeInWords);
    return pc_array_[i];
  }

  // Set stack trace entry.
  void SetAt(intptr_t i, uword pc) {
    ASSERT(i >= 0);
    ASSERT(i < kPCArraySizeInWords);
    pc_array_[i] = pc;
  }

  void DumpStackTrace() {
    for (intptr_t i = 0; i < kPCArraySizeInWords; ++i) {
      uintptr_t start = 0;
      uword pc = At(i);
      const char* native_symbol_name =
          NativeSymbolResolver::LookupSymbolName(pc, &start);
      if (native_symbol_name == nullptr) {
        OS::PrintErr("  [0x%" Pp "] Unknown symbol\n", pc);
      } else {
        OS::PrintErr("  [0x%" Pp "] %s\n", pc, native_symbol_name);
        NativeSymbolResolver::FreeSymbolName(native_symbol_name);
      }
    }
  }

  uword vm_tag() const { return vm_tag_; }
  void set_vm_tag(uword tag) {
    ASSERT(tag != VMTag::kInvalidTagId);
    vm_tag_ = tag;
  }

  uword user_tag() const { return user_tag_; }
  void set_user_tag(uword tag) { user_tag_ = tag; }

  bool leaf_frame_is_dart() const { return LeafFrameIsDart::decode(state_); }

  void set_leaf_frame_is_dart(bool leaf_frame_is_dart) {
    state_ = LeafFrameIsDart::update(leaf_frame_is_dart, state_);
  }

  bool ignore_sample() const { return IgnoreBit::decode(state_); }

  void set_ignore_sample(bool ignore_sample) {
    state_ = IgnoreBit::update(ignore_sample, state_);
  }

  bool exit_frame_sample() const { return ExitFrameBit::decode(state_); }

  void set_exit_frame_sample(bool exit_frame_sample) {
    state_ = ExitFrameBit::update(exit_frame_sample, state_);
  }

  bool missing_frame_inserted() const {
    return MissingFrameInsertedBit::decode(state_);
  }

  void set_missing_frame_inserted(bool missing_frame_inserted) {
    state_ = MissingFrameInsertedBit::update(missing_frame_inserted, state_);
  }

  bool truncated_trace() const { return TruncatedTraceBit::decode(state_); }

  void set_truncated_trace(bool truncated_trace) {
    state_ = TruncatedTraceBit::update(truncated_trace, state_);
  }

  bool is_allocation_sample() const {
    return ClassAllocationSampleBit::decode(state_);
  }

  void set_is_allocation_sample(bool allocation_sample) {
    state_ = ClassAllocationSampleBit::update(allocation_sample, state_);
  }

  uint32_t allocation_identity_hash() const {
    return allocation_identity_hash_;
  }

  void set_allocation_identity_hash(uint32_t hash) {
    allocation_identity_hash_ = hash;
  }

  Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); }

  void set_thread_task(Thread::TaskKind task) {
    state_ = ThreadTaskBit::update(task, state_);
  }

  bool is_continuation_sample() const {
    return ContinuationSampleBit::decode(state_);
  }

  void SetContinuation(Sample* next) {
    ASSERT(!is_continuation_sample());
    ASSERT(next_ == nullptr);
    state_ = ContinuationSampleBit::update(true, state_);
    next_ = next;
  }

  Sample* continuation_sample() const { return next_; }

  intptr_t allocation_cid() const {
    ASSERT(is_allocation_sample());
    return metadata();
  }

  void set_head_sample(bool head_sample) {
    state_ = HeadSampleBit::update(head_sample, state_);
  }

  bool head_sample() const { return HeadSampleBit::decode(state_); }

  intptr_t metadata() const { return MetadataBits::decode(state_); }
  void set_metadata(intptr_t metadata) {
    state_ = MetadataBits::update(metadata, state_);
  }

  void SetAllocationCid(intptr_t cid) {
    set_is_allocation_sample(true);
    set_metadata(cid);
  }

  static constexpr int kPCArraySizeInWords = 32;
  uword* GetPCArray() { return &pc_array_[0]; }

  static constexpr int kStackBufferSizeInWords = 2;
  uword* GetStackBuffer() { return &stack_buffer_[0]; }

 private:
  int64_t timestamp_;
  Dart_Port port_;
  ThreadId tid_;
  uword stack_buffer_[kStackBufferSizeInWords];
  uword pc_array_[kPCArraySizeInWords];
  uword vm_tag_;
  uword user_tag_;
  uint32_t state_;
  Sample* next_;
  uint32_t allocation_identity_hash_;

  using HeadSampleBit = BitField<decltype(state_), bool, 0, 1>;
  using LeafFrameIsDart =
      BitField<decltype(state_), bool, HeadSampleBit::kNextBit, 1>;
  using IgnoreBit =
      BitField<decltype(state_), bool, LeafFrameIsDart::kNextBit, 1>;
  using ExitFrameBit = BitField<uint32_t, bool, IgnoreBit::kNextBit, 1>;
  using MissingFrameInsertedBit =
      BitField<decltype(state_), bool, ExitFrameBit::kNextBit, 1>;
  using TruncatedTraceBit =
      BitField<decltype(state_), bool, MissingFrameInsertedBit::kNextBit, 1>;
  using ClassAllocationSampleBit =
      BitField<decltype(state_), bool, TruncatedTraceBit::kNextBit, 1>;
  using ContinuationSampleBit =
      BitField<decltype(state_), bool, ClassAllocationSampleBit::kNextBit, 1>;
  using ThreadTaskBit = BitField<decltype(state_),
                                 Thread::TaskKind,
                                 ContinuationSampleBit::kNextBit,
                                 4>;
  using MetadataBits = BitField<decltype(state_),
                                intptr_t,
                                ThreadTaskBit::kNextBit,
                                UntaggedObject::kClassIdTagSize>;

  DISALLOW_COPY_AND_ASSIGN(Sample);
};

class AbstractCode {
 public:
  explicit AbstractCode(ObjectPtr code) : code_(Object::Handle(code)) {
    ASSERT(code_.IsNull() || code_.IsCode());
  }

  ObjectPtr ptr() const { return code_.ptr(); }
  const Object* handle() const { return &code_; }

  uword PayloadStart() const {
    ASSERT(code_.IsCode());
    return Code::Cast(code_).PayloadStart();
  }

  uword Size() const {
    ASSERT(code_.IsCode());
    return Code::Cast(code_).Size();
  }

  int64_t compile_timestamp() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).compile_timestamp();
    } else {
      return 0;
    }
  }

  const char* Name() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).Name();
    } else {
      return "";
    }
  }

  const char* QualifiedName() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).QualifiedName(
          NameFormattingParams(Object::kUserVisibleName));
    } else {
      return "";
    }
  }

  bool IsStubCode() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).IsStubCode();
    } else {
      return false;
    }
  }

  bool IsAllocationStubCode() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).IsAllocationStubCode();
    } else {
      return false;
    }
  }

  bool IsTypeTestStubCode() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).IsTypeTestStubCode();
    } else {
      return false;
    }
  }

  ObjectPtr owner() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).owner();
    } else {
      return Object::null();
    }
  }

  bool IsNull() const { return code_.IsNull(); }
  bool IsCode() const { return code_.IsCode(); }

  bool is_optimized() const {
    if (code_.IsCode()) {
      return Code::Cast(code_).is_optimized();
    } else {
      return false;
    }
  }

 private:
  const Object& code_;
};

// A Code object descriptor.
class CodeDescriptor : public ZoneAllocated {
 public:
  explicit CodeDescriptor(const AbstractCode code);

  uword Start() const;

  uword Size() const;

  int64_t CompileTimestamp() const;

  const AbstractCode code() const { return code_; }

  const char* Name() const { return code_.Name(); }

  bool Contains(uword pc) const {
    uword end = Start() + Size();
    return (pc >= Start()) && (pc < end);
  }

  static int Compare(CodeDescriptor* const* a, CodeDescriptor* const* b) {
    ASSERT(a != nullptr);
    ASSERT(b != nullptr);

    uword a_start = (*a)->Start();
    uword b_start = (*b)->Start();

    if (a_start < b_start) {
      return -1;
    } else if (a_start > b_start) {
      return 1;
    } else {
      return 0;
    }
  }

 private:
  const AbstractCode code_;

  DISALLOW_COPY_AND_ASSIGN(CodeDescriptor);
};

// Fast lookup of Dart code objects.
class CodeLookupTable : public ZoneAllocated {
 public:
  explicit CodeLookupTable(Thread* thread);

  intptr_t length() const { return code_objects_.length(); }

  const CodeDescriptor* At(intptr_t index) const {
    return code_objects_.At(index);
  }

  const CodeDescriptor* FindCode(uword pc) const;

 private:
  void Build(Thread* thread);

  void Add(const Object& code);

  // Code objects sorted by entry.
  ZoneGrowableArray<CodeDescriptor*> code_objects_;

  friend class CodeLookupTableBuilder;

  DISALLOW_COPY_AND_ASSIGN(CodeLookupTable);
};

class SampleBuffer {
 public:
  SampleBuffer() = default;
  virtual ~SampleBuffer() = default;

  virtual void Init(Sample* samples, intptr_t capacity) {
    ASSERT(samples != nullptr);
    ASSERT(capacity > 0);
    samples_ = samples;
    capacity_ = capacity;
  }

  void VisitSamples(SampleVisitor* visitor) {
    ASSERT(visitor != nullptr);
    const intptr_t length = capacity();
    for (intptr_t i = 0; i < length; i++) {
      Sample* sample = At(i);
      if (!sample->head_sample()) {
        // An inner sample in a chain of samples.
        continue;
      }
      if (sample->ignore_sample()) {
        // Bad sample.
        continue;
      }
      if (sample->port() != visitor->port()) {
        // Another isolate.
        continue;
      }
      if (sample->timestamp() == 0) {
        // Empty.
        continue;
      }
      if (sample->At(0) == 0) {
        // No frames.
        continue;
      }
      visitor->IncrementVisited();
      visitor->VisitSample(sample);
    }
  }

  virtual Sample* ReserveSample() = 0;
  virtual Sample* ReserveSampleAndLink(Sample* previous) = 0;

  Sample* At(intptr_t idx) const {
    ASSERT(idx >= 0);
    ASSERT(idx < capacity_);
    return &samples_[idx];
  }

  intptr_t capacity() const { return capacity_; }

  ProcessedSampleBuffer* BuildProcessedSampleBuffer(
      SampleFilter* filter,
      ProcessedSampleBuffer* buffer = nullptr);

 protected:
  Sample* Next(Sample* sample);

  ProcessedSample* BuildProcessedSample(Sample* sample,
                                        const CodeLookupTable& clt);

  Sample* samples_;
  intptr_t capacity_;

  DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
};

class SampleBlock : public SampleBuffer {
 public:
  // The default number of samples per block. Overridden by some tests.
  static constexpr intptr_t kSamplesPerBlock = 100;

  SampleBlock() = default;
  virtual ~SampleBlock() = default;

  // Returns the number of samples contained within this block.
  intptr_t capacity() const { return capacity_; }

  Isolate* owner() const { return owner_; }
  void set_owner(Isolate* isolate) { owner_ = isolate; }

  virtual Sample* ReserveSample();
  virtual Sample* ReserveSampleAndLink(Sample* previous);

  bool TryAllocateFree() {
    State expected = kFree;
    State desired = kSampling;
    std::memory_order success_order = std::memory_order_acquire;
    std::memory_order failure_order = std::memory_order_relaxed;
    return state_.compare_exchange_strong(expected, desired, success_order,
                                          failure_order);
  }
  bool TryAllocateCompleted() {
    State expected = kCompleted;
    State desired = kSampling;
    std::memory_order success_order = std::memory_order_acquire;
    std::memory_order failure_order = std::memory_order_relaxed;
    if (state_.compare_exchange_strong(expected, desired, success_order,
                                       failure_order)) {
      owner_ = nullptr;
      cursor_ = 0;
      return true;
    }
    return false;
  }
  void MarkCompleted() {
    ASSERT(state_.load(std::memory_order_relaxed) == kSampling);
    state_.store(kCompleted, std::memory_order_release);
  }
  bool TryAcquireStreaming(Isolate* isolate) {
    if (state_.load(std::memory_order_relaxed) != kCompleted) return false;
    if (owner_ != isolate) return false;

    State expected = kCompleted;
    State desired = kStreaming;
    std::memory_order success_order = std::memory_order_acquire;
    std::memory_order failure_order = std::memory_order_relaxed;
    return state_.compare_exchange_strong(expected, desired, success_order,
                                          failure_order);
  }
  void StreamingToCompleted() {
    ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
    state_.store(kCompleted, std::memory_order_relaxed);
  }
  void StreamingToFree() {
    ASSERT(state_.load(std::memory_order_relaxed) == kStreaming);
    owner_ = nullptr;
    cursor_ = 0;
    state_.store(kFree, std::memory_order_release);
  }
  void FreeCompleted() {
    State expected = kCompleted;
    State desired = kStreaming;
    std::memory_order success_order = std::memory_order_acquire;
    std::memory_order failure_order = std::memory_order_relaxed;
    if (state_.compare_exchange_strong(expected, desired, success_order,
                                       failure_order)) {
      StreamingToFree();
    }
  }

 protected:
  bool HasStreamableSamples(const GrowableObjectArray& tag_table, UserTag* tag);

  enum State : uint32_t {
    kFree,
    kSampling,  // I.e., writing.
    kCompleted,
    kStreaming,  // I.e., reading.
  };
  std::atomic<State> state_ = kFree;
  RelaxedAtomic<uint32_t> cursor_ = 0;
  Isolate* owner_ = nullptr;

 private:
  friend class SampleBlockListProcessor;
  friend class SampleBlockBuffer;

  DISALLOW_COPY_AND_ASSIGN(SampleBlock);
};

class SampleBlockBuffer {
 public:
  static constexpr intptr_t kDefaultBlockCount = 600;

  // Creates a SampleBlockBuffer with a predetermined number of blocks.
  //
  // Defaults to kDefaultBlockCount blocks. Block size is fixed to
  // SampleBlock::kSamplesPerBlock samples per block, except for in tests.
  explicit SampleBlockBuffer(
      intptr_t blocks = kDefaultBlockCount,
      intptr_t samples_per_block = SampleBlock::kSamplesPerBlock);

  virtual ~SampleBlockBuffer();

  void VisitSamples(SampleVisitor* visitor) {
    ASSERT(visitor != nullptr);
    for (intptr_t i = 0; i < capacity_; ++i) {
      blocks_[i].VisitSamples(visitor);
    }
  }

  void FreeCompletedBlocks();

  // Reserves a sample for a CPU profile.
  //
  // Returns nullptr when a sample can't be reserved.
  Sample* ReserveCPUSample(Isolate* isolate);

  // Reserves a sample for a Dart object allocation profile.
  //
  // Returns nullptr when a sample can't be reserved.
  Sample* ReserveAllocationSample(Isolate* isolate);

  intptr_t Size() const { return memory_->size(); }

  ProcessedSampleBuffer* BuildProcessedSampleBuffer(
      Isolate* isolate,
      SampleFilter* filter,
      ProcessedSampleBuffer* buffer = nullptr);

 private:
  Sample* ReserveSampleImpl(Isolate* isolate, bool allocation_sample);

  // Returns nullptr if there are no available blocks.
  SampleBlock* ReserveSampleBlock();

  // Sample block management.
  RelaxedAtomic<int> cursor_;
  SampleBlock* blocks_;
  intptr_t capacity_;

  // Sample buffer management.
  VirtualMemory* memory_;
  Sample* sample_buffer_;

  friend class Isolate;
  DISALLOW_COPY_AND_ASSIGN(SampleBlockBuffer);
};

intptr_t Profiler::Size() {
  intptr_t size = 0;
  if (sample_block_buffer_ != nullptr) {
    size += sample_block_buffer_->Size();
  }
  return size;
}

// A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have
// been merged into a logical sample. The raw data may have been processed to
// improve the quality of the stack trace.
class ProcessedSample : public ZoneAllocated {
 public:
  ProcessedSample();

  // Add |pc| to stack trace.
  void Add(uword pc) { pcs_.Add(pc); }

  // Insert |pc| at |index|.
  void InsertAt(intptr_t index, uword pc) { pcs_.InsertAt(index, pc); }

  // Number of pcs in stack trace.
  intptr_t length() const { return pcs_.length(); }

  // Get |pc| at |index|.
  uword At(intptr_t index) const {
    ASSERT(index >= 0);
    ASSERT(index < length());
    return pcs_[index];
  }

  // Timestamp sample was taken at.
  int64_t timestamp() const { return timestamp_; }
  void set_timestamp(int64_t timestamp) { timestamp_ = timestamp; }

  ThreadId tid() const { return tid_; }
  void set_tid(ThreadId tid) { tid_ = tid; }

  // The VM tag.
  uword vm_tag() const { return vm_tag_; }
  void set_vm_tag(uword tag) { vm_tag_ = tag; }

  // The user tag.
  uword user_tag() const { return user_tag_; }
  void set_user_tag(uword tag) { user_tag_ = tag; }

  // The class id if this is an allocation profile sample. -1 otherwise.
  intptr_t allocation_cid() const { return allocation_cid_; }
  void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; }

  // The identity hash code of the allocated object if this is an allocation
  // profile sample. -1 otherwise.
  uint32_t allocation_identity_hash() const {
    return allocation_identity_hash_;
  }
  void set_allocation_identity_hash(uint32_t hash) {
    allocation_identity_hash_ = hash;
  }

  bool IsAllocationSample() const { return allocation_cid_ > 0; }

  // Was the stack trace truncated?
  bool truncated() const { return truncated_; }
  void set_truncated(bool truncated) { truncated_ = truncated; }

  // Was the first frame in the stack trace executing?
  bool first_frame_executing() const { return first_frame_executing_; }
  void set_first_frame_executing(bool first_frame_executing) {
    first_frame_executing_ = first_frame_executing;
  }

 private:
  void FixupCaller(const CodeLookupTable& clt,
                   uword pc_marker,
                   uword* stack_buffer);

  void CheckForMissingDartFrame(const CodeLookupTable& clt,
                                const CodeDescriptor* code,
                                uword pc_marker,
                                uword* stack_buffer);

  ZoneGrowableArray<uword> pcs_;
  int64_t timestamp_;
  ThreadId tid_;
  uword vm_tag_;
  uword user_tag_;
  intptr_t allocation_cid_;
  uint32_t allocation_identity_hash_;
  bool truncated_;
  bool first_frame_executing_;

  friend class SampleBuffer;
  DISALLOW_COPY_AND_ASSIGN(ProcessedSample);
};

// A collection of |ProcessedSample|s.
class ProcessedSampleBuffer : public ZoneAllocated {
 public:
  ProcessedSampleBuffer();

  void Add(ProcessedSample* sample) { samples_.Add(sample); }

  intptr_t length() const { return samples_.length(); }

  ProcessedSample* At(intptr_t index) { return samples_.At(index); }

  const CodeLookupTable& code_lookup_table() const {
    return *code_lookup_table_;
  }

 private:
  ZoneGrowableArray<ProcessedSample*> samples_;
  CodeLookupTable* code_lookup_table_;

  DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer);
};

class SampleBlockProcessor : public AllStatic {
 public:
  static void Init();

  static void Startup();
  static void Cleanup();

 private:
  static constexpr intptr_t kMaxThreads = 4096;
  static bool initialized_;
  static bool shutdown_;
  static bool thread_running_;
  static ThreadJoinId processor_thread_id_;
  static Monitor* monitor_;

  static void ThreadMain(uword parameters);
};

}  // namespace dart

#endif  // RUNTIME_VM_PROFILER_H_
