// Copyright (c) 2012, 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 "vm/stack_frame.h"

#include "platform/memory_sanitizer.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/deopt_instructions.h"
#include "vm/heap/become.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
#include "vm/raw_object.h"
#include "vm/reusable_handles.h"
#include "vm/scopes.h"
#include "vm/stub_code.h"
#include "vm/visitor.h"

namespace dart {

DECLARE_FLAG(bool, enable_interpreter);

const FrameLayout invalid_frame_layout = {
    /*.first_object_from_fp = */ -1,
    /*.last_fixed_object_from_fp = */ -1,
    /*.param_end_from_fp = */ -1,
    /*.first_local_from_fp = */ -1,
    /*.dart_fixed_frame_size = */ -1,
    /*.saved_caller_pp_from_fp = */ -1,
    /*.code_from_fp = */ -1,
};

const FrameLayout default_frame_layout = {
    /*.first_object_from_fp = */ kFirstObjectSlotFromFp,
    /*.last_fixed_object_from_fp = */ kLastFixedObjectSlotFromFp,
    /*.param_end_from_fp = */ kParamEndSlotFromFp,
    /*.first_local_from_fp = */ kFirstLocalSlotFromFp,
    /*.dart_fixed_frame_size = */ kDartFrameFixedSize,
    /*.saved_caller_pp_from_fp = */ kSavedCallerPpSlotFromFp,
    /*.code_from_fp = */ kPcMarkerSlotFromFp,
};

FrameLayout compiler_frame_layout = invalid_frame_layout;
FrameLayout runtime_frame_layout = invalid_frame_layout;

int FrameLayout::FrameSlotForVariable(const LocalVariable* variable) const {
  ASSERT(!variable->is_captured());
  return this->FrameSlotForVariableIndex(variable->index().value());
}

int FrameLayout::FrameSlotForVariableIndex(int variable_index) const {
  // Variable indices are:
  //    [1, 2, ..., M] for the M parameters.
  //    [0, -1, -2, ... -(N-1)] for the N [LocalVariable]s
  // See (runtime/vm/scopes.h)
  return variable_index <= 0 ? (variable_index + first_local_from_fp)
                             : (variable_index + param_end_from_fp);
}

void FrameLayout::Init() {
  compiler_frame_layout = default_frame_layout;
  runtime_frame_layout = default_frame_layout;
}

bool StackFrame::IsStubFrame() const {
  if (is_interpreted()) {
    return false;
  }
  ASSERT(!(IsEntryFrame() || IsExitFrame()));
#if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA)
  // On Windows and Fuchsia, the profiler calls this from a separate thread
  // where Thread::Current() is NULL, so we cannot create a NoSafepointScope.
  NoSafepointScope no_safepoint;
#endif
  RawCode* code = GetCodeObject();
  ASSERT(code != Object::null());
  const intptr_t cid = code->ptr()->owner_->GetClassId();
  ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
  return cid == kNullCid || cid == kClassCid;
}

const char* StackFrame::ToCString() const {
  ASSERT(thread_ == Thread::Current());
  Zone* zone = Thread::Current()->zone();
  if (IsDartFrame()) {
    if (is_interpreted()) {
      const Bytecode& bytecode = Bytecode::Handle(zone, LookupDartBytecode());
      ASSERT(!bytecode.IsNull());
      const Function& function = Function::Handle(zone, bytecode.function());
      ASSERT(!function.IsNull());
      return zone->PrintToString(
          "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") bytecode %s ]",
          GetName(), sp(), fp(), pc(), function.ToFullyQualifiedCString());
    }
    const Code& code = Code::Handle(zone, LookupDartCode());
    ASSERT(!code.IsNull());
    const Object& owner = Object::Handle(zone, code.owner());
    ASSERT(!owner.IsNull());
    if (owner.IsFunction()) {
      const char* opt = code.is_optimized() ? "*" : "";
      const Function& function = Function::Cast(owner);
      return zone->PrintToString(
          "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s%s ]", GetName(),
          sp(), fp(), pc(), opt, function.ToFullyQualifiedCString());
    } else {
      return zone->PrintToString(
          "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", GetName(),
          sp(), fp(), pc(), owner.ToCString());
    }
  } else {
    return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
                               ")]",
                               GetName(), sp(), fp(), pc());
  }
}

void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  // Visit pc marker and saved pool pointer, or, for interpreted frame, code
  // object and function object.
  RawObject** last_fixed =
      reinterpret_cast<RawObject**>(fp()) +
      (is_interpreted() ? kKBCLastFixedObjectSlotFromFp
                        : runtime_frame_layout.first_object_from_fp);
  RawObject** first_fixed =
      reinterpret_cast<RawObject**>(fp()) +
      (is_interpreted() ? kKBCFirstObjectSlotFromFp
                        : runtime_frame_layout.last_fixed_object_from_fp);
#if !defined(TARGET_ARCH_DBC)
  if (first_fixed <= last_fixed) {
    visitor->VisitPointers(first_fixed, last_fixed);
  } else {
    ASSERT(runtime_frame_layout.first_object_from_fp ==
           runtime_frame_layout.first_local_from_fp);
  }
#else
  ASSERT(last_fixed <= first_fixed);
  visitor->VisitPointers(last_fixed, first_fixed);
#endif
}

void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  // Visit objects between SP and (FP - callee_save_area).
#if !defined(TARGET_ARCH_DBC)
  RawObject** first = is_interpreted() ? reinterpret_cast<RawObject**>(fp()) +
                                             kKBCSavedArgDescSlotFromEntryFp
                                       : reinterpret_cast<RawObject**>(sp());
  RawObject** last = is_interpreted() ? reinterpret_cast<RawObject**>(sp())
                                      : reinterpret_cast<RawObject**>(fp()) +
                                            kExitLinkSlotFromEntryFp - 1;
  // There may not be any pointer to visit; in this case, first > last.
  visitor->VisitPointers(first, last);
#else
  // On DBC stack is growing upwards which implies fp() <= sp().
  RawObject** first = reinterpret_cast<RawObject**>(fp());
  RawObject** last = reinterpret_cast<RawObject**>(sp());
  ASSERT(first <= last);
  visitor->VisitPointers(first, last);
#endif
}

void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  // NOTE: This code runs while GC is in progress and runs within
  // a NoHandleScope block. Hence it is not ok to use regular Zone or
  // Scope handles. We use direct stack handles, the raw pointers in
  // these handles are not traversed. The use of handles is mainly to
  // be able to reuse the handle based code and avoid having to add
  // helper functions to the raw object interface.
  NoSafepointScope no_safepoint;
  RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
      fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
                                : runtime_frame_layout.code_from_fp) *
              kWordSize)));
  // May forward raw code. Note we don't just visit the pc marker slot first
  // because the visitor's forwarding might not be idempotent.
  visitor->VisitPointer(&pc_marker);
  Code code;
  if (pc_marker->IsHeapObject() && (pc_marker->GetClassId() == kCodeCid)) {
    code ^= pc_marker;
  } else {
    ASSERT(pc_marker == Object::null() ||
           (is_interpreted() && (!pc_marker->IsHeapObject() ||
                                 (pc_marker->GetClassId() == kBytecodeCid))));
  }
  if (!code.IsNull()) {
    // Optimized frames have a stack map. We need to visit the frame based
    // on the stack map.
    Array maps;
    maps = Array::null();
    StackMap map;
    const uword start = Instructions::PayloadStart(code.instructions());
    map = code.GetStackMap(pc() - start, &maps, &map);
    if (!map.IsNull()) {
#if !defined(TARGET_ARCH_DBC)
      if (is_interpreted()) {
        UNIMPLEMENTED();
      }
      RawObject** first = reinterpret_cast<RawObject**>(sp());
      RawObject** last = reinterpret_cast<RawObject**>(
          fp() + (runtime_frame_layout.first_local_from_fp * kWordSize));

      // A stack map is present in the code object, use the stack map to
      // visit frame slots which are marked as having objects.
      //
      // The layout of the frame is (lower addresses to the right):
      // | spill slots | outgoing arguments | saved registers | slow-path args |
      // |XXXXXXXXXXXXX|--------------------|XXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXX|
      //
      // The spill slots and any saved registers are described in the stack
      // map.  The outgoing arguments are assumed to be tagged; the number
      // of outgoing arguments is not explicitly tracked.
      intptr_t length = map.Length();
      // Spill slots are at the 'bottom' of the frame.
      intptr_t spill_slot_count = length - map.SlowPathBitCount();
      for (intptr_t bit = 0; bit < spill_slot_count; ++bit) {
        if (map.IsObject(bit)) {
          visitor->VisitPointer(last);
        }
        --last;
      }

      // The live registers at the 'top' of the frame comprise the rest of the
      // stack map.
      for (intptr_t bit = length - 1; bit >= spill_slot_count; --bit) {
        if (map.IsObject(bit)) {
          visitor->VisitPointer(first);
        }
        ++first;
      }

      // The last slot can be one slot (but not more) past the last slot
      // in the case that all slots were covered by the stack map.
      ASSERT((last + 1) >= first);
      visitor->VisitPointers(first, last);

      // Now visit other slots which might be part of the calling convention.
      first = reinterpret_cast<RawObject**>(
          fp() + ((runtime_frame_layout.first_local_from_fp + 1) * kWordSize));
      last = reinterpret_cast<RawObject**>(
          fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
      visitor->VisitPointers(first, last);
#else
      RawObject** first = reinterpret_cast<RawObject**>(fp());
      RawObject** last = reinterpret_cast<RawObject**>(sp());

      // Visit fixed prefix of the frame.
      RawObject** first_fixed =
          first + runtime_frame_layout.first_object_from_fp;
      RawObject** last_fixed =
          first + (runtime_frame_layout.first_object_from_fp + 1);
      ASSERT(first_fixed <= last_fixed);
      visitor->VisitPointers(first_fixed, last_fixed);

      // A stack map is present in the code object, use the stack map to
      // visit frame slots which are marked as having objects.
      //
      // The layout of the frame is (lower addresses to the left):
      // | registers | outgoing arguments |
      // |XXXXXXXXXXX|--------------------|
      //
      // The DBC registers are described in the stack map.
      // The outgoing arguments are assumed to be tagged; the number
      // of outgoing arguments is not explicitly tracked.
      ASSERT(map.SlowPathBitCount() == 0);

      // Visit DBC registers that contain tagged values.
      intptr_t length = map.Length();
      for (intptr_t bit = 0; bit < length; ++bit) {
        if (map.IsObject(bit)) {
          visitor->VisitPointer(first + bit);
        }
      }

      // Visit outgoing arguments.
      if ((first + length) <= last) {
        visitor->VisitPointers(first + length, last);
      }
#endif  // !defined(TARGET_ARCH_DBC)
      return;
    }

    // No stack map, fall through.
  }

#if !defined(TARGET_ARCH_DBC)
  // For normal unoptimized Dart frames and Stub frames each slot
  // between the first and last included are tagged objects.
  RawObject** first = reinterpret_cast<RawObject**>(
      is_interpreted() ? fp() + (kKBCFirstObjectSlotFromFp * kWordSize) : sp());
  RawObject** last = reinterpret_cast<RawObject**>(
      is_interpreted()
          ? sp()
          : fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
#else
  // On DBC stack grows upwards: fp() <= sp().
  RawObject** first = reinterpret_cast<RawObject**>(
      fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
  RawObject** last = reinterpret_cast<RawObject**>(sp());
#endif  // !defined(TARGET_ARCH_DBC)

  visitor->VisitPointers(first, last);
}

RawFunction* StackFrame::LookupDartFunction() const {
  if (is_interpreted()) {
    const Bytecode& bytecode = Bytecode::Handle(LookupDartBytecode());
    ASSERT(!bytecode.IsNull());
    return bytecode.function();
  }
  const Code& code = Code::Handle(LookupDartCode());
  if (!code.IsNull()) {
    return code.function();
  }
  return Function::null();
}

RawCode* StackFrame::LookupDartCode() const {
// We add a no gc scope to ensure that the code below does not trigger
// a GC as we are handling raw object references here. It is possible
// that the code is called while a GC is in progress, that is ok.
#if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA)
  // On Windows and Fuchsia, the profiler calls this from a separate thread
  // where Thread::Current() is NULL, so we cannot create a NoSafepointScope.
  NoSafepointScope no_safepoint;
#endif
  RawCode* code = GetCodeObject();
  if ((code != Code::null()) &&
      (code->ptr()->owner_->GetClassId() == kFunctionCid)) {
    return code;
  }
  return Code::null();
}

RawCode* StackFrame::GetCodeObject() const {
  ASSERT(!is_interpreted());
  RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
      fp() + runtime_frame_layout.code_from_fp * kWordSize));
  ASSERT((pc_marker == Object::null()) ||
         (pc_marker->GetClassId() == kCodeCid));
  return reinterpret_cast<RawCode*>(pc_marker);
}

RawBytecode* StackFrame::LookupDartBytecode() const {
// We add a no gc scope to ensure that the code below does not trigger
// a GC as we are handling raw object references here. It is possible
// that the code is called while a GC is in progress, that is ok.
#if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA)
  // On Windows and Fuchsia, the profiler calls this from a separate thread
  // where Thread::Current() is NULL, so we cannot create a NoSafepointScope.
  NoSafepointScope no_safepoint;
#endif
  return GetBytecodeObject();
}

RawBytecode* StackFrame::GetBytecodeObject() const {
  ASSERT(is_interpreted());
  RawObject* pc_marker = *(
      reinterpret_cast<RawObject**>(fp() + kKBCPcMarkerSlotFromFp * kWordSize));
  ASSERT((pc_marker == Object::null()) ||
         (pc_marker->GetClassId() == kBytecodeCid));
  return reinterpret_cast<RawBytecode*>(pc_marker);
}

bool StackFrame::FindExceptionHandler(Thread* thread,
                                      uword* handler_pc,
                                      bool* needs_stacktrace,
                                      bool* has_catch_all,
                                      bool* is_optimized) const {
  REUSABLE_CODE_HANDLESCOPE(thread);
  Code& code = reused_code_handle.Handle();
  REUSABLE_BYTECODE_HANDLESCOPE(thread);
  Bytecode& bytecode = reused_bytecode_handle.Handle();
  REUSABLE_EXCEPTION_HANDLERS_HANDLESCOPE(thread);
  ExceptionHandlers& handlers = reused_exception_handlers_handle.Handle();
  REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread);
  PcDescriptors& descriptors = reused_pc_descriptors_handle.Handle();
  uword start;
  if (is_interpreted()) {
    bytecode = LookupDartBytecode();
    ASSERT(!bytecode.IsNull());
    start = bytecode.PayloadStart();
    handlers = bytecode.exception_handlers();
    descriptors = bytecode.pc_descriptors();
  } else {
    code = LookupDartCode();
    if (code.IsNull()) {
      return false;  // Stub frames do not have exception handlers.
    }
    start = code.PayloadStart();
    handlers = code.exception_handlers();
    descriptors = code.pc_descriptors();
    *is_optimized = code.is_optimized();
  }
  HandlerInfoCache* cache = thread->isolate()->handler_info_cache();
  ExceptionHandlerInfo* info = cache->Lookup(pc());
  if (info != NULL) {
    *handler_pc = start + info->handler_pc_offset;
    *needs_stacktrace = info->needs_stacktrace;
    *has_catch_all = info->has_catch_all;
    return true;
  }
  uword pc_offset = pc() - start;

  if (handlers.num_entries() == 0) {
    return false;
  }

  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
  intptr_t try_index = -1;
  if (is_interpreted()) {
    while (iter.MoveNext()) {
      // PC descriptors for try blocks in bytecode are generated in pairs,
      // marking start and end of a try block.
      // See BytecodeMetadataHelper::ReadExceptionsTable for details.
      const intptr_t current_try_index = iter.TryIndex();
      const uword start_pc = iter.PcOffset();
      if (pc_offset < start_pc) {
        break;
      }
      const bool has_next = iter.MoveNext();
      ASSERT(has_next);
      const uword end_pc = iter.PcOffset();
      if (start_pc <= pc_offset && pc_offset < end_pc) {
        ASSERT(try_index < current_try_index);
        try_index = current_try_index;
      }
    }
  } else {
    while (iter.MoveNext()) {
      const intptr_t current_try_index = iter.TryIndex();
      if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
        try_index = current_try_index;
        break;
      }
    }
  }
  if (try_index == -1) {
    return false;
  }
  ExceptionHandlerInfo handler_info;
  handlers.GetHandlerInfo(try_index, &handler_info);
  *handler_pc = start + handler_info.handler_pc_offset;
  *needs_stacktrace = handler_info.needs_stacktrace;
  *has_catch_all = handler_info.has_catch_all;
  cache->Insert(pc(), handler_info);
  return true;
}

TokenPosition StackFrame::GetTokenPos() const {
  if (is_interpreted()) {
    const Bytecode& bytecode = Bytecode::Handle(LookupDartBytecode());
    if (bytecode.IsNull()) {
      return TokenPosition::kNoSource;  // Stub frames do not have token_pos.
    }
    return bytecode.GetTokenIndexOfPC(pc());
  }
  const Code& code = Code::Handle(LookupDartCode());
  if (code.IsNull()) {
    return TokenPosition::kNoSource;  // Stub frames do not have token_pos.
  }
  uword pc_offset = pc() - code.PayloadStart();
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(code.pc_descriptors());
  ASSERT(!descriptors.IsNull());
  PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    if (iter.PcOffset() == pc_offset) {
      return TokenPosition(iter.TokenPos());
    }
  }
  return TokenPosition::kNoSource;
}

bool StackFrame::IsValid() const {
  if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) {
    return true;
  }
  if (is_interpreted()) {
    return (LookupDartBytecode() != Bytecode::null());
  }
  return (LookupDartCode() != Code::null());
}

void StackFrameIterator::SetupLastExitFrameData() {
  ASSERT(thread_ != NULL);
  uword exit_marker = thread_->top_exit_frame_info();
  frames_.fp_ = exit_marker;
  if (FLAG_enable_interpreter) {
    frames_.CheckIfInterpreted(exit_marker);
  }
}

void StackFrameIterator::SetupNextExitFrameData() {
  ASSERT(entry_.fp() != 0);
  uword exit_address =
      entry_.fp() + ((entry_.is_interpreted() ? kKBCExitLinkSlotFromEntryFp
                                              : kExitLinkSlotFromEntryFp) *
                     kWordSize);
  uword exit_marker = *reinterpret_cast<uword*>(exit_address);
  frames_.fp_ = exit_marker;
  frames_.sp_ = 0;
  frames_.pc_ = 0;
  if (FLAG_enable_interpreter) {
    frames_.CheckIfInterpreted(exit_marker);
  }
}

// Tell MemorySanitizer that generated code initializes part of the stack.
// TODO(koda): Limit to frames that are actually written by generated code.
static void UnpoisonStack(uword fp) {
  ASSERT(fp != 0);
  uword size = OSThread::GetSpecifiedStackSize();
  MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size);
}

StackFrameIterator::StackFrameIterator(ValidationPolicy validation_policy,
                                       Thread* thread,
                                       CrossThreadPolicy cross_thread_policy)
    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
      entry_(thread),
      exit_(thread),
      frames_(thread),
      current_frame_(NULL),
      thread_(thread) {
  ASSERT(cross_thread_policy == kAllowCrossThreadIteration ||
         thread_ == Thread::Current());
  SetupLastExitFrameData();  // Setup data for last exit frame.
}

StackFrameIterator::StackFrameIterator(uword last_fp,
                                       ValidationPolicy validation_policy,
                                       Thread* thread,
                                       CrossThreadPolicy cross_thread_policy)
    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
      entry_(thread),
      exit_(thread),
      frames_(thread),
      current_frame_(NULL),
      thread_(thread) {
  ASSERT(cross_thread_policy == kAllowCrossThreadIteration ||
         thread_ == Thread::Current());
  frames_.fp_ = last_fp;
  frames_.sp_ = 0;
  frames_.pc_ = 0;
  if (FLAG_enable_interpreter) {
    frames_.CheckIfInterpreted(last_fp);
  }
}

#if !defined(TARGET_ARCH_DBC)
StackFrameIterator::StackFrameIterator(uword fp,
                                       uword sp,
                                       uword pc,
                                       ValidationPolicy validation_policy,
                                       Thread* thread,
                                       CrossThreadPolicy cross_thread_policy)
    : validate_(validation_policy == ValidationPolicy::kValidateFrames),
      entry_(thread),
      exit_(thread),
      frames_(thread),
      current_frame_(NULL),
      thread_(thread) {
  ASSERT(cross_thread_policy == kAllowCrossThreadIteration ||
         thread_ == Thread::Current());
  frames_.fp_ = fp;
  frames_.sp_ = sp;
  frames_.pc_ = pc;
  if (FLAG_enable_interpreter) {
    frames_.CheckIfInterpreted(fp);
  }
}
#endif

StackFrame* StackFrameIterator::NextFrame() {
  // When we are at the start of iteration after having created an
  // iterator object, current_frame_ will be NULL as we haven't seen
  // any frames yet (unless we start iterating in the simulator from a given
  // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries
  // to set up the next exit frame by reading the top_exit_frame_info
  // from the isolate. If we do not have any dart invocations yet,
  // top_exit_frame_info will be 0 and so we would return NULL.

  // current_frame_ will also be NULL, when we are at the end of having
  // iterated through all the frames. If NextFrame is called at this
  // point, we will try and set up the next exit frame, but since we are
  // at the end of the iteration, fp_ will be 0 and we would return NULL.
  if (current_frame_ == NULL) {
    if (!HasNextFrame()) {
      return NULL;
    }
    UnpoisonStack(frames_.fp_);
#if !defined(TARGET_ARCH_DBC)
    if (frames_.pc_ == 0) {
      // Iteration starts from an exit frame given by its fp.
      current_frame_ = NextExitFrame();
    } else if (*(reinterpret_cast<uword*>(
                   frames_.fp_ +
                   ((frames_.is_interpreted() ? kKBCSavedCallerFpSlotFromFp
                                              : kSavedCallerFpSlotFromFp) *
                    kWordSize))) == 0) {
      // Iteration starts from an entry frame given by its fp, sp, and pc.
      current_frame_ = NextEntryFrame();
    } else {
      // Iteration starts from a Dart or stub frame given by its fp, sp, and pc.
      current_frame_ = frames_.NextFrame(validate_);
    }
#else
    // Iteration starts from an exit frame given by its fp. This is the only
    // mode supported on DBC.
    ASSERT(frames_.pc_ == 0);
    current_frame_ = NextExitFrame();
#endif  // !defined(TARGET_ARCH_DBC)
    return current_frame_;
  }
  ASSERT(!validate_ || current_frame_->IsValid());
  if (current_frame_->IsEntryFrame()) {
    if (HasNextFrame()) {  // We have another chained block.
      current_frame_ = NextExitFrame();
      return current_frame_;
    }
    current_frame_ = NULL;  // No more frames.
    return current_frame_;
  }
  ASSERT(!validate_ || current_frame_->IsExitFrame() ||
         current_frame_->IsDartFrame(validate_) ||
         current_frame_->IsStubFrame());

  // Consume dart/stub frames using StackFrameIterator::FrameSetIterator
  // until we are out of dart/stub frames at which point we return the
  // corresponding entry frame for that set of dart/stub frames.
  current_frame_ =
      (frames_.HasNext()) ? frames_.NextFrame(validate_) : NextEntryFrame();
  return current_frame_;
}

void StackFrameIterator::FrameSetIterator::CheckIfInterpreted(
    uword exit_marker) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // TODO(regis): We should rely on a new thread vm_tag to identify an
  // interpreter frame and not need the HasFrame() method.
  ASSERT(FLAG_enable_interpreter);
  Interpreter* interpreter = thread_->interpreter();
  is_interpreted_ = (interpreter != NULL) && interpreter->HasFrame(exit_marker);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) {
  StackFrame* frame;
  ASSERT(HasNext());
  frame = &stack_frame_;
  frame->sp_ = sp_;
  frame->fp_ = fp_;
  frame->pc_ = pc_;
  frame->is_interpreted_ = is_interpreted_;
  sp_ = frame->GetCallerSp();
  fp_ = frame->GetCallerFp();
  pc_ = frame->GetCallerPc();
  ASSERT(is_interpreted_ == frame->is_interpreted_);
  ASSERT(!validate || frame->IsValid());
  return frame;
}

ExitFrame* StackFrameIterator::NextExitFrame() {
  exit_.sp_ = frames_.sp_;
  exit_.fp_ = frames_.fp_;
  exit_.pc_ = frames_.pc_;
  exit_.is_interpreted_ = frames_.is_interpreted_;
  frames_.sp_ = exit_.GetCallerSp();
  frames_.fp_ = exit_.GetCallerFp();
  frames_.pc_ = exit_.GetCallerPc();
  ASSERT(frames_.is_interpreted_ == exit_.is_interpreted_);
  ASSERT(!validate_ || exit_.IsValid());
  return &exit_;
}

EntryFrame* StackFrameIterator::NextEntryFrame() {
  ASSERT(!frames_.HasNext());
  entry_.sp_ = frames_.sp_;
  entry_.fp_ = frames_.fp_;
  entry_.pc_ = frames_.pc_;
  entry_.is_interpreted_ = frames_.is_interpreted_;
  SetupNextExitFrameData();  // Setup data for next exit frame in chain.
  ASSERT(!validate_ || entry_.IsValid());
  return &entry_;
}

InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc)
    : index_(0),
      num_materializations_(0),
      dest_frame_size_(0),
      code_(Code::Handle(code.raw())),
      deopt_info_(TypedData::Handle()),
      function_(Function::Handle()),
      pc_(pc),
      deopt_instructions_(),
      object_table_(ObjectPool::Handle()) {
  ASSERT(code_.is_optimized());
  ASSERT(pc_ != 0);
  ASSERT(code.ContainsInstructionAt(pc));
#if defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(deopt_info_.IsNull());
  function_ = code_.function();
#else
  ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
  uint32_t deopt_flags = 0;
  deopt_info_ = code_.GetDeoptInfoAtPc(pc, &deopt_reason, &deopt_flags);
  if (deopt_info_.IsNull()) {
    // This is the case when a call without deopt info in optimized code
    // throws an exception. (e.g. in the parameter copying prologue).
    // In that case there won't be any inlined frames.
    function_ = code_.function();
  } else {
    // Unpack deopt info into instructions (translate away suffixes).
    const Array& deopt_table = Array::Handle(code_.deopt_info_array());
    ASSERT(!deopt_table.IsNull());
    DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_);
    num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_);
    dest_frame_size_ = DeoptInfo::FrameSize(deopt_info_);
    object_table_ = code_.GetObjectPool();
    Advance();
  }
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void InlinedFunctionsIterator::Advance() {
  // Iterate over the deopt instructions and determine the inlined
  // functions if any and iterate over them.
  ASSERT(!Done());

#if defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(deopt_info_.IsNull());
  SetDone();
  return;
#else
  if (deopt_info_.IsNull()) {
    SetDone();
    return;
  }

  ASSERT(deopt_instructions_.length() != 0);
  while (index_ < deopt_instructions_.length()) {
    DeoptInstr* deopt_instr = deopt_instructions_[index_++];
    if (deopt_instr->kind() == DeoptInstr::kRetAddress) {
      pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &code_);
      function_ = code_.function();
      return;
    }
  }
  SetDone();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

// Finds the potential offset for the current function's FP if the
// current frame were to be deoptimized.
intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const {
  ASSERT(deopt_instructions_.length() != 0);
  for (intptr_t index = index_; index < deopt_instructions_.length(); index++) {
    DeoptInstr* deopt_instr = deopt_instructions_[index];
    if (deopt_instr->kind() == DeoptInstr::kCallerFp) {
      intptr_t fp_offset = (index - num_materializations_);
#if defined(TARGET_ARCH_DBC)
      // Stack on DBC is growing upwards but we record deopt commands
      // in the same order we record them on other architectures as if
      // the stack was growing downwards.
      fp_offset = dest_frame_size_ - fp_offset;
#endif
      return fp_offset;
    }
  }
  UNREACHABLE();
  return 0;
}

#if defined(DEBUG)
void ValidateFrames() {
  StackFrameIterator frames(ValidationPolicy::kValidateFrames,
                            Thread::Current(),
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  while (frame != NULL) {
    frame = frames.NextFrame();
  }
}
#endif

}  // namespace dart
