// 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.

#include "platform/utils.h"

#include "vm/allocation.h"
#include "vm/atomic.h"
#include "vm/code_patcher.h"
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/profiler.h"
#include "vm/signal_handler.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"

namespace dart {


#if defined(USING_SIMULATOR) || defined(TARGET_OS_WINDOWS) || \
    defined(TARGET_OS_ANDROID)
  DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
#else
  DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
#endif
DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
DEFINE_FLAG(charp, profile_dir, NULL,
            "Enable writing profile data into specified directory.");
DEFINE_FLAG(int, profile_period, 1000,
            "Time between profiler samples in microseconds. Minimum 250.");
DEFINE_FLAG(int, profile_depth, 8,
            "Maximum number stack frames walked. Minimum 1. Maximum 128.");

bool Profiler::initialized_ = false;
SampleBuffer* Profiler::sample_buffer_ = NULL;

void Profiler::InitOnce() {
  const int kMinimumProfilePeriod = 250;
  const int kMinimumDepth = 1;
  const int kMaximumDepth = 128;
  // Place some sane restrictions on user controlled flags.
  if (FLAG_profile_period < kMinimumProfilePeriod) {
    FLAG_profile_period = kMinimumProfilePeriod;
  }
  if (FLAG_profile_depth < kMinimumDepth) {
    FLAG_profile_depth = kMinimumDepth;
  } else if (FLAG_profile_depth > kMaximumDepth) {
    FLAG_profile_depth = kMaximumDepth;
  }
  // We must always initialize the Sample, even when the profiler is disabled.
  Sample::InitOnce();
  if (!FLAG_profile) {
    return;
  }
  ASSERT(!initialized_);
  sample_buffer_ = new SampleBuffer();
  NativeSymbolResolver::InitOnce();
  ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
  ThreadInterrupter::Startup();
  initialized_ = true;
}


void Profiler::Shutdown() {
  if (!FLAG_profile) {
    return;
  }
  ASSERT(initialized_);
  ThreadInterrupter::Shutdown();
  NativeSymbolResolver::ShutdownOnce();
}


void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
  if (!FLAG_profile) {
    return;
  }
  ASSERT(isolate != NULL);
  ASSERT(sample_buffer_ != NULL);
  {
    MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
    SampleBuffer* sample_buffer = sample_buffer_;
    if (!shared_buffer) {
      sample_buffer = new SampleBuffer();
    }
    IsolateProfilerData* profiler_data =
        new IsolateProfilerData(sample_buffer, !shared_buffer);
    ASSERT(profiler_data != NULL);
    isolate->set_profiler_data(profiler_data);
    if (FLAG_trace_profiled_isolates) {
      OS::Print("Profiler Setup %p %s\n", isolate, isolate->name());
    }
  }
}


void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) {
  ASSERT(isolate != NULL);
  if (!FLAG_profile) {
    return;
  }
  // We do not have a current isolate.
  ASSERT(Isolate::Current() == NULL);
  {
    MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
    IsolateProfilerData* profiler_data = isolate->profiler_data();
    if (profiler_data == NULL) {
      // Already freed.
      return;
    }
    isolate->set_profiler_data(NULL);
    delete profiler_data;
    if (FLAG_trace_profiled_isolates) {
      OS::Print("Profiler Shutdown %p %s\n", isolate, isolate->name());
    }
  }
}


void Profiler::BeginExecution(Isolate* isolate) {
  if (isolate == NULL) {
    return;
  }
  if (!FLAG_profile) {
    return;
  }
  ASSERT(initialized_);
  IsolateProfilerData* profiler_data = isolate->profiler_data();
  if (profiler_data == NULL) {
    return;
  }
  ThreadInterrupter::Register(RecordSampleInterruptCallback, isolate);
}


void Profiler::EndExecution(Isolate* isolate) {
  if (isolate == NULL) {
    return;
  }
  if (!FLAG_profile) {
    return;
  }
  ASSERT(initialized_);
  ThreadInterrupter::Unregister();
}


void Profiler::RecordTickInterruptCallback(const InterruptedThreadState& state,
                                           void* data) {
  Isolate* isolate = reinterpret_cast<Isolate*>(data);
  if (isolate == NULL) {
    return;
  }
  IsolateProfilerData* profiler_data = isolate->profiler_data();
  if (profiler_data == NULL) {
    return;
  }
  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
  if (sample_buffer == NULL) {
    return;
  }
  Sample* sample = sample_buffer->ReserveSample();
  sample->Init(Sample::kIsolateSample, isolate, OS::GetCurrentTimeMicros(),
               state.tid);
}


void Profiler::RecordSampleInterruptCallback(
    const InterruptedThreadState& state,
    void* data) {
  Isolate* isolate = reinterpret_cast<Isolate*>(data);
  if (isolate == NULL) {
    return;
  }
  IsolateProfilerData* profiler_data = isolate->profiler_data();
  if (profiler_data == NULL) {
    return;
  }
  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
  if (sample_buffer == NULL) {
    return;
  }
  Sample* sample = sample_buffer->ReserveSample();
  sample->Init(Sample::kIsolateSample, isolate, OS::GetCurrentTimeMicros(),
               state.tid);
  uintptr_t stack_lower = 0;
  uintptr_t stack_upper = 0;
  isolate->GetStackBounds(&stack_lower, &stack_upper);
  if ((stack_lower == 0) || (stack_upper == 0)) {
    stack_lower = 0;
    stack_upper = 0;
  }
  ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
                                        state.pc, state.fp, state.sp);
  stackWalker.walk();
}


struct AddressEntry {
  uintptr_t pc;
  uintptr_t ticks;
};


// A region of code. Each region is a kind of code (Dart, Collected, or Native).
class CodeRegion : public ZoneAllocated {
 public:
  enum Kind {
    kDartCode,
    kCollectedCode,
    kNativeCode
  };

  CodeRegion(Kind kind, uintptr_t start, uintptr_t end) :
      kind_(kind),
      start_(start),
      end_(end),
      inclusive_ticks_(0),
      exclusive_ticks_(0),
      name_(NULL),
      address_table_(new ZoneGrowableArray<AddressEntry>()) {
  }

  ~CodeRegion() {
  }

  uintptr_t start() const { return start_; }
  void set_start(uintptr_t start) {
    start_ = start;
  }

  uintptr_t end() const { return end_; }
  void set_end(uintptr_t end) {
    end_ = end;
  }

  void AdjustExtent(uintptr_t start, uintptr_t end) {
    if (start < start_) {
      start_ = start;
    }
    if (end > end_) {
      end_ = end;
    }
  }

  bool contains(uintptr_t pc) const {
    return (pc >= start_) && (pc < end_);
  }

  intptr_t inclusive_ticks() const { return inclusive_ticks_; }
  void set_inclusive_ticks(intptr_t inclusive_ticks) {
    inclusive_ticks_ = inclusive_ticks;
  }

  intptr_t exclusive_ticks() const { return exclusive_ticks_; }
  void set_exclusive_ticks(intptr_t exclusive_ticks) {
    exclusive_ticks_ = exclusive_ticks;
  }

  const char* name() const { return name_; }
  void SetName(const char* name) {
    if (name == NULL) {
      name_ = NULL;
    }
    intptr_t len = strlen(name);
    name_ = Isolate::Current()->current_zone()->Alloc<const char>(len + 1);
    strncpy(const_cast<char*>(name_), name, len);
    const_cast<char*>(name_)[len] = '\0';
  }

  Kind kind() const { return kind_; }

  static const char* KindToCString(Kind kind) {
    switch (kind) {
      case kDartCode:
        return "Dart";
      case kCollectedCode:
        return "Collected";
      case kNativeCode:
        return "Native";
    }
    UNREACHABLE();
    return NULL;
  }

  void AddTick(bool exclusive) {
    if (exclusive) {
      exclusive_ticks_++;
    } else {
      inclusive_ticks_++;
    }
  }

  void DebugPrint() {
    printf("%s [%" Px ", %" Px ") %s\n", name_, start(), end(),
           KindToCString(kind_));
  }

  void AddTickAtAddress(uintptr_t pc) {
    const intptr_t length = address_table_->length();
    intptr_t i = 0;
    for (; i < length; i++) {
      AddressEntry& entry = (*address_table_)[i];
      if (entry.pc == pc) {
        entry.ticks++;
        return;
      }
      if (entry.pc > pc) {
        break;
      }
    }
    AddressEntry entry;
    entry.pc = pc;
    entry.ticks = 1;
    if (i < length) {
      // Insert at i.
      address_table_->InsertAt(i, entry);
    } else {
      // Add to end.
      address_table_->Add(entry);
    }
  }


  void PrintToJSONArray(JSONArray* events, bool full) {
    JSONObject obj(events);
    obj.AddProperty("type", "ProfileCode");
    obj.AddProperty("kind", KindToCString(kind()));
    obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
    obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
    if (kind() == kDartCode) {
      // Look up code in Dart heap.
      Code& code = Code::Handle(Code::LookupCode(start()));
      Function& func = Function::Handle();
      ASSERT(!code.IsNull());
      func ^= code.function();
      if (func.IsNull()) {
        if (name() == NULL) {
          GenerateAndSetSymbolName("Stub");
        }
        obj.AddPropertyF("start", "%" Px "", start());
        obj.AddPropertyF("end", "%" Px "", end());
        obj.AddProperty("name", name());
      } else {
        obj.AddProperty("code", code, !full);
      }
    } else if (kind() == kCollectedCode) {
      if (name() == NULL) {
        GenerateAndSetSymbolName("Collected");
      }
      obj.AddPropertyF("start", "%" Px "", start());
      obj.AddPropertyF("end", "%" Px "", end());
      obj.AddProperty("name", name());
    } else {
      ASSERT(kind() == kNativeCode);
      if (name() == NULL) {
        GenerateAndSetSymbolName("Native");
      }
      obj.AddPropertyF("start", "%" Px "", start());
      obj.AddPropertyF("end", "%" Px "", end());
      obj.AddProperty("name", name());
    }
    {
      JSONArray ticks(&obj, "ticks");
      for (intptr_t i = 0; i < address_table_->length(); i++) {
        const AddressEntry& entry = (*address_table_)[i];
        ticks.AddValueF("%" Px "", entry.pc);
        ticks.AddValueF("%" Pd "", entry.ticks);
      }
    }
  }

 private:
  void GenerateAndSetSymbolName(const char* prefix) {
    const intptr_t kBuffSize = 512;
    char buff[kBuffSize];
    OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")",
                prefix, start(), end());
    SetName(buff);
  }

  Kind kind_;
  uintptr_t start_;
  uintptr_t end_;
  intptr_t inclusive_ticks_;
  intptr_t exclusive_ticks_;
  const char* name_;
  ZoneGrowableArray<AddressEntry>* address_table_;

  DISALLOW_COPY_AND_ASSIGN(CodeRegion);
};


// All code regions. Code region tables are built on demand when a profile
// is requested (through the service or on isolate shutdown).
class ProfilerCodeRegionTable : public ValueObject {
 public:
  explicit ProfilerCodeRegionTable(Isolate* isolate) :
      heap_(isolate->heap()),
      code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) {
  }

  ~ProfilerCodeRegionTable() {
  }

  void AddTick(uintptr_t pc, bool exclusive, bool tick_address) {
    intptr_t index = FindIndex(pc);
    if (index < 0) {
      CodeRegion* code_region = CreateCodeRegion(pc);
      ASSERT(code_region != NULL);
      index = InsertCodeRegion(code_region);
    }
    ASSERT(index >= 0);
    ASSERT(index < code_region_table_->length());
    (*code_region_table_)[index]->AddTick(exclusive);
    if (tick_address) {
      (*code_region_table_)[index]->AddTickAtAddress(pc);
    }
  }

  intptr_t Length() const { return code_region_table_->length(); }

  CodeRegion* At(intptr_t idx) {
    return (*code_region_table_)[idx];
  }

 private:
  intptr_t FindIndex(uintptr_t pc) {
    const intptr_t length = code_region_table_->length();
    for (intptr_t i = 0; i < length; i++) {
      const CodeRegion* code_region = (*code_region_table_)[i];
      if (code_region->contains(pc)) {
        return i;
      }
    }
    return -1;
  }

  CodeRegion* CreateCodeRegion(uintptr_t pc) {
    Code& code = Code::Handle(Code::LookupCode(pc));
    if (!code.IsNull()) {
      return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(),
                            code.EntryPoint() + code.Size());
    }
    if (heap_->CodeContains(pc)) {
      const intptr_t kDartCodeAlignment = 0x10;
      const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
      return new CodeRegion(CodeRegion::kCollectedCode,
                            (pc & kDartCodeAlignmentMask),
                            (pc & kDartCodeAlignmentMask) + kDartCodeAlignment);
    }
    uintptr_t native_start = 0;
    char* native_name = NativeSymbolResolver::LookupSymbolName(pc,
                                                               &native_start);
    if (native_name == NULL) {
      return new CodeRegion(CodeRegion::kNativeCode, pc, pc + 1);
    }
    ASSERT(pc >= native_start);
    CodeRegion* code_region =
        new CodeRegion(CodeRegion::kNativeCode, native_start, pc + 1);
    code_region->SetName(native_name);
    free(native_name);
    return code_region;
  }

  intptr_t InsertCodeRegion(CodeRegion* code_region) {
    const intptr_t length = code_region_table_->length();
    const uintptr_t start = code_region->start();
    const uintptr_t end = code_region->end();
    intptr_t i = 0;
    for (; i < length; i++) {
      CodeRegion* region = (*code_region_table_)[i];
      if (region->contains(start) || region->contains(end - 1)) {
        // We should only see overlapping native code regions.
        ASSERT(region->kind() == CodeRegion::kNativeCode);
        // When code regions overlap, they should be of the same kind.
        ASSERT(region->kind() == code_region->kind());
        // Overlapping code region.
        region->AdjustExtent(start, end);
        return i;
      } else if (start >= region->end()) {
        // Insert here.
        break;
      }
    }
    if (i != length) {
      code_region_table_->InsertAt(i, code_region);
      return i;
    }
    code_region_table_->Add(code_region);
    return code_region_table_->length() - 1;
  }

  Heap* heap_;
  ZoneGrowableArray<CodeRegion*>* code_region_table_;
};


void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
                                 bool full) {
  ASSERT(isolate == Isolate::Current());
  // Disable profile interrupts while processing the buffer.
  EndExecution(isolate);
  MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
  IsolateProfilerData* profiler_data = isolate->profiler_data();
  if (profiler_data == NULL) {
    JSONObject error(stream);
    error.AddProperty("type", "Error");
    error.AddProperty("text", "Isolate does not have profiling enabled.");
    return;
  }
  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
  ASSERT(sample_buffer != NULL);
  {
    StackZone zone(isolate);
    {
      // Build code region table.
      ProfilerCodeRegionTable code_region_table(isolate);
      intptr_t samples =
          ProcessSamples(isolate, &code_region_table, sample_buffer);
      {
        // Serialize to JSON.
        JSONObject obj(stream);
        obj.AddProperty("type", "Profile");
        obj.AddProperty("samples", samples);
        JSONArray codes(&obj, "codes");
        for (intptr_t i = 0; i < code_region_table.Length(); i++) {
          CodeRegion* region = code_region_table.At(i);
          ASSERT(region != NULL);
          region->PrintToJSONArray(&codes, full);
        }
      }
    }
  }
  // Enable profile interrupts.
  BeginExecution(isolate);
}


intptr_t Profiler::ProcessSamples(Isolate* isolate,
                                  ProfilerCodeRegionTable* code_region_table,
                                  SampleBuffer* sample_buffer) {
  int64_t start = OS::GetCurrentTimeMillis();
  intptr_t samples = 0;
  Sample* sample = Sample::Allocate();
  for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
    sample_buffer->CopySample(i, sample);
    if (sample->isolate() != isolate) {
      continue;
    }
    if (sample->timestamp() == 0) {
      continue;
    }
    samples += ProcessSample(isolate, code_region_table, sample);
  }
  free(sample);
  int64_t end = OS::GetCurrentTimeMillis();
  if (FLAG_trace_profiled_isolates) {
    int64_t delta = end - start;
    OS::Print("Processed %" Pd " samples from %s in %" Pd64 " milliseconds.\n",
        samples,
        isolate->name(),
        delta);
  }
  return samples;
}


intptr_t Profiler::ProcessSample(Isolate* isolate,
                                 ProfilerCodeRegionTable* code_region_table,
                                Sample* sample) {
  if (sample->type() != Sample::kIsolateSample) {
    return 0;
  }
  if (sample->At(0) == 0) {
    // No frames in this sample.
    return 0;
  }
  // i points to the leaf (exclusive) PC sample. Do not tick the address.
  code_region_table->AddTick(sample->At(0), true, false);
  // Give all frames an inclusive tick and tick the address.
  for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
    if (sample->At(i) == 0) {
      break;
    }
    code_region_table->AddTick(sample->At(i), false, true);
  }
  return 1;
}


void Profiler::WriteProfile(Isolate* isolate) {
  if (isolate == NULL) {
    return;
  }
  if (!FLAG_profile) {
    return;
  }
  ASSERT(initialized_);
  if (FLAG_profile_dir == NULL) {
    return;
  }
  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
  if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) {
    // Embedder has not provided necessary callbacks.
    return;
  }
  // We will be looking up code objects within the isolate.
  ASSERT(Isolate::Current() == isolate);
  JSONStream stream(10 * MB);
  intptr_t pid = OS::ProcessId();
  PrintToJSONStream(isolate, &stream, true);
  const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json";
  intptr_t len = OS::SNPrint(NULL, 0, format,
                             FLAG_profile_dir, pid, isolate->main_port());
  char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
  OS::SNPrint(filename, len + 1, format,
              FLAG_profile_dir, pid, isolate->main_port());
  void* f = file_open(filename, true);
  if (f == NULL) {
    // Cannot write.
    return;
  }
  TextBuffer* buffer = stream.buffer();
  ASSERT(buffer != NULL);
  file_write(buffer->buf(), buffer->length(), f);
  file_close(f);
}


IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer,
                                         bool own_sample_buffer) {
  ASSERT(sample_buffer != NULL);
  sample_buffer_ = sample_buffer;
  own_sample_buffer_ = own_sample_buffer;
}


IsolateProfilerData::~IsolateProfilerData() {
  if (own_sample_buffer_) {
    delete sample_buffer_;
    sample_buffer_ = NULL;
    own_sample_buffer_ = false;
  }
}


intptr_t Sample::instance_size_ = 0;

void Sample::InitOnce() {
  ASSERT(FLAG_profile_depth >= 1);
  instance_size_ =
     sizeof(Sample) + (sizeof(intptr_t) * FLAG_profile_depth);  // NOLINT.
}


uintptr_t Sample::At(intptr_t i) const {
  ASSERT(i >= 0);
  ASSERT(i < FLAG_profile_depth);
  return pcs_[i];
}


void Sample::SetAt(intptr_t i, uintptr_t pc) {
  ASSERT(i >= 0);
  ASSERT(i < FLAG_profile_depth);
  pcs_[i] = pc;
}


void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
                  ThreadId tid) {
  timestamp_ = timestamp;
  tid_ = tid;
  isolate_ = isolate;
  type_ = type;
  for (int i = 0; i < FLAG_profile_depth; i++) {
    pcs_[i] = 0;
  }
}


void Sample::CopyInto(Sample* dst) const {
  ASSERT(dst != NULL);
  dst->timestamp_ = timestamp_;
  dst->tid_ = tid_;
  dst->isolate_ = isolate_;
  dst->type_ = type_;
  for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
    dst->pcs_[i] = pcs_[i];
  }
}


Sample* Sample::Allocate() {
  return reinterpret_cast<Sample*>(malloc(instance_size()));
}


SampleBuffer::SampleBuffer(intptr_t capacity) {
  capacity_ = capacity;
  samples_ = reinterpret_cast<Sample*>(
      calloc(capacity, Sample::instance_size()));
  cursor_ = 0;
}


SampleBuffer::~SampleBuffer() {
  if (samples_ != NULL) {
    free(samples_);
    samples_ = NULL;
    cursor_ = 0;
    capacity_ = 0;
  }
}


Sample* SampleBuffer::ReserveSample() {
  ASSERT(samples_ != NULL);
  uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
  // Map back into sample buffer range.
  cursor = cursor % capacity_;
  return At(cursor);
}


void SampleBuffer::CopySample(intptr_t i, Sample* sample) const {
  At(i)->CopyInto(sample);
}


Sample* SampleBuffer::At(intptr_t idx) const {
  ASSERT(idx >= 0);
  ASSERT(idx < capacity_);
  intptr_t offset = idx * Sample::instance_size();
  uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
  return reinterpret_cast<Sample*>(samples + offset);
}


ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample,
                                                     uintptr_t stack_lower,
                                                     uintptr_t stack_upper,
                                                     uintptr_t pc,
                                                     uintptr_t fp,
                                                     uintptr_t sp) :
    sample_(sample),
    stack_lower_(stack_lower),
    stack_upper_(stack_upper),
    original_pc_(pc),
    original_fp_(fp),
    original_sp_(sp),
    lower_bound_(stack_lower) {
  ASSERT(sample_ != NULL);
}


// Notes on stack frame walking:
//
// The sampling profiler will collect up to Sample::kNumStackFrames stack frames
// The stack frame walking code uses the frame pointer to traverse the stack.
// If the VM is compiled without frame pointers (which is the default on
// recent GCC versions with optimizing enabled) the stack walking code may
// fail (sometimes leading to a crash).
//

int ProfilerSampleStackWalker::walk() {
  const intptr_t kMaxStep = 0x1000;  // 4K.
  const bool kWalkStack = true;  // Walk the stack.
  // Always store the exclusive PC.
  sample_->SetAt(0, original_pc_);
  if (!kWalkStack) {
    // Not walking the stack, only took exclusive sample.
    return 1;
  }
  uword* pc = reinterpret_cast<uword*>(original_pc_);
  uword* fp = reinterpret_cast<uword*>(original_fp_);
  uword* previous_fp = fp;
  if (original_sp_ > original_fp_) {
    // Stack pointer should not be above frame pointer.
    return 1;
  }
  intptr_t gap = original_fp_ - original_sp_;
  if (gap >= kMaxStep) {
    // Gap between frame pointer and stack pointer is
    // too large.
    return 1;
  }
  if (original_sp_ < lower_bound_) {
    // The stack pointer gives us a better lower bound than
    // the isolates stack limit.
    lower_bound_ = original_sp_;
  }
  int i = 0;
  for (; i < FLAG_profile_depth; i++) {
    sample_->SetAt(i, reinterpret_cast<uintptr_t>(pc));
    if (!ValidFramePointer(fp)) {
      return i + 1;
    }
    pc = CallerPC(fp);
    previous_fp = fp;
    fp = CallerFP(fp);
    intptr_t step = fp - previous_fp;
    if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) {
      // Frame pointer step is too large.
      // Frame pointer did not move to a higher address.
      // Frame pointer is outside of isolate stack bounds.
      return i + 1;
    }
    // Move the lower bound up.
    lower_bound_ = reinterpret_cast<uintptr_t>(fp);
  }
  return i;
}


uword* ProfilerSampleStackWalker::CallerPC(uword* fp) {
  ASSERT(fp != NULL);
  return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp));
}


uword* ProfilerSampleStackWalker::CallerFP(uword* fp) {
  ASSERT(fp != NULL);
  return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp));
}


bool ProfilerSampleStackWalker::ValidFramePointer(uword* fp) {
  if (fp == NULL) {
    return false;
  }
  uintptr_t cursor = reinterpret_cast<uintptr_t>(fp);
  cursor += sizeof(fp);
  bool r = cursor >= lower_bound_ && cursor < stack_upper_;
  return r;
}


}  // namespace dart
