// 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/malloc_hooks.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 AllocationSampleBuffer;
class SampleBlock;
class ProfileTrieNode;

#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_register_check)                                        \
  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(failure_native_allocation_sample)                                          \
  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 InitAllocationSampleBuffer();
  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 AllocationSampleBuffer* allocation_sample_buffer() {
    return allocation_sample_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);
  static Sample* SampleNativeAllocation(intptr_t skip_count,
                                        uword address,
                                        uintptr_t allocation_size);

  // 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 Windows and Fuchsia 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();

 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 AllocationSampleBuffer* allocation_sample_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)
      : port_(port),
        thread_task_mask_(thread_task_mask),
        time_origin_micros_(time_origin_micros),
        time_extent_micros_(time_extent_micros) {
    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);

  static const intptr_t kNoTaskFilter = -1;

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

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;
#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
    native_allocation_address_ = 0;
    native_allocation_size_bytes_ = 0;
    next_free_ = NULL;
#endif
    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);
      char* native_symbol_name =
          NativeSymbolResolver::LookupSymbolName(pc, &start);
      if (native_symbol_name == NULL) {
        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;
  }

#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
  uword native_allocation_address() const { return native_allocation_address_; }
  void set_native_allocation_address(uword address) {
    native_allocation_address_ = address;
  }

  uintptr_t native_allocation_size_bytes() const {
    return native_allocation_size_bytes_;
  }
  void set_native_allocation_size_bytes(uintptr_t size) {
    native_allocation_size_bytes_ = size;
  }

  Sample* next_free() const { return next_free_; }
  void set_next_free(Sample* next_free) { next_free_ = next_free; }
#else
  uword native_allocation_address() const { return 0; }
  void set_native_allocation_address(uword address) { UNREACHABLE(); }

  uintptr_t native_allocation_size_bytes() const { return 0; }
  void set_native_allocation_size_bytes(uintptr_t size) { UNREACHABLE(); }

  Sample* next_free() const { return nullptr; }
  void set_next_free(Sample* next_free) { UNREACHABLE(); }
#endif  // defined(DART_USE_TCMALLOC) && defined(DEBUG)

  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:
  enum StateBits {
    kHeadSampleBit = 0,
    kLeafFrameIsDartBit = 1,
    kIgnoreBit = 2,
    kExitFrameBit = 3,
    kMissingFrameInsertedBit = 4,
    kTruncatedTraceBit = 5,
    kClassAllocationSampleBit = 6,
    kContinuationSampleBit = 7,
    kThreadTaskBit = 8,  // 6 bits.
    kMetadataBit = 14,   // 16 bits.
    kNextFreeBit = 30,
  };
  class HeadSampleBit : public BitField<uint32_t, bool, kHeadSampleBit, 1> {};
  class LeafFrameIsDart
      : public BitField<uint32_t, bool, kLeafFrameIsDartBit, 1> {};
  class IgnoreBit : public BitField<uint32_t, bool, kIgnoreBit, 1> {};
  class ExitFrameBit : public BitField<uint32_t, bool, kExitFrameBit, 1> {};
  class MissingFrameInsertedBit
      : public BitField<uint32_t, bool, kMissingFrameInsertedBit, 1> {};
  class TruncatedTraceBit
      : public BitField<uint32_t, bool, kTruncatedTraceBit, 1> {};
  class ClassAllocationSampleBit
      : public BitField<uint32_t, bool, kClassAllocationSampleBit, 1> {};
  class ContinuationSampleBit
      : public BitField<uint32_t, bool, kContinuationSampleBit, 1> {};
  class ThreadTaskBit
      : public BitField<uint32_t, Thread::TaskKind, kThreadTaskBit, 6> {};
  class MetadataBits : public BitField<uint32_t, intptr_t, kMetadataBit, 16> {};

  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_;

#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
  uword native_allocation_address_;
  uintptr_t native_allocation_size_bytes_;
  Sample* next_free_;
#endif

  DISALLOW_COPY_AND_ASSIGN(Sample);
};

class NativeAllocationSampleFilter : public SampleFilter {
 public:
  NativeAllocationSampleFilter(int64_t time_origin_micros,
                               int64_t time_extent_micros)
      : SampleFilter(ILLEGAL_PORT,
                     SampleFilter::kNoTaskFilter,
                     time_origin_micros,
                     time_extent_micros) {}

  bool FilterSample(Sample* sample) {
    // If the sample is an allocation sample, we need to check that the
    // memory at the address hasn't been freed, and if the address associated
    // with the allocation has been freed and then reissued.
    void* alloc_address =
        reinterpret_cast<void*>(sample->native_allocation_address());
    ASSERT(alloc_address != NULL);
    Sample* recorded_sample = MallocHooks::GetSample(alloc_address);
    return (sample == recorded_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 != NULL);
    ASSERT(b != NULL);

    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);
};

// Interface for a class that can create a ProcessedSampleBuffer.
class ProcessedSampleBufferBuilder {
 public:
  virtual ~ProcessedSampleBufferBuilder() = default;
  virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
      SampleFilter* filter,
      ProcessedSampleBuffer* buffer = nullptr) = 0;
};

class SampleBuffer : public ProcessedSampleBufferBuilder {
 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 != NULL);
    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_; }

  virtual 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 const intptr_t kSamplesPerBlock = 1000;

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

  void Clear() {
    allocation_block_ = false;
    cursor_ = 0;
    full_ = false;
    evictable_ = false;
    next_free_ = nullptr;
  }

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

  // Specify whether or not this block is used for assigning allocation
  // samples.
  void set_is_allocation_block(bool is_allocation_block) {
    allocation_block_ = is_allocation_block;
  }

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

  // Manually marks the block as full so it can be processed and added back to
  // the pool of available blocks.
  void release_block() { full_.store(true); }

  // When true, this sample block is considered complete and will no longer be
  // used to assign new Samples. This block is **not** available for
  // re-allocation simply because it's full. It must be processed by
  // SampleBlockBuffer::ProcessCompletedBlocks before it can be considered
  // evictable and available for re-allocation.
  bool is_full() const { return full_.load(); }

  // When true, this sample block is available for re-allocation.
  bool evictable() const { return evictable_.load(); }

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

 protected:
  Isolate* owner_ = nullptr;
  bool allocation_block_ = false;

  intptr_t index_;
  RelaxedAtomic<int> cursor_ = 0;
  RelaxedAtomic<bool> full_ = false;
  RelaxedAtomic<bool> evictable_ = false;

  SampleBlock* next_free_ = nullptr;

 private:
  friend class SampleBlockBuffer;

  DISALLOW_COPY_AND_ASSIGN(SampleBlock);
};

class SampleBlockBuffer : public ProcessedSampleBufferBuilder {
 public:
  static const intptr_t kDefaultBlockCount = 60;

  // 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 != NULL);
    for (intptr_t i = 0; i < cursor_.load(); ++i) {
      (&blocks_[i])->VisitSamples(visitor);
    }
  }

  // Returns true when there is at least a single block that needs to be
  // processed.
  //
  // NOTE: this should only be called from the interrupt handler as
  // invocation will have the side effect of clearing the underlying flag.
  bool process_blocks() { return can_process_block_.exchange(false); }

  // Iterates over the blocks in the buffer and processes blocks marked as
  // full. Processing consists of sending a service event with the samples from
  // completed, unprocessed blocks and marking these blocks are evictable
  // (i.e., safe to be re-allocated and re-used).
  void ProcessCompletedBlocks();

  // 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(); }

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

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

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

  void FreeBlock(SampleBlock* block) {
    ASSERT(block->next_free_ == nullptr);
    MutexLocker ml(&free_block_lock_);
    if (free_list_head_ == nullptr) {
      free_list_head_ = block;
      free_list_tail_ = block;
      return;
    }
    free_list_tail_->next_free_ = block;
    free_list_tail_ = block;
  }

  SampleBlock* GetFreeBlock() {
    MutexLocker ml(&free_block_lock_);
    if (free_list_head_ == nullptr) {
      return nullptr;
    }
    SampleBlock* block = free_list_head_;
    free_list_head_ = block->next_free_;
    if (free_list_head_ == nullptr) {
      free_list_tail_ = nullptr;
    }
    block->next_free_ = nullptr;
    return block;
  }

  Mutex free_block_lock_;
  RelaxedAtomic<bool> can_process_block_ = false;

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

  // Sample buffer management.
  VirtualMemory* memory_;
  Sample* sample_buffer_;
  DISALLOW_COPY_AND_ASSIGN(SampleBlockBuffer);
};

class AllocationSampleBuffer : public SampleBuffer {
 public:
  explicit AllocationSampleBuffer(intptr_t capacity = 60000);
  virtual ~AllocationSampleBuffer();

  virtual Sample* ReserveSample();
  virtual Sample* ReserveSampleAndLink(Sample* previous);
  void FreeAllocationSample(Sample* sample);

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

 private:
  intptr_t ReserveSampleSlotLocked();

  Mutex mutex_;
  Sample* free_sample_list_;
  VirtualMemory* memory_;
  RelaxedAtomic<int> cursor_ = 0;
  DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer);
};

intptr_t Profiler::Size() {
  intptr_t size = 0;
  if (sample_block_buffer_ != nullptr) {
    size += sample_block_buffer_->Size();
  }
  if (allocation_sample_buffer_ != nullptr) {
    size += allocation_sample_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; }

  bool is_native_allocation_sample() const {
    return native_allocation_size_bytes_ != 0;
  }

  uintptr_t native_allocation_size_bytes() const {
    return native_allocation_size_bytes_;
  }
  void set_native_allocation_size_bytes(uintptr_t allocation_size) {
    native_allocation_size_bytes_ = allocation_size;
  }

  // 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;
  }

  ProfileTrieNode* timeline_code_trie() const { return timeline_code_trie_; }
  void set_timeline_code_trie(ProfileTrieNode* trie) {
    ASSERT(timeline_code_trie_ == NULL);
    timeline_code_trie_ = trie;
  }

  ProfileTrieNode* timeline_function_trie() const {
    return timeline_function_trie_;
  }
  void set_timeline_function_trie(ProfileTrieNode* trie) {
    ASSERT(timeline_function_trie_ == NULL);
    timeline_function_trie_ = trie;
  }

 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_;
  uword native_allocation_address_;
  uintptr_t native_allocation_size_bytes_;
  ProfileTrieNode* timeline_code_trie_;
  ProfileTrieNode* timeline_function_trie_;

  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);
};

}  // namespace dart

#endif  // RUNTIME_VM_PROFILER_H_
