// 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_.step_in_enabled_ = false;
  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;
  Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
      MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
      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());

  // 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()) {
    // 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());
  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()) 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();
}


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()) 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()) {
      // 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) {
  if (!is_active()) return;
  if (last_step_action() < StepIn) return;
  if (in_debug_scope()) return;
  if (thread_local_.step_in_enabled_) {
    FloodWithOneShot(function);
  }
}

void Debug::PrepareStepInSuspendedGenerator() {
  if (!is_active()) return;
  if (in_debug_scope()) return;
  DCHECK(has_suspended_generator());
  thread_local_.last_step_action_ = StepIn;
  thread_local_.step_in_enabled_ = true;
  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);

  // Remember this step action and count.
  thread_local_.last_step_action_ = step_action;
  STATIC_ASSERT(StepFrame > StepIn);
  thread_local_.step_in_enabled_ = (step_action >= StepIn);

  // 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()) {
        // Stepping out to the embedder. Disable step-in to avoid stepping into
        // the next (unrelated) call that the embedder makes.
        thread_local_.step_in_enabled_ = false;
      } else {
        // 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();
  Heap* heap = isolate->heap();
  if (!shared->HasDebugInfo()) {
    return Handle<Object>(heap->undefined_value(), isolate);
  }
  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
  if (debug_info->GetBreakPointCount() == 0) {
    return Handle<Object>(heap->undefined_value(), isolate);
  }
  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()) {
      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_.step_in_enabled_ = false;
  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();
    }
  }
}


void Debug::EnableStepIn() {
  STATIC_ASSERT(StepFrame > StepIn);
  thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
}


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");

  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;
  DCHECK(!has_suspended_generator());
  DCHECK(generator_object->function()->shared()->is_async());
  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()) {
    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();
  }
  // 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()) {
        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();
    } 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() && !callback->IsNull()) {
    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_;
}


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
