// Copyright (c) 2011, 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_STACK_FRAME_H_
#define RUNTIME_VM_STACK_FRAME_H_

#include "vm/allocation.h"
#include "vm/frame_layout.h"
#include "vm/object.h"
#include "vm/stub_code.h"

#if defined(TARGET_ARCH_IA32)
#include "vm/stack_frame_ia32.h"
#elif defined(TARGET_ARCH_X64)
#include "vm/stack_frame_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/stack_frame_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/stack_frame_arm64.h"
#else
#error Unknown architecture.
#endif

namespace dart {

// Forward declarations.
class ObjectPointerVisitor;
class LocalVariable;

extern UntaggedFrame runtime_frame_layout;

// Generic stack frame.
class StackFrame : public ValueObject {
 public:
  virtual ~StackFrame() {}

  // Accessors to get the pc, sp and fp of a frame.
  uword sp() const { return sp_; }
  uword fp() const { return fp_; }
  uword pc() const { return pc_; }

  // The pool pointer is not implemented on all architectures.
  static int SavedCallerPpSlotFromFp() {
    if (runtime_frame_layout.saved_caller_pp_from_fp !=
        kSavedCallerFpSlotFromFp) {
      return runtime_frame_layout.saved_caller_pp_from_fp;
    }
    UNREACHABLE();
    return 0;
  }

  bool IsMarkedForLazyDeopt() const {
    uword raw_pc =
        *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize));
    return raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint();
  }
  void MarkForLazyDeopt() {
    set_pc(StubCode::DeoptimizeLazyFromReturn().EntryPoint());
  }
  void UnmarkForLazyDeopt() {
    // If this frame was marked for lazy deopt, pc_ was computed to be the
    // original return address using the pending deopts table in GetCallerPc.
    // Write this value back into the frame.
    uword original_pc = pc();
    ASSERT(original_pc != StubCode::DeoptimizeLazyFromReturn().EntryPoint());
    set_pc(original_pc);
  }

  void set_pc(uword value) {
    *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize)) = value;
    pc_ = value;
  }

  void set_pc_marker(CodePtr code) {
    *reinterpret_cast<CodePtr*>(
        fp() + (runtime_frame_layout.code_from_fp * kWordSize)) = code;
  }

  // Visit objects in the frame.
  virtual void VisitObjectPointers(ObjectPointerVisitor* visitor);

  const char* ToCString() const;

  // Check validity of a frame, used for assertion purposes.
  virtual bool IsValid() const;

  // Returns true iff the current frame is a bare instructions dart frame.
  bool IsBareInstructionsDartFrame() const;

  // Returns true iff the current frame is a bare instructions stub frame.
  bool IsBareInstructionsStubFrame() const;

  // Frame type.
  virtual bool IsDartFrame(bool validate = true) const {
    ASSERT(!validate || IsValid());
    return !(IsEntryFrame() || IsExitFrame() || IsStubFrame());
  }
  virtual bool IsStubFrame() const;
  virtual bool IsEntryFrame() const { return false; }
  virtual bool IsExitFrame() const { return false; }

  FunctionPtr LookupDartFunction() const;
  CodePtr LookupDartCode() const;
  bool FindExceptionHandler(Thread* thread,
                            uword* handler_pc,
                            bool* needs_stacktrace,
                            bool* is_catch_all,
                            bool* is_optimized) const;
  // Returns token_pos of the pc(), or -1 if none exists.
  TokenPosition GetTokenPos() const;

  static void DumpCurrentTrace();

  uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }

 protected:
  explicit StackFrame(Thread* thread)
      : fp_(0), sp_(0), pc_(0), thread_(thread) {}

  // Name of the frame, used for generic frame printing functionality.
  virtual const char* GetName() const {
    if (IsBareInstructionsStubFrame()) return "bare-stub";
    if (IsStubFrame()) return "stub";
    return IsBareInstructionsDartFrame() ? "bare-dart" : "dart";
  }

  Isolate* isolate() const { return thread_->isolate(); }
  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }

  Thread* thread() const { return thread_; }

 private:
  CodePtr GetCodeObject() const;

  uword GetCallerFp() const {
    return *(reinterpret_cast<uword*>(fp() +
                                      (kSavedCallerFpSlotFromFp * kWordSize)));
  }

  uword GetCallerPc() const {
    uword raw_pc = *(reinterpret_cast<uword*>(
        fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
    ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow().EntryPoint());
    if (raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint()) {
      return thread_->pending_deopts().FindPendingDeopt(GetCallerFp());
    }
    return raw_pc;
  }

  uword fp_;
  uword sp_;
  uword pc_;
  Thread* thread_;

  // The iterators FrameSetIterator and StackFrameIterator set the private
  // fields fp_ and sp_ when they return the respective frame objects.
  friend class FrameSetIterator;
  friend class StackFrameIterator;
  friend class ProfilerDartStackWalker;
  DISALLOW_COPY_AND_ASSIGN(StackFrame);
};

// Exit frame is used to mark the transition from dart code into dart VM
// runtime code.
class ExitFrame : public StackFrame {
 public:
  bool IsValid() const { return sp() == 0; }
  bool IsDartFrame(bool validate = true) const { return false; }
  bool IsStubFrame() const { return false; }
  bool IsExitFrame() const { return true; }

  // Visit objects in the frame.
  virtual void VisitObjectPointers(ObjectPointerVisitor* visitor);

 protected:
  virtual const char* GetName() const { return "exit"; }

 private:
  explicit ExitFrame(Thread* thread) : StackFrame(thread) {}

  friend class StackFrameIterator;
  DISALLOW_COPY_AND_ASSIGN(ExitFrame);
};

// Entry Frame is used to mark the transition from dart VM runtime code into
// dart code.
class EntryFrame : public StackFrame {
 public:
  bool IsValid() const { return StubCode::InInvocationStub(pc()); }
  bool IsDartFrame(bool validate = true) const { return false; }
  bool IsStubFrame() const { return false; }
  bool IsEntryFrame() const { return true; }

  // Visit objects in the frame.
  virtual void VisitObjectPointers(ObjectPointerVisitor* visitor);

 protected:
  virtual const char* GetName() const { return "entry"; }

 private:
  explicit EntryFrame(Thread* thread) : StackFrame(thread) {}

  friend class StackFrameIterator;
  DISALLOW_COPY_AND_ASSIGN(EntryFrame);
};

// A StackFrameIterator can be initialized with a thread other than the
// current thread. Because this is generally a bad idea, it is only allowed on
// Windows- where it is needed for the profiler. It is the responsibility of
// users of StackFrameIterator to ensure that the thread given is not running
// concurrently.
class StackFrameIterator {
 public:
  enum CrossThreadPolicy {
    kNoCrossThreadIteration = 0,
    kAllowCrossThreadIteration = 1,
  };

  // Iterators for iterating over all frames from the last ExitFrame to the
  // first EntryFrame.
  StackFrameIterator(ValidationPolicy validation_policy,
                     Thread* thread,
                     CrossThreadPolicy cross_thread_policy);
  StackFrameIterator(uword last_fp,
                     ValidationPolicy validation_policy,
                     Thread* thread,
                     CrossThreadPolicy cross_thread_policy);

  // Iterator for iterating over all frames from the current frame (given by its
  // fp, sp, and pc) to the first EntryFrame.
  StackFrameIterator(uword fp,
                     uword sp,
                     uword pc,
                     ValidationPolicy validation_policy,
                     Thread* thread,
                     CrossThreadPolicy cross_thread_policy);

  explicit StackFrameIterator(const StackFrameIterator& orig);

  // Checks if a next frame exists.
  bool HasNextFrame() const { return frames_.fp_ != 0; }

  // Get next frame.
  StackFrame* NextFrame();

  bool validate() const { return validate_; }

 private:
  // Iterator for iterating over the set of frames (dart or stub) which exist
  // in one EntryFrame and ExitFrame block.
  class FrameSetIterator : public ValueObject {
   public:
    // Checks if a next non entry/exit frame exists in the set.
    bool HasNext() const {
      if (fp_ == 0) {
        return false;
      }
      const uword pc =
          *(reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize)));
      return !StubCode::InInvocationStub(pc);
    }

    // Get next non entry/exit frame in the set (assumes a next frame exists).
    StackFrame* NextFrame(bool validate);

   private:
    explicit FrameSetIterator(Thread* thread)
        : fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) {}
    void Unpoison();

    uword fp_;
    uword sp_;
    uword pc_;
    StackFrame stack_frame_;  // Singleton frame returned by NextFrame().
    Thread* thread_;

    friend class StackFrameIterator;
    DISALLOW_COPY_AND_ASSIGN(FrameSetIterator);
  };

  // Get next exit frame.
  ExitFrame* NextExitFrame();

  // Get next entry frame.
  EntryFrame* NextEntryFrame();

  // Get an iterator to the next set of frames between an entry and exit
  // frame.
  FrameSetIterator* NextFrameSet() { return &frames_; }

  // Setup last or next exit frames so that we are ready to iterate over
  // stack frames.
  void SetupLastExitFrameData();
  void SetupNextExitFrameData();

  bool validate_;     // Validate each frame as we traverse the frames.
  EntryFrame entry_;  // Singleton entry frame returned by NextEntryFrame().
  ExitFrame exit_;    // Singleton exit frame returned by NextExitFrame().
  FrameSetIterator frames_;
  StackFrame* current_frame_;  // Points to the current frame in the iterator.
  Thread* thread_;

  friend class ProfilerDartStackWalker;
};

// Iterator for iterating over all dart frames (skips over exit frames,
// entry frames and stub frames).
// A DartFrameIterator can be initialized with an isolate other than the
// current thread's isolate. Because this is generally a bad idea,
// it is only allowed on Windows- where it is needed for the profiler.
// It is the responsibility of users of DartFrameIterator to ensure that the
// isolate given is not running concurrently on another thread.
class DartFrameIterator {
 public:
  explicit DartFrameIterator(
      Thread* thread,
      StackFrameIterator::CrossThreadPolicy cross_thread_policy)
      : frames_(ValidationPolicy::kDontValidateFrames,
                thread,
                cross_thread_policy) {}
  explicit DartFrameIterator(
      uword last_fp,
      Thread* thread,
      StackFrameIterator::CrossThreadPolicy cross_thread_policy)
      : frames_(last_fp,
                ValidationPolicy::kDontValidateFrames,
                thread,
                cross_thread_policy) {}

  DartFrameIterator(uword fp,
                    uword sp,
                    uword pc,
                    Thread* thread,
                    StackFrameIterator::CrossThreadPolicy cross_thread_policy)
      : frames_(fp,
                sp,
                pc,
                ValidationPolicy::kDontValidateFrames,
                thread,
                cross_thread_policy) {}

  explicit DartFrameIterator(const DartFrameIterator& orig)
      : frames_(orig.frames_) {}

  // Get next dart frame.
  StackFrame* NextFrame() {
    StackFrame* frame = frames_.NextFrame();
    while (frame != NULL && !frame->IsDartFrame(frames_.validate())) {
      frame = frames_.NextFrame();
    }
    return frame;
  }

 private:
  StackFrameIterator frames_;
};

// Iterator for iterating over all inlined dart functions in an optimized
// dart frame (the iteration includes the function that is inlining the
// other functions).
class InlinedFunctionsIterator : public ValueObject {
 public:
  InlinedFunctionsIterator(const Code& code, uword pc);
  bool Done() const { return index_ == -1; }
  void Advance();

  FunctionPtr function() const {
    ASSERT(!Done());
    return function_.ptr();
  }

  uword pc() const {
    ASSERT(!Done());
    return pc_;
  }

  CodePtr code() const {
    ASSERT(!Done());
    return code_.ptr();
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  intptr_t GetDeoptFpOffset() const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

 private:
  void SetDone() { index_ = -1; }

  intptr_t index_;
  intptr_t num_materializations_;
  intptr_t dest_frame_size_;
  Code& code_;
  TypedData& deopt_info_;
  Function& function_;
  uword pc_;
  GrowableArray<DeoptInstr*> deopt_instructions_;
  ObjectPool& object_table_;

  DISALLOW_COPY_AND_ASSIGN(InlinedFunctionsIterator);
};

#if defined(DEBUG)
void ValidateFrames();
#endif

DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
                                                intptr_t var_index) {
  return fp_offset + var_index;
}

DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) {
  return fp + (kParamEndSlotFromFp * kWordSize) + (reverse_index * kWordSize);
}

// Both fp and other_fp are compiled code frame pointers.
DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) {
  return other_fp < fp;
}

// Value for stack limit that is used to cause an interrupt.
static const uword kInterruptStackLimit = ~static_cast<uword>(0);

DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
  return fp + LocalVarIndex(0, index) * kWordSize;
}

}  // namespace dart

#endif  // RUNTIME_VM_STACK_FRAME_H_
