// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_DEBUG_DEBUG_H_
#define V8_DEBUG_DEBUG_H_

#include <vector>

#include "src/debug/debug-interface.h"
#include "src/debug/interface-types.h"
#include "src/frames.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/isolate.h"
#include "src/objects/debug-objects.h"
#include "src/source-position-table.h"

namespace v8 {
namespace internal {

// Forward declarations.
class AbstractCode;
class DebugScope;
class JSGeneratorObject;

// Step actions. NOTE: These values are in macros.py as well.
enum StepAction : int8_t {
  StepNone = -1,  // Stepping not prepared.
  StepOut = 0,    // Step out of the current function.
  StepNext = 1,   // Step to the next statement in the current function.
  StepIn = 2,     // Step into new functions invoked or the next statement
                  // in the current function.
  LastStepAction = StepIn
};

// Type of exception break. NOTE: These values are in macros.py as well.
enum ExceptionBreakType {
  BreakException = 0,
  BreakUncaughtException = 1
};

enum DebugBreakType {
  NOT_DEBUG_BREAK,
  DEBUGGER_STATEMENT,
  DEBUG_BREAK_SLOT,
  DEBUG_BREAK_SLOT_AT_CALL,
  DEBUG_BREAK_SLOT_AT_RETURN,
  DEBUG_BREAK_SLOT_AT_SUSPEND,
  DEBUG_BREAK_AT_ENTRY,
};

enum IgnoreBreakMode {
  kIgnoreIfAllFramesBlackboxed,
  kIgnoreIfTopFrameBlackboxed
};

class BreakLocation {
 public:
  static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
                                 JavaScriptFrame* frame);

  static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
                                    JavaScriptFrame* frame,
                                    std::vector<BreakLocation>* result_out);

  inline bool IsSuspend() const { return type_ == DEBUG_BREAK_SLOT_AT_SUSPEND; }
  inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
  inline bool IsReturnOrSuspend() const {
    return type_ >= DEBUG_BREAK_SLOT_AT_RETURN;
  }
  inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
  inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
  inline bool IsDebuggerStatement() const {
    return type_ == DEBUGGER_STATEMENT;
  }
  inline bool IsDebugBreakAtEntry() const {
    bool result = type_ == DEBUG_BREAK_AT_ENTRY;
    return result;
  }

  bool HasBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info) const;

  inline int position() const { return position_; }

  debug::BreakLocationType type() const;

  JSGeneratorObject GetGeneratorObjectForSuspendedFrame(
      JavaScriptFrame* frame) const;

 private:
  BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
                int code_offset, int position, int generator_obj_reg_index)
      : abstract_code_(abstract_code),
        code_offset_(code_offset),
        type_(type),
        position_(position),
        generator_obj_reg_index_(generator_obj_reg_index) {
    DCHECK_NE(NOT_DEBUG_BREAK, type_);
  }

  BreakLocation(int position, DebugBreakType type)
      : code_offset_(0),
        type_(type),
        position_(position),
        generator_obj_reg_index_(0) {}

  static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
                                      Handle<AbstractCode> abstract_code,
                                      int offset);

  void SetDebugBreak();
  void ClearDebugBreak();

  Handle<AbstractCode> abstract_code_;
  int code_offset_;
  DebugBreakType type_;
  int position_;
  int generator_obj_reg_index_;

  friend class BreakIterator;
};

class V8_EXPORT_PRIVATE BreakIterator {
 public:
  explicit BreakIterator(Handle<DebugInfo> debug_info);

  BreakLocation GetBreakLocation();
  bool Done() const { return source_position_iterator_.done(); }
  void Next();

  void SkipToPosition(int position);
  void SkipTo(int count) {
    while (count-- > 0) Next();
  }

  int code_offset() { return source_position_iterator_.code_offset(); }
  int break_index() const { return break_index_; }
  inline int position() const { return position_; }
  inline int statement_position() const { return statement_position_; }

  void ClearDebugBreak();
  void SetDebugBreak();

 private:
  int BreakIndexFromPosition(int position);

  Isolate* isolate();

  DebugBreakType GetDebugBreakType();

  Handle<DebugInfo> debug_info_;
  int break_index_;
  int position_;
  int statement_position_;
  SourcePositionTableIterator source_position_iterator_;
  DisallowHeapAllocation no_gc_;

  DISALLOW_COPY_AND_ASSIGN(BreakIterator);
};

// Linked list holding debug info objects. The debug info objects are kept as
// weak handles to avoid a debug info object to keep a function alive.
class DebugInfoListNode {
 public:
  DebugInfoListNode(Isolate* isolate, DebugInfo debug_info);
  ~DebugInfoListNode();

  DebugInfoListNode* next() { return next_; }
  void set_next(DebugInfoListNode* next) { next_ = next; }
  Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }

 private:
  // Global (weak) handle to the debug info object.
  Address* debug_info_;

  // Next pointer for linked list.
  DebugInfoListNode* next_;
};

class DebugFeatureTracker {
 public:
  enum Feature {
    kActive = 1,
    kBreakPoint = 2,
    kStepping = 3,
    kHeapSnapshot = 4,
    kAllocationTracking = 5,
    kProfiler = 6,
    kLiveEdit = 7,
  };

  explicit DebugFeatureTracker(Isolate* isolate)
      : isolate_(isolate), bitfield_(0) {}
  void Track(Feature feature);

 private:
  Isolate* isolate_;
  uint32_t bitfield_;
};


// This class contains the debugger support. The main purpose is to handle
// setting break points in the code.
//
// This class controls the debug info for all functions which currently have
// active breakpoints in them. This debug info is held in the heap root object
// debug_info which is a FixedArray. Each entry in this list is of class
// DebugInfo.
class V8_EXPORT_PRIVATE Debug {
 public:
  // Debug event triggers.
  void OnDebugBreak(Handle<FixedArray> break_points_hit);

  void OnThrow(Handle<Object> exception);
  void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
  void OnCompileError(Handle<Script> script);
  void OnAfterCompile(Handle<Script> script);

  void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);

  // The break target may not be the top-most frame, since we may be
  // breaking before entering a function that cannot contain break points.
  void Break(JavaScriptFrame* frame, Handle<JSFunction> break_target);

  // Scripts handling.
  Handle<FixedArray> GetLoadedScripts();

  // Break point handling.
  bool SetBreakpoint(Handle<SharedFunctionInfo> shared,
                     Handle<BreakPoint> break_point, int* source_position);
  void ClearBreakPoint(Handle<BreakPoint> break_point);
  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
  bool IsBreakOnException(ExceptionBreakType type);

  bool SetBreakPointForScript(Handle<Script> script, Handle<String> condition,
                              int* source_position, int* id);
  bool SetBreakpointForFunction(Handle<SharedFunctionInfo> shared,
                                Handle<String> condition, int* id);
  void RemoveBreakpoint(int id);

  // Find breakpoints from the debug info and the break location and check
  // whether they are hit. Return an empty handle if not, or a FixedArray with
  // hit BreakPoint objects.
  MaybeHandle<FixedArray> GetHitBreakPoints(Handle<DebugInfo> debug_info,
                                            int position);

  // Stepping handling.
  void PrepareStep(StepAction step_action);
  void PrepareStepIn(Handle<JSFunction> function);
  void PrepareStepInSuspendedGenerator();
  void PrepareStepOnThrow();
  void ClearStepping();

  void SetBreakOnNextFunctionCall();
  void ClearBreakOnNextFunctionCall();

  void DeoptimizeFunction(Handle<SharedFunctionInfo> shared);
  void PrepareFunctionForDebugExecution(Handle<SharedFunctionInfo> shared);
  void InstallDebugBreakTrampoline();
  bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
                              int end_position, bool restrict_to_function,
                              std::vector<BreakLocation>* locations);

  MaybeHandle<JSArray> GetPrivateFields(Handle<JSReceiver> receiver);

  bool IsBlackboxed(Handle<SharedFunctionInfo> shared);

  bool CanBreakAtEntry(Handle<SharedFunctionInfo> shared);

  void SetDebugDelegate(debug::DebugDelegate* delegate);

  // Returns whether the operation succeeded.
  bool EnsureBreakInfo(Handle<SharedFunctionInfo> shared);
  void CreateBreakInfo(Handle<SharedFunctionInfo> shared);
  Handle<DebugInfo> GetOrCreateDebugInfo(Handle<SharedFunctionInfo> shared);

  void InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
                           Handle<CoverageInfo> coverage_info);
  void RemoveAllCoverageInfos();

  // This function is used in FunctionNameUsing* tests.
  Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
                                                int position);

  static Handle<Object> GetSourceBreakLocations(
      Isolate* isolate, Handle<SharedFunctionInfo> shared);

  // Check whether this frame is just about to return.
  bool IsBreakAtReturn(JavaScriptFrame* frame);

  // Support for LiveEdit
  void ScheduleFrameRestart(StackFrame* frame);

  bool AllFramesOnStackAreBlackboxed();

  // Set new script source, throw an exception if error occurred. When preview
  // is true: try to set source, throw exception if any without actual script
  // change. stack_changed is true if after editing script on pause stack is
  // changed and client should request stack trace again.
  bool SetScriptSource(Handle<Script> script, Handle<String> source,
                       bool preview, debug::LiveEditResult* result);

  int GetFunctionDebuggingId(Handle<JSFunction> function);

  // Threading support.
  char* ArchiveDebug(char* to);
  char* RestoreDebug(char* from);
  static int ArchiveSpacePerThread();
  void FreeThreadResources() { }
  void Iterate(RootVisitor* v);
  void InitThread(const ExecutionAccess& lock) { ThreadInit(); }

  bool CheckExecutionState() { return is_active(); }

  void StartSideEffectCheckMode();
  void StopSideEffectCheckMode();

  void ApplySideEffectChecks(Handle<DebugInfo> debug_info);
  void ClearSideEffectChecks(Handle<DebugInfo> debug_info);

  bool PerformSideEffectCheck(Handle<JSFunction> function,
                              Handle<Object> receiver);

  enum AccessorKind { kNotAccessor, kGetter, kSetter };
  bool PerformSideEffectCheckForCallback(Handle<Object> callback_info,
                                         Handle<Object> receiver,
                                         AccessorKind accessor_kind);
  bool PerformSideEffectCheckAtBytecode(InterpretedFrame* frame);
  bool PerformSideEffectCheckForObject(Handle<Object> object);

  // Flags and states.
  inline bool is_active() const { return is_active_; }
  inline bool in_debug_scope() const {
    return !!base::Relaxed_Load(&thread_local_.current_debug_scope_);
  }
  inline bool needs_check_on_function_call() const {
    return hook_on_function_call_;
  }

  void set_break_points_active(bool v) { break_points_active_ = v; }
  bool break_points_active() const { return break_points_active_; }

  StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }

  Handle<Object> return_value_handle();
  Object return_value() { return thread_local_.return_value_; }
  void set_return_value(Object value) { thread_local_.return_value_ = value; }

  // Support for embedding into generated code.
  Address is_active_address() {
    return reinterpret_cast<Address>(&is_active_);
  }

  Address hook_on_function_call_address() {
    return reinterpret_cast<Address>(&hook_on_function_call_);
  }

  Address suspended_generator_address() {
    return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
  }

  Address restart_fp_address() {
    return reinterpret_cast<Address>(&thread_local_.restart_fp_);
  }
  bool will_restart() const {
    return thread_local_.restart_fp_ != kNullAddress;
  }

  StepAction last_step_action() { return thread_local_.last_step_action_; }
  bool break_on_next_function_call() const {
    return thread_local_.break_on_next_function_call_;
  }

  DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }

  // For functions in which we cannot set a break point, use a canonical
  // source position for break points.
  static const int kBreakAtEntryPosition = 0;

  void RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info);

 private:
  explicit Debug(Isolate* isolate);
  ~Debug();

  void UpdateDebugInfosForExecutionMode();
  void UpdateState();
  void UpdateHookOnFunctionCall();
  void Unload();

  // Return the number of virtual frames below debugger entry.
  int CurrentFrameCount();

  inline bool ignore_events() const {
    return is_suppressed_ || !is_active_ ||
           isolate_->debug_execution_mode() == DebugInfo::kSideEffects;
  }
  inline bool break_disabled() const { return break_disabled_; }

  void clear_suspended_generator() {
    thread_local_.suspended_generator_ = Smi::kZero;
  }

  bool has_suspended_generator() const {
    return thread_local_.suspended_generator_ != Smi::kZero;
  }

  bool IsExceptionBlackboxed(bool uncaught);

  void OnException(Handle<Object> exception, Handle<Object> promise,
                   v8::debug::ExceptionType exception_type);

  void ProcessCompileEvent(bool has_compile_error, Handle<Script> script);

  // Find the closest source position for a break point for a given position.
  int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position);
  // Instrument code to break at break points.
  void ApplyBreakPoints(Handle<DebugInfo> debug_info);
  // Clear code from instrumentation.
  void ClearBreakPoints(Handle<DebugInfo> debug_info);
  // Clear all code from instrumentation.
  void ClearAllBreakPoints();
  // Instrument a function with one-shots.
  void FloodWithOneShot(Handle<SharedFunctionInfo> function,
                        bool returns_only = false);
  // Clear all one-shot instrumentations, but restore break points.
  void ClearOneShot();

  bool IsFrameBlackboxed(JavaScriptFrame* frame);

  void ActivateStepOut(StackFrame* frame);
  MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
                                           BreakLocation* location,
                                           bool* has_break_points = nullptr);
  bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
  // Check whether a BreakPoint object is hit. Evaluate condition depending
  // on whether this is a regular break location or a break at function entry.
  bool CheckBreakPoint(Handle<BreakPoint> break_point, bool is_break_at_entry);

  inline void AssertDebugContext() {
    DCHECK(in_debug_scope());
  }

  void ThreadInit();

  void PrintBreakLocation();

  void ClearAllDebuggerHints();

  // Wraps logic for clearing and maybe freeing all debug infos.
  using DebugInfoClearFunction = std::function<void(Handle<DebugInfo>)>;
  void ClearAllDebugInfos(const DebugInfoClearFunction& clear_function);

  void FindDebugInfo(Handle<DebugInfo> debug_info, DebugInfoListNode** prev,
                     DebugInfoListNode** curr);
  void FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node);

  debug::DebugDelegate* debug_delegate_ = nullptr;

  // Debugger is active, i.e. there is a debug event listener attached.
  bool is_active_;
  // Debugger needs to be notified on every new function call.
  // Used for stepping and read-only checks
  bool hook_on_function_call_;
  // Suppress debug events.
  bool is_suppressed_;
  // Running liveedit.
  bool running_live_edit_ = false;
  // Do not trigger debug break events.
  bool break_disabled_;
  // Do not break on break points.
  bool break_points_active_;
  // Trigger debug break events for all exceptions.
  bool break_on_exception_;
  // Trigger debug break events for uncaught exceptions.
  bool break_on_uncaught_exception_;
  // Termination exception because side effect check has failed.
  bool side_effect_check_failed_;

  // List of active debug info objects.
  DebugInfoListNode* debug_info_list_;

  // Used for side effect check to mark temporary objects.
  class TemporaryObjectsTracker;
  std::unique_ptr<TemporaryObjectsTracker> temporary_objects_;

  Handle<RegExpMatchInfo> regexp_match_info_;

  // Used to collect histogram data on debugger feature usage.
  DebugFeatureTracker feature_tracker_;

  // Per-thread data.
  class ThreadLocal {
   public:
    // Top debugger entry.
    base::AtomicWord current_debug_scope_;

    // Frame id for the frame of the current break.
    StackFrame::Id break_frame_id_;

    // Step action for last step performed.
    StepAction last_step_action_;

    // If set, next PrepareStepIn will ignore this function until stepped into
    // another function, at which point this will be cleared.
    Object ignore_step_into_function_;

    // If set then we need to repeat StepOut action at return.
    bool fast_forward_to_return_;

    // Source statement position from last step next action.
    int last_statement_position_;

    // Frame pointer from last step next or step frame action.
    int last_frame_count_;

    // Frame pointer of the target frame we want to arrive at.
    int target_frame_count_;

    // Value of the accumulator at the point of entering the debugger.
    Object return_value_;

    // The suspended generator object to track when stepping.
    Object suspended_generator_;

    // The new frame pointer to drop to when restarting a frame.
    Address restart_fp_;

    // Last used inspector breakpoint id.
    int last_breakpoint_id_;

    // This flag is true when SetBreakOnNextFunctionCall is called and it forces
    // debugger to break on next function call.
    bool break_on_next_function_call_;
  };

  // Storage location for registers when handling debug break calls
  ThreadLocal thread_local_;

  Isolate* isolate_;

  friend class Isolate;
  friend class DebugScope;
  friend class DisableBreak;
  friend class LiveEdit;
  friend class SuppressDebug;

  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
  friend void CheckDebuggerUnloaded();               // In test-debug.cc

  DISALLOW_COPY_AND_ASSIGN(Debug);
};

// This scope is used to load and enter the debug context and create a new
// break state.  Leaving the scope will restore the previous state.
class DebugScope {
 public:
  explicit DebugScope(Debug* debug);
  ~DebugScope();

 private:
  Isolate* isolate() { return debug_->isolate_; }

  Debug* debug_;
  DebugScope* prev_;               // Previous scope if entered recursively.
  StackFrame::Id break_frame_id_;  // Previous break frame id.
  PostponeInterruptsScope no_interrupts_;
};

// This scope is used to handle return values in nested debug break points.
// When there are nested debug breaks, we use this to restore the return
// value to the previous state. This is not merged with DebugScope because
// return_value_ will not be cleared when we use DebugScope.
class ReturnValueScope {
 public:
  explicit ReturnValueScope(Debug* debug);
  ~ReturnValueScope();

 private:
  Debug* debug_;
  Handle<Object> return_value_;  // Previous result.
};

// Stack allocated class for disabling break.
class DisableBreak {
 public:
  explicit DisableBreak(Debug* debug, bool disable = true)
      : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
    debug_->break_disabled_ = disable;
  }
  ~DisableBreak() {
    debug_->break_disabled_ = previous_break_disabled_;
  }

 private:
  Debug* debug_;
  bool previous_break_disabled_;
  DISALLOW_COPY_AND_ASSIGN(DisableBreak);
};

class SuppressDebug {
 public:
  explicit SuppressDebug(Debug* debug)
      : debug_(debug), old_state_(debug->is_suppressed_) {
    debug_->is_suppressed_ = true;
  }
  ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }

 private:
  Debug* debug_;
  bool old_state_;
  DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
};

// Code generator routines.
class DebugCodegen : public AllStatic {
 public:
  enum DebugBreakCallHelperMode {
    SAVE_RESULT_REGISTER,
    IGNORE_RESULT_REGISTER
  };

  // Builtin to drop frames to restart function.
  static void GenerateFrameDropperTrampoline(MacroAssembler* masm);

  // Builtin to atomically (wrt deopts) handle debugger statement and
  // drop frames to restart function if necessary.
  static void GenerateHandleDebuggerStatement(MacroAssembler* masm);

  // Builtin to trigger a debug break before entering the function.
  static void GenerateDebugBreakTrampoline(MacroAssembler* masm);
};


}  // namespace internal
}  // namespace v8

#endif  // V8_DEBUG_DEBUG_H_
