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

#include "src/debug/debug.h"

#include "src/api.h"
#include "src/arguments.h"
#include "src/bootstrapper.h"
#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/compilation-cache.h"
#include "src/compiler.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
#include "src/frames-inl.h"
#include "src/full-codegen/full-codegen.h"
#include "src/global-handles.h"
#include "src/interpreter/interpreter.h"
#include "src/isolate-inl.h"
#include "src/list.h"
#include "src/log.h"
#include "src/messages.h"
#include "src/snapshot/natives.h"

#include "include/v8-debug.h"

namespace v8 {
namespace internal {

Debug::Debug(Isolate* isolate)
    : debug_context_(Handle<Context>()),
      event_listener_(Handle<Object>()),
      event_listener_data_(Handle<Object>()),
      message_handler_(NULL),
      command_received_(0),
      command_queue_(isolate->logger(), kQueueInitialSize),
      is_active_(false),
      is_suppressed_(false),
      live_edit_enabled_(true),  // TODO(yangguo): set to false by default.
      break_disabled_(false),
      break_points_active_(true),
      in_debug_event_listener_(false),
      break_on_exception_(false),
      break_on_uncaught_exception_(false),
      debug_info_list_(NULL),
      feature_tracker_(isolate),
      isolate_(isolate) {
  ThreadInit();
}


static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
  // Isolate::context() may have been NULL when "script collected" event
  // occured.
  if (context.is_null()) return v8::Local<v8::Context>();
  Handle<Context> native_context(context->native_context());
  return v8::Utils::ToLocal(native_context);
}

BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
                             int code_offset, int position,
                             int statement_position)
    : debug_info_(debug_info),
      code_offset_(code_offset),
      type_(type),
      position_(position),
      statement_position_(statement_position) {}

BreakLocation::Iterator* BreakLocation::GetIterator(
    Handle<DebugInfo> debug_info, BreakLocatorType type) {
  if (debug_info->abstract_code()->IsBytecodeArray()) {
    return new BytecodeArrayIterator(debug_info, type);
  } else {
    return new CodeIterator(debug_info, type);
  }
}

BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
    : debug_info_(debug_info),
      break_index_(-1),
      position_(1),
      statement_position_(1) {}

int BreakLocation::Iterator::ReturnPosition() {
  if (debug_info_->shared()->HasSourceCode()) {
    return debug_info_->shared()->end_position() -
           debug_info_->shared()->start_position() - 1;
  } else {
    return 0;
  }
}

BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
                                          BreakLocatorType type)
    : Iterator(debug_info),
      reloc_iterator_(debug_info->abstract_code()->GetCode(),
                      GetModeMask(type)) {
  // There is at least one break location.
  DCHECK(!Done());
  Next();
}

int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
  int mask = 0;
  mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
  mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
  mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
  mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
  if (isolate()->is_tail_call_elimination_enabled()) {
    mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL);
  }
  if (type == ALL_BREAK_LOCATIONS) {
    mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
    mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
  }
  return mask;
}

void BreakLocation::CodeIterator::Next() {
  DisallowHeapAllocation no_gc;
  DCHECK(!Done());

  // Iterate through reloc info stopping at each breakable code target.
  bool first = break_index_ == -1;
  while (!Done()) {
    if (!first) reloc_iterator_.next();
    first = false;
    if (Done()) return;

    // Whenever a statement position or (plain) position is passed update the
    // current value of these.
    if (RelocInfo::IsPosition(rmode())) {
      if (RelocInfo::IsStatementPosition(rmode())) {
        statement_position_ = static_cast<int>(
            rinfo()->data() - debug_info_->shared()->start_position());
      }
      // Always update the position as we don't want that to be before the
      // statement position.
      position_ = static_cast<int>(rinfo()->data() -
                                   debug_info_->shared()->start_position());
      DCHECK(position_ >= 0);
      DCHECK(statement_position_ >= 0);
      continue;
    }

    DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
           RelocInfo::IsDebuggerStatement(rmode()));

    if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
      // Set the positions to the end of the function.
      statement_position_ = position_ = ReturnPosition();
    }

    break;
  }
  break_index_++;
}

BreakLocation BreakLocation::CodeIterator::GetBreakLocation() {
  DebugBreakType type;
  if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
    type = DEBUG_BREAK_SLOT_AT_RETURN;
  } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
    type = DEBUG_BREAK_SLOT_AT_CALL;
  } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
    type = isolate()->is_tail_call_elimination_enabled()
               ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
               : DEBUG_BREAK_SLOT_AT_CALL;
  } else if (RelocInfo::IsDebuggerStatement(rmode())) {
    type = DEBUGGER_STATEMENT;
  } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
    type = DEBUG_BREAK_SLOT;
  } else {
    type = NOT_DEBUG_BREAK;
  }
  return BreakLocation(debug_info_, type, code_offset(), position(),
                       statement_position());
}

BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
    Handle<DebugInfo> debug_info, BreakLocatorType type)
    : Iterator(debug_info),
      source_position_iterator_(debug_info->abstract_code()
                                    ->GetBytecodeArray()
                                    ->source_position_table()),
      break_locator_type_(type),
      start_position_(debug_info->shared()->start_position()) {
  // There is at least one break location.
  DCHECK(!Done());
  Next();
}

void BreakLocation::BytecodeArrayIterator::Next() {
  DisallowHeapAllocation no_gc;
  DCHECK(!Done());
  bool first = break_index_ == -1;
  while (!Done()) {
    if (!first) source_position_iterator_.Advance();
    first = false;
    if (Done()) return;
    position_ = source_position_iterator_.source_position() - start_position_;
    if (source_position_iterator_.is_statement()) {
      statement_position_ = position_;
    }
    DCHECK(position_ >= 0);
    DCHECK(statement_position_ >= 0);

    enum DebugBreakType type = GetDebugBreakType();
    if (type == NOT_DEBUG_BREAK) continue;

    if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;

    DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
    if (type == DEBUG_BREAK_SLOT_AT_CALL) break;
    if (type == DEBUG_BREAK_SLOT_AT_RETURN) {
      DCHECK_EQ(ReturnPosition(), position_);
      DCHECK_EQ(ReturnPosition(), statement_position_);
      break;
    }
  }
  break_index_++;
}

BreakLocation::DebugBreakType
BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
  BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
  interpreter::Bytecode bytecode =
      interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));

  if (bytecode == interpreter::Bytecode::kDebugger) {
    return DEBUGGER_STATEMENT;
  } else if (bytecode == interpreter::Bytecode::kReturn) {
    return DEBUG_BREAK_SLOT_AT_RETURN;
  } else if (bytecode == interpreter::Bytecode::kTailCall) {
    return isolate()->is_tail_call_elimination_enabled()
               ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
               : DEBUG_BREAK_SLOT_AT_CALL;
  } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) {
    return DEBUG_BREAK_SLOT_AT_CALL;
  } else if (source_position_iterator_.is_statement()) {
    return DEBUG_BREAK_SLOT;
  } else {
    return NOT_DEBUG_BREAK;
  }
}

BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
  return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(),
                       position(), statement_position());
}

// Find the break point at the supplied address, or the closest one before
// the address.
BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
                                            int offset) {
  base::SmartPointer<Iterator> it(GetIterator(debug_info));
  it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
  return it->GetBreakLocation();
}

int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
  // Code offset points to the instruction after the call. Subtract 1 to
  // exclude that instruction from the search. For bytecode, the code offset
  // still points to the call.
  return is_interpreted ? code_offset : code_offset - 1;
}

BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
                                       JavaScriptFrame* frame) {
  FrameSummary summary = FrameSummary::GetFirst(frame);
  int call_offset =
      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
  return FromCodeOffset(debug_info, call_offset);
}

void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info,
                                            int statement_position,
                                            List<BreakLocation>* result_out) {
  for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
       it->Next()) {
    if (it->statement_position() == statement_position) {
      result_out->Add(it->GetBreakLocation());
    }
  }
}

int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
                                            int offset) {
  // Run through all break points to locate the one closest to the address.
  int closest_break = 0;
  int distance = kMaxInt;
  DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
  for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
       it->Next()) {
    // Check if this break point is closer that what was previously found.
    if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
      closest_break = it->break_index();
      distance = offset - it->code_offset();
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
  }
  return closest_break;
}


BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
                                          int position,
                                          BreakPositionAlignment alignment) {
  // Run through all break points to locate the one closest to the source
  // position.
  int distance = kMaxInt;
  base::SmartPointer<Iterator> it(GetIterator(debug_info));
  BreakLocation closest_break = it->GetBreakLocation();
  while (!it->Done()) {
    int next_position;
    if (alignment == STATEMENT_ALIGNED) {
      next_position = it->statement_position();
    } else {
      DCHECK(alignment == BREAK_POSITION_ALIGNED);
      next_position = it->position();
    }
    if (position <= next_position && next_position - position < distance) {
      closest_break = it->GetBreakLocation();
      distance = next_position - position;
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
    it->Next();
  }
  return closest_break;
}


void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
  // If there is not already a real break point here patch code with debug
  // break.
  if (!HasBreakPoint()) SetDebugBreak();
  DCHECK(IsDebugBreak() || IsDebuggerStatement());
  // Set the break point information.
  DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_,
                           statement_position_, break_point_object);
}


void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
  // Clear the break point information.
  DebugInfo::ClearBreakPoint(debug_info_, code_offset_, break_point_object);
  // If there are no more break points here remove the debug break.
  if (!HasBreakPoint()) {
    ClearDebugBreak();
    DCHECK(!IsDebugBreak());
  }
}


void BreakLocation::SetOneShot() {
  // Debugger statement always calls debugger. No need to modify it.
  if (IsDebuggerStatement()) return;

  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
    DCHECK(IsDebugBreak());
    return;
  }

  // Patch code with debug break.
  SetDebugBreak();
}


void BreakLocation::ClearOneShot() {
  // Debugger statement always calls debugger. No need to modify it.
  if (IsDebuggerStatement()) return;

  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
    DCHECK(IsDebugBreak());
    return;
  }

  // Patch code removing debug break.
  ClearDebugBreak();
  DCHECK(!IsDebugBreak());
}


void BreakLocation::SetDebugBreak() {
  // Debugger statement always calls debugger. No need to modify it.
  if (IsDebuggerStatement()) return;

  // If there is already a break point here just return. This might happen if
  // the same code is flooded with break points twice. Flooding the same
  // function twice might happen when stepping in a function with an exception
  // handler as the handler and the function is the same.
  if (IsDebugBreak()) return;

  DCHECK(IsDebugBreakSlot());
  if (abstract_code()->IsCode()) {
    Code* code = abstract_code()->GetCode();
    DCHECK(code->kind() == Code::FUNCTION);
    Builtins* builtins = isolate()->builtins();
    Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
                                     : builtins->Slot_DebugBreak();
    Address pc = code->instruction_start() + code_offset();
    DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
  } else {
    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
    interpreter::Bytecode bytecode =
        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
    interpreter::Bytecode debugbreak =
        interpreter::Bytecodes::GetDebugBreak(bytecode);
    bytecode_array->set(code_offset(),
                        interpreter::Bytecodes::ToByte(debugbreak));
  }
  DCHECK(IsDebugBreak());
}


void BreakLocation::ClearDebugBreak() {
  // Debugger statement always calls debugger. No need to modify it.
  if (IsDebuggerStatement()) return;

  DCHECK(IsDebugBreakSlot());
  if (abstract_code()->IsCode()) {
    Code* code = abstract_code()->GetCode();
    DCHECK(code->kind() == Code::FUNCTION);
    Address pc = code->instruction_start() + code_offset();
    DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
  } else {
    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
    BytecodeArray* original = debug_info_->original_bytecode_array();
    bytecode_array->set(code_offset(), original->get(code_offset()));
  }
  DCHECK(!IsDebugBreak());
}


bool BreakLocation::IsDebugBreak() const {
  if (IsDebuggerStatement()) return false;
  DCHECK(IsDebugBreakSlot());
  if (abstract_code()->IsCode()) {
    Code* code = abstract_code()->GetCode();
    DCHECK(code->kind() == Code::FUNCTION);
    Address pc = code->instruction_start() + code_offset();
    return DebugCodegen::DebugBreakSlotIsPatched(pc);
  } else {
    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
    interpreter::Bytecode bytecode =
        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
    return interpreter::Bytecodes::IsDebugBreak(bytecode);
  }
}


Handle<Object> BreakLocation::BreakPointObjects() const {
  return debug_info_->GetBreakPointObjects(code_offset_);
}

void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
  uint32_t mask = 1 << feature;
  // Only count one sample per feature and isolate.
  if (bitfield_ & mask) return;
  isolate_->counters()->debug_feature_usage()->AddSample(feature);
  bitfield_ |= mask;
}


// Threading support.
void Debug::ThreadInit() {
  thread_local_.break_count_ = 0;
  thread_local_.break_id_ = 0;
  thread_local_.break_frame_id_ = StackFrame::NO_ID;
  thread_local_.last_step_action_ = StepNone;
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
  thread_local_.last_fp_ = 0;
  thread_local_.target_fp_ = 0;
  thread_local_.return_value_ = Handle<Object>();
  clear_suspended_generator();
  // TODO(isolates): frames_are_dropped_?
  base::NoBarrier_Store(&thread_local_.current_debug_scope_,
                        static_cast<base::AtomicWord>(0));
}


char* Debug::ArchiveDebug(char* storage) {
  // Simply reset state. Don't archive anything.
  ThreadInit();
  return storage + ArchiveSpacePerThread();
}


char* Debug::RestoreDebug(char* storage) {
  // Simply reset state. Don't restore anything.
  ThreadInit();
  return storage + ArchiveSpacePerThread();
}

int Debug::ArchiveSpacePerThread() { return 0; }

void Debug::Iterate(ObjectVisitor* v) {
  v->VisitPointer(&thread_local_.suspended_generator_);
}

DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
  // Globalize the request debug info object and make it weak.
  GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
  debug_info_ =
      Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
}


DebugInfoListNode::~DebugInfoListNode() {
  if (debug_info_ == nullptr) return;
  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
  debug_info_ = nullptr;
}


bool Debug::Load() {
  // Return if debugger is already loaded.
  if (is_loaded()) return true;

  // Bail out if we're already in the process of compiling the native
  // JavaScript source code for the debugger.
  if (is_suppressed_) return false;
  SuppressDebug while_loading(this);

  // Disable breakpoints and interrupts while compiling and running the
  // debugger scripts including the context creation code.
  DisableBreak disable(this, true);
  PostponeInterruptsScope postpone(isolate_);

  // Create the debugger context.
  HandleScope scope(isolate_);
  ExtensionConfiguration no_extensions;
  // TODO(yangguo): we rely on the fact that first context snapshot is usable
  //                as debug context. This dependency is gone once we remove
  //                debug context completely.
  static const int kFirstContextSnapshotIndex = 0;
  Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
      MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
      kFirstContextSnapshotIndex, DEBUG_CONTEXT);

  // Fail if no context could be created.
  if (context.is_null()) return false;

  debug_context_ = Handle<Context>::cast(
      isolate_->global_handles()->Create(*context));

  feature_tracker()->Track(DebugFeatureTracker::kActive);

  return true;
}


void Debug::Unload() {
  ClearAllBreakPoints();
  ClearStepping();

  // Return debugger is not loaded.
  if (!is_loaded()) return;

  // Clear debugger context global handle.
  GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
  debug_context_ = Handle<Context>();
}

void Debug::Break(JavaScriptFrame* frame) {
  HandleScope scope(isolate_);

  // Initialize LiveEdit.
  LiveEdit::InitializeThreadLocal(this);

  // Just continue if breaks are disabled or debugger cannot be loaded.
  if (break_disabled()) return;

  // Enter the debugger.
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Postpone interrupt during breakpoint processing.
  PostponeInterruptsScope postpone(isolate_);

  // Get the debug info (create it if it does not exist).
  Handle<JSFunction> function(frame->function());
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
    // Return if we failed to retrieve the debug info.
    return;
  }
  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);

  // Find the break location where execution has stopped.
  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);

  // Find actual break points, if any, and trigger debug break event.
  Handle<Object> break_points_hit = CheckBreakPoints(&location);
  if (!break_points_hit->IsUndefined(isolate_)) {
    // Clear all current stepping setup.
    ClearStepping();
    // Notify the debug event listeners.
    OnDebugBreak(break_points_hit, false);
    return;
  }

  // No break point. Check for stepping.
  StepAction step_action = last_step_action();
  Address current_fp = frame->UnpaddedFP();
  Address target_fp = thread_local_.target_fp_;
  Address last_fp = thread_local_.last_fp_;

  bool step_break = false;
  switch (step_action) {
    case StepNone:
      return;
    case StepOut:
      // Step out has not reached the target frame yet.
      if (current_fp < target_fp) return;
      step_break = true;
      break;
    case StepNext:
      // Step next should not break in a deeper frame.
      if (current_fp < target_fp) return;
      // For step-next, a tail call is like a return and should break.
      step_break = location.IsTailCall();
    // Fall through.
    case StepIn: {
      FrameSummary summary = FrameSummary::GetFirst(frame);
      int offset = summary.code_offset();
      step_break = step_break || location.IsReturn() ||
                   (current_fp != last_fp) ||
                   (thread_local_.last_statement_position_ !=
                    location.abstract_code()->SourceStatementPosition(offset));
      break;
    }
    case StepFrame:
      step_break = current_fp != last_fp;
      break;
  }

  // Clear all current stepping setup.
  ClearStepping();

  if (step_break) {
    // Notify the debug event listeners.
    OnDebugBreak(isolate_->factory()->undefined_value(), false);
  } else {
    // Re-prepare to continue.
    PrepareStep(step_action);
  }
}


// Find break point objects for this location, if any, and evaluate them.
// Return an array of break point objects that evaluated true.
Handle<Object> Debug::CheckBreakPoints(BreakLocation* location,
                                       bool* has_break_points) {
  Factory* factory = isolate_->factory();
  bool has_break_points_to_check =
      break_points_active_ && location->HasBreakPoint();
  if (has_break_points) *has_break_points = has_break_points_to_check;
  if (!has_break_points_to_check) return factory->undefined_value();

  Handle<Object> break_point_objects = location->BreakPointObjects();
  // Count the number of break points hit. If there are multiple break points
  // they are in a FixedArray.
  Handle<FixedArray> break_points_hit;
  int break_points_hit_count = 0;
  DCHECK(!break_point_objects->IsUndefined(isolate_));
  if (break_point_objects->IsFixedArray()) {
    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
    break_points_hit = factory->NewFixedArray(array->length());
    for (int i = 0; i < array->length(); i++) {
      Handle<Object> break_point_object(array->get(i), isolate_);
      if (CheckBreakPoint(break_point_object)) {
        break_points_hit->set(break_points_hit_count++, *break_point_object);
      }
    }
  } else {
    break_points_hit = factory->NewFixedArray(1);
    if (CheckBreakPoint(break_point_objects)) {
      break_points_hit->set(break_points_hit_count++, *break_point_objects);
    }
  }
  if (break_points_hit_count == 0) return factory->undefined_value();
  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
  result->set_length(Smi::FromInt(break_points_hit_count));
  return result;
}


bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
  // A break location is considered muted if break locations on the current
  // statement have at least one break point, and all of these break points
  // evaluate to false. Aside from not triggering a debug break event at the
  // break location, we also do not trigger one for debugger statements, nor
  // an exception event on exception at this location.
  Object* fun = frame->function();
  if (!fun->IsJSFunction()) return false;
  JSFunction* function = JSFunction::cast(fun);
  if (!function->shared()->HasDebugInfo()) return false;
  HandleScope scope(isolate_);
  Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
  // Enter the debugger.
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return false;
  BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
  List<BreakLocation> break_locations;
  BreakLocation::AllForStatementPosition(
      debug_info, current_position.statement_position(), &break_locations);
  bool has_break_points_at_all = false;
  for (int i = 0; i < break_locations.length(); i++) {
    bool has_break_points;
    Handle<Object> check_result =
        CheckBreakPoints(&break_locations[i], &has_break_points);
    has_break_points_at_all |= has_break_points;
    if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
  }
  return has_break_points_at_all;
}


MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
                                        Handle<Object> args[]) {
  PostponeInterruptsScope no_interrupts(isolate_);
  AssertDebugContext();
  Handle<JSReceiver> holder =
      Handle<JSReceiver>::cast(isolate_->natives_utils_object());
  Handle<JSFunction> fun = Handle<JSFunction>::cast(
      JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
  Handle<Object> undefined = isolate_->factory()->undefined_value();
  return Execution::TryCall(isolate_, fun, undefined, argc, args);
}


// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
  Factory* factory = isolate_->factory();
  HandleScope scope(isolate_);

  // Ignore check if break point object is not a JSObject.
  if (!break_point_object->IsJSObject()) return true;

  // Get the break id as an object.
  Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());

  // Call IsBreakPointTriggered.
  Handle<Object> argv[] = { break_id, break_point_object };
  Handle<Object> result;
  if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
           .ToHandle(&result)) {
    return false;
  }

  // Return whether the break point is triggered.
  return result->IsTrue(isolate_);
}


bool Debug::SetBreakPoint(Handle<JSFunction> function,
                          Handle<Object> break_point_object,
                          int* source_position) {
  HandleScope scope(isolate_);

  // Make sure the function is compiled and has set up the debug info.
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
    // Return if retrieving debug info failed.
    return true;
  }

  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  // Source positions starts with zero.
  DCHECK(*source_position >= 0);

  // Find the break point and change it.
  BreakLocation location = BreakLocation::FromPosition(
      debug_info, *source_position, STATEMENT_ALIGNED);
  *source_position = location.statement_position();
  location.SetBreakPoint(break_point_object);

  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);

  // At least one active break point now.
  return debug_info->GetBreakPointCount() > 0;
}


bool Debug::SetBreakPointForScript(Handle<Script> script,
                                   Handle<Object> break_point_object,
                                   int* source_position,
                                   BreakPositionAlignment alignment) {
  HandleScope scope(isolate_);

  // Obtain shared function info for the function.
  Handle<Object> result =
      FindSharedFunctionInfoInScript(script, *source_position);
  if (result->IsUndefined(isolate_)) return false;

  // Make sure the function has set up the debug info.
  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
  if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
    // Return if retrieving debug info failed.
    return false;
  }

  // Find position within function. The script position might be before the
  // source position of the first function.
  int position;
  if (shared->start_position() > *source_position) {
    position = 0;
  } else {
    position = *source_position - shared->start_position();
  }

  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  // Source positions starts with zero.
  DCHECK(position >= 0);

  // Find the break point and change it.
  BreakLocation location =
      BreakLocation::FromPosition(debug_info, position, alignment);
  location.SetBreakPoint(break_point_object);

  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);

  position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
                                              : location.position();

  *source_position = position + shared->start_position();

  // At least one active break point now.
  DCHECK(debug_info->GetBreakPointCount() > 0);
  return true;
}


void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
  HandleScope scope(isolate_);

  DebugInfoListNode* node = debug_info_list_;
  while (node != NULL) {
    Handle<Object> result =
        DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
    if (!result->IsUndefined(isolate_)) {
      // Get information in the break point.
      Handle<BreakPointInfo> break_point_info =
          Handle<BreakPointInfo>::cast(result);
      Handle<DebugInfo> debug_info = node->debug_info();

      BreakLocation location = BreakLocation::FromCodeOffset(
          debug_info, break_point_info->code_offset());
      location.ClearBreakPoint(break_point_object);

      // If there are no more break points left remove the debug info for this
      // function.
      if (debug_info->GetBreakPointCount() == 0) {
        RemoveDebugInfoAndClearFromShared(debug_info);
      }

      return;
    }
    node = node->next();
  }
}


// Clear out all the debug break code. This is ONLY supposed to be used when
// shutting down the debugger as it will leave the break point information in
// DebugInfo even though the code is patched back to the non break point state.
void Debug::ClearAllBreakPoints() {
  for (DebugInfoListNode* node = debug_info_list_; node != NULL;
       node = node->next()) {
    for (base::SmartPointer<BreakLocation::Iterator> it(
             BreakLocation::GetIterator(node->debug_info()));
         !it->Done(); it->Next()) {
      it->GetBreakLocation().ClearDebugBreak();
    }
  }
  // Remove all debug info.
  while (debug_info_list_ != NULL) {
    RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
  }
}


void Debug::FloodWithOneShot(Handle<JSFunction> function,
                             BreakLocatorType type) {
  // Debug utility functions are not subject to debugging.
  if (function->native_context() == *debug_context()) return;

  if (!function->shared()->IsSubjectToDebugging()) {
    // Builtin functions are not subject to stepping, but need to be
    // deoptimized, because optimized code does not check for debug
    // step in at call sites.
    Deoptimizer::DeoptimizeFunction(*function);
    return;
  }
  // Make sure the function is compiled and has set up the debug info.
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
    // Return if we failed to retrieve the debug info.
    return;
  }

  // Flood the function with break points.
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  for (base::SmartPointer<BreakLocation::Iterator> it(
           BreakLocation::GetIterator(debug_info, type));
       !it->Done(); it->Next()) {
    it->GetBreakLocation().SetOneShot();
  }
}


void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
  if (type == BreakUncaughtException) {
    break_on_uncaught_exception_ = enable;
  } else {
    break_on_exception_ = enable;
  }
}


bool Debug::IsBreakOnException(ExceptionBreakType type) {
  if (type == BreakUncaughtException) {
    return break_on_uncaught_exception_;
  } else {
    return break_on_exception_;
  }
}


void Debug::PrepareStepIn(Handle<JSFunction> function) {
  CHECK(last_step_action() >= StepIn);
  if (!is_active()) return;
  if (in_debug_scope()) return;
  FloodWithOneShot(function);
}

void Debug::PrepareStepInSuspendedGenerator() {
  CHECK(has_suspended_generator());
  if (!is_active()) return;
  if (in_debug_scope()) return;
  thread_local_.last_step_action_ = StepIn;
  Handle<JSFunction> function(
      JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
  FloodWithOneShot(function);
  clear_suspended_generator();
}

void Debug::PrepareStepOnThrow() {
  if (!is_active()) return;
  if (last_step_action() == StepNone) return;
  if (in_debug_scope()) return;

  ClearOneShot();

  // Iterate through the JavaScript stack looking for handlers.
  JavaScriptFrameIterator it(isolate_);
  while (!it.done()) {
    JavaScriptFrame* frame = it.frame();
    if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
    it.Advance();
  }

  if (last_step_action() == StepNext) {
    while (!it.done()) {
      Address current_fp = it.frame()->UnpaddedFP();
      if (current_fp >= thread_local_.target_fp_) break;
      it.Advance();
    }
  }

  // Find the closest Javascript frame we can flood with one-shots.
  while (!it.done() &&
         !it.frame()->function()->shared()->IsSubjectToDebugging()) {
    it.Advance();
  }

  if (it.done()) return;  // No suitable Javascript catch handler.

  FloodWithOneShot(Handle<JSFunction>(it.frame()->function()));
}


void Debug::PrepareStep(StepAction step_action) {
  HandleScope scope(isolate_);

  DCHECK(in_debug_scope());

  // Get the frame where the execution has stopped and skip the debug frame if
  // any. The debug frame will only be present if execution was stopped due to
  // hitting a break point. In other situations (e.g. unhandled exception) the
  // debug frame is not present.
  StackFrame::Id frame_id = break_frame_id();
  // If there is no JavaScript stack don't do anything.
  if (frame_id == StackFrame::NO_ID) return;

  JavaScriptFrameIterator frames_it(isolate_, frame_id);
  JavaScriptFrame* frame = frames_it.frame();

  feature_tracker()->Track(DebugFeatureTracker::kStepping);

  thread_local_.last_step_action_ = step_action;

  // If the function on the top frame is unresolved perform step out. This will
  // be the case when calling unknown function and having the debugger stopped
  // in an unhandled exception.
  if (!frame->function()->IsJSFunction()) {
    // Step out: Find the calling JavaScript frame and flood it with
    // breakpoints.
    frames_it.Advance();
    // Fill the function to return to with one-shot break points.
    JSFunction* function = frames_it.frame()->function();
    FloodWithOneShot(Handle<JSFunction>(function));
    return;
  }

  // Get the debug info (create it if it does not exist).
  FrameSummary summary = FrameSummary::GetFirst(frame);
  Handle<JSFunction> function(summary.function());
  Handle<SharedFunctionInfo> shared(function->shared());
  if (!EnsureDebugInfo(shared, function)) {
    // Return if ensuring debug info failed.
    return;
  }

  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  // Refresh frame summary if the code has been recompiled for debugging.
  if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
    summary = FrameSummary::GetFirst(frame);
  }

  int call_offset =
      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
  BreakLocation location =
      BreakLocation::FromCodeOffset(debug_info, call_offset);

  // Any step at a return is a step-out.
  if (location.IsReturn()) step_action = StepOut;
  // A step-next at a tail call is a step-out.
  if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;

  thread_local_.last_statement_position_ =
      debug_info->abstract_code()->SourceStatementPosition(
          summary.code_offset());
  thread_local_.last_fp_ = frame->UnpaddedFP();
  // No longer perform the current async step.
  clear_suspended_generator();

  switch (step_action) {
    case StepNone:
      UNREACHABLE();
      break;
    case StepOut:
      // Advance to caller frame.
      frames_it.Advance();
      // Skip native and extension functions on the stack.
      while (!frames_it.done() &&
             !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) {
        // Builtin functions are not subject to stepping, but need to be
        // deoptimized to include checks for step-in at call sites.
        Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
        frames_it.Advance();
      }
      if (!frames_it.done()) {
        // Fill the caller function to return to with one-shot break points.
        Handle<JSFunction> caller_function(frames_it.frame()->function());
        FloodWithOneShot(caller_function);
        thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP();
      }
      // Clear last position info. For stepping out it does not matter.
      thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
      thread_local_.last_fp_ = 0;
      break;
    case StepNext:
      thread_local_.target_fp_ = frame->UnpaddedFP();
      FloodWithOneShot(function);
      break;
    case StepIn:
      FloodWithOneShot(function);
      break;
    case StepFrame:
      // No point in setting one-shot breaks at places where we are not about
      // to leave the current frame.
      FloodWithOneShot(function, CALLS_AND_RETURNS);
      break;
  }
}


// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
    Handle<SharedFunctionInfo> shared,
    BreakPositionAlignment position_alignment) {
  Isolate* isolate = shared->GetIsolate();
  if (!shared->HasDebugInfo()) {
    return isolate->factory()->undefined_value();
  }
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  if (debug_info->GetBreakPointCount() == 0) {
    return isolate->factory()->undefined_value();
  }
  Handle<FixedArray> locations =
      isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
  int count = 0;
  for (int i = 0; i < debug_info->break_points()->length(); ++i) {
    if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
      BreakPointInfo* break_point_info =
          BreakPointInfo::cast(debug_info->break_points()->get(i));
      int break_points = break_point_info->GetBreakPointCount();
      if (break_points == 0) continue;
      Smi* position = NULL;
      switch (position_alignment) {
        case STATEMENT_ALIGNED:
          position = Smi::FromInt(break_point_info->statement_position());
          break;
        case BREAK_POSITION_ALIGNED:
          position = Smi::FromInt(break_point_info->source_position());
          break;
      }
      for (int j = 0; j < break_points; ++j) locations->set(count++, position);
    }
  }
  return locations;
}


void Debug::ClearStepping() {
  // Clear the various stepping setup.
  ClearOneShot();

  thread_local_.last_step_action_ = StepNone;
  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
  thread_local_.last_fp_ = 0;
  thread_local_.target_fp_ = 0;
}


// Clears all the one-shot break points that are currently set. Normally this
// function is called each time a break point is hit as one shot break points
// are used to support stepping.
void Debug::ClearOneShot() {
  // The current implementation just runs through all the breakpoints. When the
  // last break point for a function is removed that function is automatically
  // removed from the list.
  for (DebugInfoListNode* node = debug_info_list_; node != NULL;
       node = node->next()) {
    for (base::SmartPointer<BreakLocation::Iterator> it(
             BreakLocation::GetIterator(node->debug_info()));
         !it->Done(); it->Next()) {
      it->GetBreakLocation().ClearOneShot();
    }
  }
}


bool MatchingCodeTargets(Code* target1, Code* target2) {
  if (target1 == target2) return true;
  if (target1->kind() != target2->kind()) return false;
  return target1->is_handler() || target1->is_inline_cache_stub();
}


// Count the number of calls before the current frame PC to find the
// corresponding PC in the newly recompiled code.
static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
                                       Address old_pc) {
  DCHECK_EQ(old_code->kind(), Code::FUNCTION);
  DCHECK_EQ(new_code->kind(), Code::FUNCTION);
  DCHECK(new_code->has_debug_break_slots());
  static const int mask = RelocInfo::kCodeTargetMask;

  // Find the target of the current call.
  Code* target = NULL;
  intptr_t delta = 0;
  for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    Address current_pc = rinfo->pc();
    // The frame PC is behind the call instruction by the call instruction size.
    if (current_pc > old_pc) break;
    delta = old_pc - current_pc;
    target = Code::GetCodeFromTargetAddress(rinfo->target_address());
  }

  // Count the number of calls to the same target before the current call.
  int index = 0;
  for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    Address current_pc = rinfo->pc();
    if (current_pc > old_pc) break;
    Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
    if (MatchingCodeTargets(target, current)) index++;
  }

  DCHECK(index > 0);

  // Repeat the count on the new code to find corresponding call.
  for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
    RelocInfo* rinfo = it.rinfo();
    Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
    if (MatchingCodeTargets(target, current)) index--;
    if (index == 0) return rinfo->pc() + delta;
  }

  UNREACHABLE();
  return NULL;
}


// Count the number of continuations at which the current pc offset is at.
static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
  DCHECK_EQ(code->kind(), Code::FUNCTION);
  Address pc = code->instruction_start() + pc_offset;
  int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
  int index = 0;
  for (RelocIterator it(code, mask); !it.done(); it.next()) {
    index++;
    RelocInfo* rinfo = it.rinfo();
    Address current_pc = rinfo->pc();
    if (current_pc == pc) break;
    DCHECK(current_pc < pc);
  }
  return index;
}


// Find the pc offset for the given continuation index.
static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
  DCHECK_EQ(code->kind(), Code::FUNCTION);
  DCHECK(code->has_debug_break_slots());
  int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
  RelocIterator it(code, mask);
  for (int i = 1; i < index; i++) it.next();
  return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
}


class RedirectActiveFunctions : public ThreadVisitor {
 public:
  explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
      : shared_(shared) {
    DCHECK(shared->HasDebugCode());
  }

  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
    for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
      JavaScriptFrame* frame = it.frame();
      JSFunction* function = frame->function();
      if (frame->is_optimized()) continue;
      if (!function->Inlines(shared_)) continue;

      if (frame->is_interpreted()) {
        InterpretedFrame* interpreted_frame =
            reinterpret_cast<InterpretedFrame*>(frame);
        BytecodeArray* debug_copy =
            shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray();
        interpreted_frame->PatchBytecodeArray(debug_copy);
        continue;
      }

      Code* frame_code = frame->LookupCode();
      DCHECK(frame_code->kind() == Code::FUNCTION);
      if (frame_code->has_debug_break_slots()) continue;

      Code* new_code = function->shared()->code();
      Address old_pc = frame->pc();
      Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);

      if (FLAG_trace_deopt) {
        PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
               "\n",
               reinterpret_cast<intptr_t>(old_pc),
               reinterpret_cast<intptr_t>(new_pc));
      }

      if (FLAG_enable_embedded_constant_pool) {
        // Update constant pool pointer for new code.
        frame->set_constant_pool(new_code->constant_pool());
      }

      // Patch the return address to return into the code with
      // debug break slots.
      frame->set_pc(new_pc);
    }
  }

 private:
  SharedFunctionInfo* shared_;
  DisallowHeapAllocation no_gc_;
};


bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
  DCHECK(shared->is_compiled());

  if (isolate_->concurrent_recompilation_enabled()) {
    isolate_->optimizing_compile_dispatcher()->Flush();
  }

  List<Handle<JSFunction> > functions;
  List<Handle<JSGeneratorObject> > suspended_generators;

  // Flush all optimized code maps. Note that the below heap iteration does not
  // cover this, because the given function might have been inlined into code
  // for which no JSFunction exists.
  {
    SharedFunctionInfo::Iterator iterator(isolate_);
    while (SharedFunctionInfo* shared = iterator.Next()) {
      shared->ClearCodeFromOptimizedCodeMap();
    }
  }

  // Make sure we abort incremental marking.
  isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                                      "prepare for break points");

  DCHECK(shared->is_compiled());
  bool is_interpreted = shared->HasBytecodeArray();

  {
    // TODO(yangguo): with bytecode, we still walk the heap to find all
    // optimized code for the function to deoptimize. We can probably be
    // smarter here and avoid the heap walk.
    HeapIterator iterator(isolate_->heap());
    HeapObject* obj;
    bool find_resumables = !is_interpreted && shared->is_resumable();

    while ((obj = iterator.next())) {
      if (obj->IsJSFunction()) {
        JSFunction* function = JSFunction::cast(obj);
        if (!function->Inlines(*shared)) continue;
        if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
          Deoptimizer::DeoptimizeFunction(function);
        }
        if (is_interpreted) continue;
        if (function->shared() == *shared) functions.Add(handle(function));
      } else if (find_resumables && obj->IsJSGeneratorObject()) {
        // This case handles async functions as well, as they use generator
        // objects for in-progress async function execution.
        JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
        if (!generator_obj->is_suspended()) continue;
        JSFunction* function = generator_obj->function();
        if (!function->Inlines(*shared)) continue;
        int pc_offset = generator_obj->continuation();
        int index =
            ComputeContinuationIndexFromPcOffset(function->code(), pc_offset);
        generator_obj->set_continuation(index);
        suspended_generators.Add(handle(generator_obj));
      }
    }
  }

  // We do not need to replace code to debug bytecode.
  DCHECK(!is_interpreted || functions.length() == 0);
  DCHECK(!is_interpreted || suspended_generators.length() == 0);

  // We do not need to recompile to debug bytecode.
  if (!is_interpreted && !shared->HasDebugCode()) {
    DCHECK(functions.length() > 0);
    if (!Compiler::CompileDebugCode(functions.first())) return false;
  }

  for (Handle<JSFunction> const function : functions) {
    function->ReplaceCode(shared->code());
    JSFunction::EnsureLiterals(function);
  }

  for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
    int index = generator_obj->continuation();
    int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index);
    generator_obj->set_continuation(pc_offset);
  }

  // Update PCs on the stack to point to recompiled code.
  RedirectActiveFunctions redirect_visitor(*shared);
  redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
  isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);

  return true;
}

void Debug::RecordAsyncFunction(Handle<JSGeneratorObject> generator_object) {
  if (last_step_action() <= StepOut) return;
  if (!generator_object->function()->shared()->is_async()) return;
  DCHECK(!has_suspended_generator());
  thread_local_.suspended_generator_ = *generator_object;
  ClearStepping();
}

class SharedFunctionInfoFinder {
 public:
  explicit SharedFunctionInfoFinder(int target_position)
      : current_candidate_(NULL),
        current_candidate_closure_(NULL),
        current_start_position_(RelocInfo::kNoPosition),
        target_position_(target_position) {}

  void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
    if (!shared->IsSubjectToDebugging()) return;
    int start_position = shared->function_token_position();
    if (start_position == RelocInfo::kNoPosition) {
      start_position = shared->start_position();
    }

    if (start_position > target_position_) return;
    if (target_position_ > shared->end_position()) return;

    if (current_candidate_ != NULL) {
      if (current_start_position_ == start_position &&
          shared->end_position() == current_candidate_->end_position()) {
        // If we already have a matching closure, do not throw it away.
        if (current_candidate_closure_ != NULL && closure == NULL) return;
        // If a top-level function contains only one function
        // declaration the source for the top-level and the function
        // is the same. In that case prefer the non top-level function.
        if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
      } else if (start_position < current_start_position_ ||
                 current_candidate_->end_position() < shared->end_position()) {
        return;
      }
    }

    current_start_position_ = start_position;
    current_candidate_ = shared;
    current_candidate_closure_ = closure;
  }

  SharedFunctionInfo* Result() { return current_candidate_; }

  JSFunction* ResultClosure() { return current_candidate_closure_; }

 private:
  SharedFunctionInfo* current_candidate_;
  JSFunction* current_candidate_closure_;
  int current_start_position_;
  int target_position_;
  DisallowHeapAllocation no_gc_;
};


// We need to find a SFI for a literal that may not yet have been compiled yet,
// and there may not be a JSFunction referencing it. Find the SFI closest to
// the given position, compile it to reveal possible inner SFIs and repeat.
// While we are at this, also ensure code with debug break slots so that we do
// not have to compile a SFI without JSFunction, which is paifu for those that
// cannot be compiled without context (need to find outer compilable SFI etc.)
Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
                                                     int position) {
  for (int iteration = 0;; iteration++) {
    // Go through all shared function infos associated with this script to
    // find the inner most function containing this position.
    // If there is no shared function info for this script at all, there is
    // no point in looking for it by walking the heap.
    if (!script->shared_function_infos()->IsWeakFixedArray()) break;

    SharedFunctionInfo* shared;
    {
      SharedFunctionInfoFinder finder(position);
      WeakFixedArray::Iterator iterator(script->shared_function_infos());
      SharedFunctionInfo* candidate;
      while ((candidate = iterator.Next<SharedFunctionInfo>())) {
        finder.NewCandidate(candidate);
      }
      shared = finder.Result();
      if (shared == NULL) break;
      // We found it if it's already compiled and has debug code.
      if (shared->HasDebugCode()) {
        Handle<SharedFunctionInfo> shared_handle(shared);
        // If the iteration count is larger than 1, we had to compile the outer
        // function in order to create this shared function info. So there can
        // be no JSFunction referencing it. We can anticipate creating a debug
        // info while bypassing PrepareFunctionForBreakpoints.
        if (iteration > 1) {
          AllowHeapAllocation allow_before_return;
          CreateDebugInfo(shared_handle);
        }
        return shared_handle;
      }
    }
    // If not, compile to reveal inner functions, if possible.
    if (shared->allows_lazy_compilation_without_context()) {
      HandleScope scope(isolate_);
      if (!Compiler::CompileDebugCode(handle(shared))) break;
      continue;
    }

    // If not possible, comb the heap for the best suitable compile target.
    JSFunction* closure;
    {
      HeapIterator it(isolate_->heap());
      SharedFunctionInfoFinder finder(position);
      while (HeapObject* object = it.next()) {
        JSFunction* candidate_closure = NULL;
        SharedFunctionInfo* candidate = NULL;
        if (object->IsJSFunction()) {
          candidate_closure = JSFunction::cast(object);
          candidate = candidate_closure->shared();
        } else if (object->IsSharedFunctionInfo()) {
          candidate = SharedFunctionInfo::cast(object);
          if (!candidate->allows_lazy_compilation_without_context()) continue;
        } else {
          continue;
        }
        if (candidate->script() == *script) {
          finder.NewCandidate(candidate, candidate_closure);
        }
      }
      closure = finder.ResultClosure();
      shared = finder.Result();
    }
    if (shared == NULL) break;
    HandleScope scope(isolate_);
    if (closure == NULL) {
      if (!Compiler::CompileDebugCode(handle(shared))) break;
    } else {
      if (!Compiler::CompileDebugCode(handle(closure))) break;
    }
  }
  return isolate_->factory()->undefined_value();
}


// Ensures the debug information is present for shared.
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
                            Handle<JSFunction> function) {
  if (!shared->IsSubjectToDebugging()) return false;

  // Return if we already have the debug info for shared.
  if (shared->HasDebugInfo()) return true;

  if (function.is_null()) {
    DCHECK(shared->HasDebugCode());
  } else if (!Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
    return false;
  }

  if (shared->HasBytecodeArray()) {
    // To prepare bytecode for debugging, we already need to have the debug
    // info (containing the debug copy) upfront, but since we do not recompile,
    // preparing for break points cannot fail.
    CreateDebugInfo(shared);
    CHECK(PrepareFunctionForBreakPoints(shared));
  } else {
    if (!PrepareFunctionForBreakPoints(shared)) return false;
    CreateDebugInfo(shared);
  }
  return true;
}


void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) {
  // Create the debug info object.
  DCHECK(shared->HasDebugCode());
  Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);

  // Add debug info to the list.
  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
  node->set_next(debug_info_list_);
  debug_info_list_ = node;
}


void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
  HandleScope scope(isolate_);
  Handle<SharedFunctionInfo> shared(debug_info->shared());

  DCHECK_NOT_NULL(debug_info_list_);
  // Run through the debug info objects to find this one and remove it.
  DebugInfoListNode* prev = NULL;
  DebugInfoListNode* current = debug_info_list_;
  while (current != NULL) {
    if (current->debug_info().is_identical_to(debug_info)) {
      // Unlink from list. If prev is NULL we are looking at the first element.
      if (prev == NULL) {
        debug_info_list_ = current->next();
      } else {
        prev->set_next(current->next());
      }
      delete current;
      shared->set_debug_info(DebugInfo::uninitialized());
      return;
    }
    // Move to next in list.
    prev = current;
    current = current->next();
  }

  UNREACHABLE();
}

void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
  after_break_target_ = NULL;
  if (!LiveEdit::SetAfterBreakTarget(this)) {
    // Continue just after the slot.
    after_break_target_ = frame->pc();
  }
}


bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
  HandleScope scope(isolate_);

  // Get the executing function in which the debug break occurred.
  Handle<JSFunction> function(JSFunction::cast(frame->function()));
  Handle<SharedFunctionInfo> shared(function->shared());

  // With no debug info there are no break points, so we can't be at a return.
  if (!shared->HasDebugInfo()) return false;

  DCHECK(!frame->is_optimized());
  FrameSummary summary = FrameSummary::GetFirst(frame);

  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  BreakLocation location =
      BreakLocation::FromCodeOffset(debug_info, summary.code_offset());
  return location.IsReturn() || location.IsTailCall();
}


void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
                                  LiveEdit::FrameDropMode mode) {
  if (mode != LiveEdit::CURRENTLY_SET_MODE) {
    thread_local_.frame_drop_mode_ = mode;
  }
  thread_local_.break_frame_id_ = new_break_frame_id;
}


bool Debug::IsDebugGlobal(JSGlobalObject* global) {
  return is_loaded() && global == debug_context()->global_object();
}


void Debug::ClearMirrorCache() {
  PostponeInterruptsScope postpone(isolate_);
  HandleScope scope(isolate_);
  CallFunction("ClearMirrorCache", 0, NULL);
}


Handle<FixedArray> Debug::GetLoadedScripts() {
  isolate_->heap()->CollectAllGarbage();
  Factory* factory = isolate_->factory();
  if (!factory->script_list()->IsWeakFixedArray()) {
    return factory->empty_fixed_array();
  }
  Handle<WeakFixedArray> array =
      Handle<WeakFixedArray>::cast(factory->script_list());
  Handle<FixedArray> results = factory->NewFixedArray(array->Length());
  int length = 0;
  {
    Script::Iterator iterator(isolate_);
    Script* script;
    while ((script = iterator.Next())) {
      if (script->HasValidSource()) results->set(length++, script);
    }
  }
  results->Shrink(length);
  return results;
}


MaybeHandle<Object> Debug::MakeExecutionState() {
  // Create the execution state object.
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
  return CallFunction("MakeExecutionState", arraysize(argv), argv);
}


MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
  // Create the new break event object.
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
                            break_points_hit };
  return CallFunction("MakeBreakEvent", arraysize(argv), argv);
}


MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
                                              bool uncaught,
                                              Handle<Object> promise) {
  // Create the new exception event object.
  Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
                            exception,
                            isolate_->factory()->ToBoolean(uncaught),
                            promise };
  return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
}


MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
                                            v8::DebugEvent type) {
  // Create the compile event object.
  Handle<Object> script_wrapper = Script::GetWrapper(script);
  Handle<Object> argv[] = { script_wrapper,
                            isolate_->factory()->NewNumberFromInt(type) };
  return CallFunction("MakeCompileEvent", arraysize(argv), argv);
}


MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
  // Create the async task event object.
  Handle<Object> argv[] = { task_event };
  return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
}


void Debug::OnThrow(Handle<Object> exception) {
  if (in_debug_scope() || ignore_events()) return;
  PrepareStepOnThrow();
  // Temporarily clear any scheduled_exception to allow evaluating
  // JavaScript from the debug event handler.
  HandleScope scope(isolate_);
  Handle<Object> scheduled_exception;
  if (isolate_->has_scheduled_exception()) {
    scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
    isolate_->clear_scheduled_exception();
  }
  OnException(exception, isolate_->GetPromiseOnStackOnThrow());
  if (!scheduled_exception.is_null()) {
    isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
  }
}


void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
  if (in_debug_scope() || ignore_events()) return;
  HandleScope scope(isolate_);
  // Check whether the promise has been marked as having triggered a message.
  Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate_)) {
    OnException(value, promise);
  }
}


MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
    Handle<JSObject> promise) {
  Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler();
  return Execution::Call(isolate_, fun, promise, 0, NULL);
}


void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
  // In our prediction, try-finally is not considered to catch.
  Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
  bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
  if (promise->IsJSObject()) {
    Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
    // Mark the promise as already having triggered a message.
    Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
    JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
    // Check whether the promise reject is considered an uncaught exception.
    Handle<Object> has_reject_handler;
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
        isolate_, has_reject_handler,
        PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
    uncaught = has_reject_handler->IsFalse(isolate_);
  }
  // Bail out if exception breaks are not active
  if (uncaught) {
    // Uncaught exceptions are reported by either flags.
    if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
  } else {
    // Caught exceptions are reported is activated.
    if (!break_on_exception_) return;
  }

  {
    // Check whether the break location is muted.
    JavaScriptFrameIterator it(isolate_);
    if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return;
  }

  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Create the event data object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeExceptionEvent(
          exception, uncaught, promise).ToHandle(&event_data)) {
    return;
  }

  // Process debug event.
  ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
  // Return to continue execution from where the exception was thrown.
}


void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
  // The caller provided for DebugScope.
  AssertDebugContext();
  // Bail out if there is no listener for this event
  if (ignore_events()) return;

#ifdef DEBUG
  PrintBreakLocation();
#endif  // DEBUG

  HandleScope scope(isolate_);
  // Create the event data object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;

  // Process debug event.
  ProcessDebugEvent(v8::Break,
                    Handle<JSObject>::cast(event_data),
                    auto_continue);
}


void Debug::OnCompileError(Handle<Script> script) {
  ProcessCompileEvent(v8::CompileError, script);
}


void Debug::OnBeforeCompile(Handle<Script> script) {
  ProcessCompileEvent(v8::BeforeCompile, script);
}


// Handle debugger actions when a new script is compiled.
void Debug::OnAfterCompile(Handle<Script> script) {
  ProcessCompileEvent(v8::AfterCompile, script);
}


void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
  if (in_debug_scope() || ignore_events()) return;

  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Create the script collected state object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;

  // Process debug event.
  ProcessDebugEvent(v8::AsyncTaskEvent,
                    Handle<JSObject>::cast(event_data),
                    true);
}


void Debug::ProcessDebugEvent(v8::DebugEvent event,
                              Handle<JSObject> event_data,
                              bool auto_continue) {
  HandleScope scope(isolate_);

  // Create the execution state.
  Handle<Object> exec_state;
  // Bail out and don't call debugger if exception.
  if (!MakeExecutionState().ToHandle(&exec_state)) return;

  // First notify the message handler if any.
  if (message_handler_ != NULL) {
    NotifyMessageHandler(event,
                         Handle<JSObject>::cast(exec_state),
                         event_data,
                         auto_continue);
  }
  // Notify registered debug event listener. This can be either a C or
  // a JavaScript function. Don't call event listener for v8::Break
  // here, if it's only a debug command -- they will be processed later.
  if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
    CallEventCallback(event, exec_state, event_data, NULL);
  }
}


void Debug::CallEventCallback(v8::DebugEvent event,
                              Handle<Object> exec_state,
                              Handle<Object> event_data,
                              v8::Debug::ClientData* client_data) {
  // Prevent other interrupts from triggering, for example API callbacks,
  // while dispatching event listners.
  PostponeInterruptsScope postpone(isolate_);
  bool previous = in_debug_event_listener_;
  in_debug_event_listener_ = true;
  if (event_listener_->IsForeign()) {
    // Invoke the C debug event listener.
    v8::Debug::EventCallback callback =
        FUNCTION_CAST<v8::Debug::EventCallback>(
            Handle<Foreign>::cast(event_listener_)->foreign_address());
    EventDetailsImpl event_details(event,
                                   Handle<JSObject>::cast(exec_state),
                                   Handle<JSObject>::cast(event_data),
                                   event_listener_data_,
                                   client_data);
    callback(event_details);
    DCHECK(!isolate_->has_scheduled_exception());
  } else {
    // Invoke the JavaScript debug event listener.
    DCHECK(event_listener_->IsJSFunction());
    Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
                              exec_state,
                              event_data,
                              event_listener_data_ };
    Handle<JSReceiver> global = isolate_->global_proxy();
    Execution::TryCall(isolate_, Handle<JSFunction>::cast(event_listener_),
                       global, arraysize(argv), argv);
  }
  in_debug_event_listener_ = previous;
}


void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
  if (ignore_events()) return;
  SuppressDebug while_processing(this);

  bool in_nested_debug_scope = in_debug_scope();
  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  if (event == v8::AfterCompile) {
    // If debugging there might be script break points registered for this
    // script. Make sure that these break points are set.
    Handle<Object> argv[] = {Script::GetWrapper(script)};
    if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
            .is_null()) {
      return;
    }
  }

  // Create the compile state object.
  Handle<Object> event_data;
  // Bail out and don't call debugger if exception.
  if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;

  // Don't call NotifyMessageHandler if already in debug scope to avoid running
  // nested command loop.
  if (in_nested_debug_scope) {
    if (event_listener_.is_null()) return;
    // Create the execution state.
    Handle<Object> exec_state;
    // Bail out and don't call debugger if exception.
    if (!MakeExecutionState().ToHandle(&exec_state)) return;

    CallEventCallback(event, exec_state, event_data, NULL);
  } else {
    // Process debug event.
    ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true);
  }
}


Handle<Context> Debug::GetDebugContext() {
  if (!is_loaded()) return Handle<Context>();
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return Handle<Context>();
  // The global handle may be destroyed soon after.  Return it reboxed.
  return handle(*debug_context(), isolate_);
}


void Debug::NotifyMessageHandler(v8::DebugEvent event,
                                 Handle<JSObject> exec_state,
                                 Handle<JSObject> event_data,
                                 bool auto_continue) {
  // Prevent other interrupts from triggering, for example API callbacks,
  // while dispatching message handler callbacks.
  PostponeInterruptsScope no_interrupts(isolate_);
  DCHECK(is_active_);
  HandleScope scope(isolate_);
  // Process the individual events.
  bool sendEventMessage = false;
  switch (event) {
    case v8::Break:
      sendEventMessage = !auto_continue;
      break;
    case v8::NewFunction:
    case v8::BeforeCompile:
    case v8::CompileError:
    case v8::AsyncTaskEvent:
      break;
    case v8::Exception:
    case v8::AfterCompile:
      sendEventMessage = true;
      break;
  }

  // The debug command interrupt flag might have been set when the command was
  // added. It should be enough to clear the flag only once while we are in the
  // debugger.
  DCHECK(in_debug_scope());
  isolate_->stack_guard()->ClearDebugCommand();

  // Notify the debugger that a debug event has occurred unless auto continue is
  // active in which case no event is send.
  if (sendEventMessage) {
    MessageImpl message = MessageImpl::NewEvent(
        event,
        auto_continue,
        Handle<JSObject>::cast(exec_state),
        Handle<JSObject>::cast(event_data));
    InvokeMessageHandler(message);
  }

  // If auto continue don't make the event cause a break, but process messages
  // in the queue if any. For script collected events don't even process
  // messages in the queue as the execution state might not be what is expected
  // by the client.
  if (auto_continue && !has_commands()) return;

  // DebugCommandProcessor goes here.
  bool running = auto_continue;

  Handle<Object> cmd_processor_ctor =
      JSReceiver::GetProperty(isolate_, exec_state, "debugCommandProcessor")
          .ToHandleChecked();
  Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
  Handle<JSReceiver> cmd_processor = Handle<JSReceiver>::cast(
      Execution::Call(isolate_, cmd_processor_ctor, exec_state, 1, ctor_args)
          .ToHandleChecked());
  Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
      JSReceiver::GetProperty(isolate_, cmd_processor, "processDebugRequest")
          .ToHandleChecked());
  Handle<Object> is_running =
      JSReceiver::GetProperty(isolate_, cmd_processor, "isRunning")
          .ToHandleChecked();

  // Process requests from the debugger.
  do {
    // Wait for new command in the queue.
    command_received_.Wait();

    // Get the command from the queue.
    CommandMessage command = command_queue_.Get();
    isolate_->logger()->DebugTag(
        "Got request from command queue, in interactive loop.");
    if (!is_active()) {
      // Delete command text and user data.
      command.Dispose();
      return;
    }

    Vector<const uc16> command_text(
        const_cast<const uc16*>(command.text().start()),
        command.text().length());
    Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
        command_text).ToHandleChecked();
    Handle<Object> request_args[] = { request_text };
    Handle<Object> answer_value;
    Handle<String> answer;
    MaybeHandle<Object> maybe_exception;
    MaybeHandle<Object> maybe_result =
        Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1,
                           request_args, &maybe_exception);

    if (maybe_result.ToHandle(&answer_value)) {
      if (answer_value->IsUndefined(isolate_)) {
        answer = isolate_->factory()->empty_string();
      } else {
        answer = Handle<String>::cast(answer_value);
      }

      // Log the JSON request/response.
      if (FLAG_trace_debug_json) {
        PrintF("%s\n", request_text->ToCString().get());
        PrintF("%s\n", answer->ToCString().get());
      }

      Handle<Object> is_running_args[] = { answer };
      maybe_result = Execution::Call(
          isolate_, is_running, cmd_processor, 1, is_running_args);
      Handle<Object> result;
      if (!maybe_result.ToHandle(&result)) break;
      running = result->IsTrue(isolate_);
    } else {
      Handle<Object> exception;
      if (!maybe_exception.ToHandle(&exception)) break;
      Handle<Object> result;
      if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
      answer = Handle<String>::cast(result);
    }

    // Return the result.
    MessageImpl message = MessageImpl::NewResponse(
        event, running, exec_state, event_data, answer, command.client_data());
    InvokeMessageHandler(message);
    command.Dispose();

    // Return from debug event processing if either the VM is put into the
    // running state (through a continue command) or auto continue is active
    // and there are no more commands queued.
  } while (!running || has_commands());
  command_queue_.Clear();
}


void Debug::SetEventListener(Handle<Object> callback,
                             Handle<Object> data) {
  GlobalHandles* global_handles = isolate_->global_handles();

  // Remove existing entry.
  GlobalHandles::Destroy(event_listener_.location());
  event_listener_ = Handle<Object>();
  GlobalHandles::Destroy(event_listener_data_.location());
  event_listener_data_ = Handle<Object>();

  // Set new entry.
  if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) {
    event_listener_ = global_handles->Create(*callback);
    if (data.is_null()) data = isolate_->factory()->undefined_value();
    event_listener_data_ = global_handles->Create(*data);
  }

  UpdateState();
}


void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
  message_handler_ = handler;
  UpdateState();
  if (handler == NULL && in_debug_scope()) {
    // Send an empty command to the debugger if in a break to make JavaScript
    // run again if the debugger is closed.
    EnqueueCommandMessage(Vector<const uint16_t>::empty());
  }
}



void Debug::UpdateState() {
  bool is_active = message_handler_ != NULL || !event_listener_.is_null();
  if (is_active || in_debug_scope()) {
    // Note that the debug context could have already been loaded to
    // bootstrap test cases.
    isolate_->compilation_cache()->Disable();
    is_active = Load();
  } else if (is_loaded()) {
    isolate_->compilation_cache()->Enable();
    Unload();
  }
  is_active_ = is_active;
}


// Calls the registered debug message handler. This callback is part of the
// public API.
void Debug::InvokeMessageHandler(MessageImpl message) {
  if (message_handler_ != NULL) message_handler_(message);
}


// Puts a command coming from the public API on the queue.  Creates
// a copy of the command string managed by the debugger.  Up to this
// point, the command data was managed by the API client.  Called
// by the API client thread.
void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
                                  v8::Debug::ClientData* client_data) {
  // Need to cast away const.
  CommandMessage message = CommandMessage::New(
      Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
                       command.length()),
      client_data);
  isolate_->logger()->DebugTag("Put command on command_queue.");
  command_queue_.Put(message);
  command_received_.Signal();

  // Set the debug command break flag to have the command processed.
  if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
}


MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return isolate_->factory()->undefined_value();

  // Create the execution state.
  Handle<Object> exec_state;
  if (!MakeExecutionState().ToHandle(&exec_state)) {
    return isolate_->factory()->undefined_value();
  }

  Handle<Object> argv[] = { exec_state, data };
  return Execution::Call(
      isolate_,
      fun,
      Handle<Object>(debug_context()->global_proxy(), isolate_),
      arraysize(argv),
      argv);
}


void Debug::HandleDebugBreak() {
  // Ignore debug break during bootstrapping.
  if (isolate_->bootstrapper()->IsActive()) return;
  // Just continue if breaks are disabled.
  if (break_disabled()) return;
  // Ignore debug break if debugger is not active.
  if (!is_active()) return;

  StackLimitCheck check(isolate_);
  if (check.HasOverflowed()) return;

  { JavaScriptFrameIterator it(isolate_);
    DCHECK(!it.done());
    Object* fun = it.frame()->function();
    if (fun && fun->IsJSFunction()) {
      // Don't stop in builtin functions.
      if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
      JSGlobalObject* global =
          JSFunction::cast(fun)->context()->global_object();
      // Don't stop in debugger functions.
      if (IsDebugGlobal(global)) return;
      // Don't stop if the break location is muted.
      if (IsMutedAtCurrentLocation(it.frame())) return;
    }
  }

  // Collect the break state before clearing the flags.
  bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
                            !isolate_->stack_guard()->CheckDebugBreak();

  isolate_->stack_guard()->ClearDebugBreak();

  // Clear stepping to avoid duplicate breaks.
  ClearStepping();

  ProcessDebugMessages(debug_command_only);
}


void Debug::ProcessDebugMessages(bool debug_command_only) {
  isolate_->stack_guard()->ClearDebugCommand();

  StackLimitCheck check(isolate_);
  if (check.HasOverflowed()) return;

  HandleScope scope(isolate_);
  DebugScope debug_scope(this);
  if (debug_scope.failed()) return;

  // Notify the debug event listeners. Indicate auto continue if the break was
  // a debug command break.
  OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
}

#ifdef DEBUG
void Debug::PrintBreakLocation() {
  if (!FLAG_print_break_location) return;
  HandleScope scope(isolate_);
  JavaScriptFrameIterator iterator(isolate_);
  if (iterator.done()) return;
  JavaScriptFrame* frame = iterator.frame();
  FrameSummary summary = FrameSummary::GetFirst(frame);
  int source_position =
      summary.abstract_code()->SourcePosition(summary.code_offset());
  Handle<Object> script_obj(summary.function()->shared()->script(), isolate_);
  PrintF("[debug] break in function '");
  summary.function()->PrintName();
  PrintF("'.\n");
  if (script_obj->IsScript()) {
    Handle<Script> script = Handle<Script>::cast(script_obj);
    Handle<String> source(String::cast(script->source()));
    Script::InitLineEnds(script);
    int line =
        Script::GetLineNumber(script, source_position) - script->line_offset();
    int column = Script::GetColumnNumber(script, source_position) -
                 (line == 0 ? script->column_offset() : 0);
    Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
    int line_start =
        line == 0 ? 0 : Smi::cast(line_ends->get(line - 1))->value() + 1;
    int line_end = Smi::cast(line_ends->get(line))->value();
    DisallowHeapAllocation no_gc;
    String::FlatContent content = source->GetFlatContent();
    if (content.IsOneByte()) {
      PrintF("[debug] %.*s\n", line_end - line_start,
             content.ToOneByteVector().start() + line_start);
      PrintF("[debug] ");
      for (int i = 0; i < column; i++) PrintF(" ");
      PrintF("^\n");
    } else {
      PrintF("[debug] at line %d column %d\n", line, column);
    }
  }
}
#endif  // DEBUG

DebugScope::DebugScope(Debug* debug)
    : debug_(debug),
      prev_(debug->debugger_entry()),
      save_(debug_->isolate_),
      no_termination_exceptons_(debug_->isolate_,
                                StackGuard::TERMINATE_EXECUTION) {
  // Link recursive debugger entry.
  base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
                        reinterpret_cast<base::AtomicWord>(this));

  // Store the previous break id, frame id and return value.
  break_id_ = debug_->break_id();
  break_frame_id_ = debug_->break_frame_id();
  return_value_ = debug_->return_value();

  // Create the new break info. If there is no JavaScript frames there is no
  // break frame id.
  JavaScriptFrameIterator it(isolate());
  bool has_js_frames = !it.done();
  debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
                                                        : StackFrame::NO_ID;
  debug_->SetNextBreakId();

  debug_->UpdateState();
  // Make sure that debugger is loaded and enter the debugger context.
  // The previous context is kept in save_.
  failed_ = !debug_->is_loaded();
  if (!failed_) isolate()->set_context(*debug->debug_context());
}


DebugScope::~DebugScope() {
  if (!failed_ && prev_ == NULL) {
    // Clear mirror cache when leaving the debugger. Skip this if there is a
    // pending exception as clearing the mirror cache calls back into
    // JavaScript. This can happen if the v8::Debug::Call is used in which
    // case the exception should end up in the calling code.
    if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();

    // If there are commands in the queue when leaving the debugger request
    // that these commands are processed.
    if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
  }

  // Leaving this debugger entry.
  base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
                        reinterpret_cast<base::AtomicWord>(prev_));

  // Restore to the previous break state.
  debug_->thread_local_.break_frame_id_ = break_frame_id_;
  debug_->thread_local_.break_id_ = break_id_;
  debug_->thread_local_.return_value_ = return_value_;

  debug_->UpdateState();
}


MessageImpl MessageImpl::NewEvent(DebugEvent event,
                                  bool running,
                                  Handle<JSObject> exec_state,
                                  Handle<JSObject> event_data) {
  MessageImpl message(true, event, running,
                      exec_state, event_data, Handle<String>(), NULL);
  return message;
}


MessageImpl MessageImpl::NewResponse(DebugEvent event,
                                     bool running,
                                     Handle<JSObject> exec_state,
                                     Handle<JSObject> event_data,
                                     Handle<String> response_json,
                                     v8::Debug::ClientData* client_data) {
  MessageImpl message(false, event, running,
                      exec_state, event_data, response_json, client_data);
  return message;
}


MessageImpl::MessageImpl(bool is_event,
                         DebugEvent event,
                         bool running,
                         Handle<JSObject> exec_state,
                         Handle<JSObject> event_data,
                         Handle<String> response_json,
                         v8::Debug::ClientData* client_data)
    : is_event_(is_event),
      event_(event),
      running_(running),
      exec_state_(exec_state),
      event_data_(event_data),
      response_json_(response_json),
      client_data_(client_data) {}


bool MessageImpl::IsEvent() const {
  return is_event_;
}


bool MessageImpl::IsResponse() const {
  return !is_event_;
}


DebugEvent MessageImpl::GetEvent() const {
  return event_;
}


bool MessageImpl::WillStartRunning() const {
  return running_;
}


v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
  return v8::Utils::ToLocal(exec_state_);
}


v8::Isolate* MessageImpl::GetIsolate() const {
  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
}


v8::Local<v8::Object> MessageImpl::GetEventData() const {
  return v8::Utils::ToLocal(event_data_);
}


v8::Local<v8::String> MessageImpl::GetJSON() const {
  Isolate* isolate = event_data_->GetIsolate();
  v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));

  if (IsEvent()) {
    // Call toJSONProtocol on the debug event object.
    Handle<Object> fun =
        JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol")
            .ToHandleChecked();
    if (!fun->IsJSFunction()) {
      return v8::Local<v8::String>();
    }

    MaybeHandle<Object> maybe_json =
        Execution::TryCall(isolate, fun, event_data_, 0, NULL);
    Handle<Object> json;
    if (!maybe_json.ToHandle(&json) || !json->IsString()) {
      return v8::Local<v8::String>();
    }
    return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
  } else {
    return v8::Utils::ToLocal(response_json_);
  }
}


v8::Local<v8::Context> MessageImpl::GetEventContext() const {
  Isolate* isolate = event_data_->GetIsolate();
  v8::Local<v8::Context> context = GetDebugEventContext(isolate);
  // Isolate::context() may be NULL when "script collected" event occurs.
  DCHECK(!context.IsEmpty());
  return context;
}


v8::Debug::ClientData* MessageImpl::GetClientData() const {
  return client_data_;
}


EventDetailsImpl::EventDetailsImpl(DebugEvent event,
                                   Handle<JSObject> exec_state,
                                   Handle<JSObject> event_data,
                                   Handle<Object> callback_data,
                                   v8::Debug::ClientData* client_data)
    : event_(event),
      exec_state_(exec_state),
      event_data_(event_data),
      callback_data_(callback_data),
      client_data_(client_data) {}


DebugEvent EventDetailsImpl::GetEvent() const {
  return event_;
}


v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
  return v8::Utils::ToLocal(exec_state_);
}


v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
  return v8::Utils::ToLocal(event_data_);
}


v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
  return GetDebugEventContext(exec_state_->GetIsolate());
}


v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
  return v8::Utils::ToLocal(callback_data_);
}


v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
  return client_data_;
}

v8::Isolate* EventDetailsImpl::GetIsolate() const {
  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
}

CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
                                   client_data_(NULL) {
}


CommandMessage::CommandMessage(const Vector<uint16_t>& text,
                               v8::Debug::ClientData* data)
    : text_(text),
      client_data_(data) {
}


void CommandMessage::Dispose() {
  text_.Dispose();
  delete client_data_;
  client_data_ = NULL;
}


CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
                                   v8::Debug::ClientData* data) {
  return CommandMessage(command.Clone(), data);
}


CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
                                                     size_(size) {
  messages_ = NewArray<CommandMessage>(size);
}


CommandMessageQueue::~CommandMessageQueue() {
  while (!IsEmpty()) Get().Dispose();
  DeleteArray(messages_);
}


CommandMessage CommandMessageQueue::Get() {
  DCHECK(!IsEmpty());
  int result = start_;
  start_ = (start_ + 1) % size_;
  return messages_[result];
}


void CommandMessageQueue::Put(const CommandMessage& message) {
  if ((end_ + 1) % size_ == start_) {
    Expand();
  }
  messages_[end_] = message;
  end_ = (end_ + 1) % size_;
}


void CommandMessageQueue::Expand() {
  CommandMessageQueue new_queue(size_ * 2);
  while (!IsEmpty()) {
    new_queue.Put(Get());
  }
  CommandMessage* array_to_free = messages_;
  *this = new_queue;
  new_queue.messages_ = array_to_free;
  // Make the new_queue empty so that it doesn't call Dispose on any messages.
  new_queue.start_ = new_queue.end_;
  // Automatic destructor called on new_queue, freeing array_to_free.
}


LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
    : logger_(logger), queue_(size) {}


bool LockingCommandMessageQueue::IsEmpty() const {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  return queue_.IsEmpty();
}


CommandMessage LockingCommandMessageQueue::Get() {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  CommandMessage result = queue_.Get();
  logger_->DebugEvent("Get", result.text());
  return result;
}


void LockingCommandMessageQueue::Put(const CommandMessage& message) {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  queue_.Put(message);
  logger_->DebugEvent("Put", message.text());
}


void LockingCommandMessageQueue::Clear() {
  base::LockGuard<base::Mutex> lock_guard(&mutex_);
  queue_.Clear();
}

}  // namespace internal
}  // namespace v8
