// 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 SampleBuffer;
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)

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 SampleBuffer* sample_buffer() { return sample_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);
  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, uintptr_t pc);
  static RelaxedAtomic<bool> initialized_;

  static SampleBuffer* sample_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;

  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:
  void Init(Dart_Port port, int64_t timestamp, ThreadId tid) {
    Clear();
    timestamp_ = timestamp;
    tid_ = tid;
    port_ = port;
  }

  Dart_Port port() const { return port_; }

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

  void Clear() {
    port_ = ILLEGAL_PORT;
    pc_marker_ = 0;
    for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) {
      stack_buffer_[i] = 0;
    }
    vm_tag_ = VMTag::kInvalidTagId;
    user_tag_ = UserTags::kDefaultUserTag;
    lr_ = 0;
    metadata_ = 0;
    state_ = 0;
    native_allocation_address_ = 0;
    native_allocation_size_bytes_ = 0;
    continuation_index_ = -1;
    next_free_ = NULL;
    uword* pcs = GetPCArray();
    for (intptr_t i = 0; i < pcs_length_; i++) {
      pcs[i] = 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 < pcs_length_);
    uword* pcs = GetPCArray();
    return pcs[i];
  }

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

  void DumpStackTrace() {
    for (intptr_t i = 0; i < pcs_length_; ++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; }

  uword pc_marker() const { return pc_marker_; }

  void set_pc_marker(uword pc_marker) { pc_marker_ = pc_marker; }

  uword lr() const { return lr_; }

  void set_lr(uword link_register) { lr_ = link_register; }

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

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

  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 SetContinuationIndex(intptr_t index) {
    ASSERT(!is_continuation_sample());
    ASSERT(continuation_index_ == -1);
    state_ = ContinuationSampleBit::update(true, state_);
    continuation_index_ = index;
    ASSERT(is_continuation_sample());
  }

  intptr_t continuation_index() const {
    ASSERT(is_continuation_sample());
    return continuation_index_;
  }

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

  void set_metadata(intptr_t metadata) { metadata_ = metadata; }

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

  static void Init();

  static intptr_t instance_size() { return instance_size_; }

  uword* GetPCArray() const;

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

 private:
  static intptr_t instance_size_;
  static intptr_t pcs_length_;
  enum StateBits {
    kHeadSampleBit = 0,
    kLeafFrameIsDartBit = 1,
    kIgnoreBit = 2,
    kExitFrameBit = 3,
    kMissingFrameInsertedBit = 4,
    kTruncatedTraceBit = 5,
    kClassAllocationSampleBit = 6,
    kContinuationSampleBit = 7,
    kThreadTaskBit = 8,  // 6 bits.
    kNextFreeBit = 14,
  };
  class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {};
  class LeafFrameIsDart : public BitField<uword, bool, kLeafFrameIsDartBit, 1> {
  };
  class IgnoreBit : public BitField<uword, bool, kIgnoreBit, 1> {};
  class ExitFrameBit : public BitField<uword, bool, kExitFrameBit, 1> {};
  class MissingFrameInsertedBit
      : public BitField<uword, bool, kMissingFrameInsertedBit, 1> {};
  class TruncatedTraceBit
      : public BitField<uword, bool, kTruncatedTraceBit, 1> {};
  class ClassAllocationSampleBit
      : public BitField<uword, bool, kClassAllocationSampleBit, 1> {};
  class ContinuationSampleBit
      : public BitField<uword, bool, kContinuationSampleBit, 1> {};
  class ThreadTaskBit
      : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 6> {};

  int64_t timestamp_;
  ThreadId tid_;
  Dart_Port port_;
  uword pc_marker_;
  uword stack_buffer_[kStackBufferSizeInWords];
  uword vm_tag_;
  uword user_tag_;
  uword metadata_;
  uword lr_;
  uword state_;
  uword native_allocation_address_;
  uintptr_t native_allocation_size_bytes_;
  intptr_t continuation_index_;
  Sample* next_free_;

  /* There are a variable number of words that follow, the words hold the
   * sampled pc values. Access via GetPCArray() */
  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 raw() const { return code_.raw(); }
  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);
};

// Ring buffer of Samples that is (usually) shared by many isolates.
class SampleBuffer {
 public:
  // Up to 1 minute @ 1000Hz, less if samples are deep.
  static const intptr_t kDefaultBufferCapacity = 60000;

  explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
  virtual ~SampleBuffer();

  intptr_t capacity() const { return capacity_; }

  Sample* At(intptr_t idx) const;
  intptr_t ReserveSampleSlot();
  virtual Sample* ReserveSample();
  virtual Sample* ReserveSampleAndLink(Sample* previous);

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

  ProcessedSampleBuffer* BuildProcessedSampleBuffer(SampleFilter* filter);

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

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

  VirtualMemory* memory_;
  Sample* samples_;
  intptr_t capacity_;
  RelaxedAtomic<uintptr_t> cursor_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
};

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

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

 private:
  Mutex mutex_;
  Sample* free_sample_list_;

  DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer);
};

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

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