// Copyright 2006-2008 Google Inc. All Rights Reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "v8.h"

#include "api.h"
#include "arguments.h"
#include "bootstrapper.h"
#include "code-stubs.h"
#include "compiler.h"
#include "debug.h"
#include "execution.h"
#include "global-handles.h"
#include "natives.h"
#include "stub-cache.h"
#include "log.h"

namespace v8 { namespace internal {

DEFINE_bool(remote_debugging, false, "enable remote debugging");
DEFINE_int(debug_port, 5858, "port for remote debugging");
DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response");
DECLARE_bool(allow_natives_syntax);
DECLARE_bool(log_debugger);


static void PrintLn(v8::Local<v8::Value> value) {
  v8::Local<v8::String> s = value->ToString();
  char* data = NewArray<char>(s->Length() + 1);
  if (data == NULL) {
    V8::FatalProcessOutOfMemory("PrintLn");
    return;
  }
  s->WriteAscii(data);
  PrintF("%s\n", data);
  DeleteArray(data);
}


static Handle<Code> ComputeCallDebugBreak(int argc) {
  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);
}


static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {
  CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);
}


BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
                                             BreakLocatorType type) {
  debug_info_ = debug_info;
  type_ = type;
  reloc_iterator_ = NULL;
  reloc_iterator_original_ = NULL;
  Reset();  // Initialize the rest of the member variables.
}


BreakLocationIterator::~BreakLocationIterator() {
  ASSERT(reloc_iterator_ != NULL);
  ASSERT(reloc_iterator_original_ != NULL);
  delete reloc_iterator_;
  delete reloc_iterator_original_;
}


void BreakLocationIterator::Next() {
  AssertNoAllocation nogc;
  ASSERT(!RinfoDone());

  // Iterate through reloc info for code and original code stopping at each
  // breakable code target.
  bool first = break_point_ == -1;
  while (!RinfoDone()) {
    if (!first) RinfoNext();
    first = false;
    if (RinfoDone()) return;

    // Update the current source position each time a source position is
    // passed.
    if (is_position(rmode())) {
      position_ = rinfo()->data() - debug_info_->shared()->start_position();
      if (is_statement_position(rmode())) {
        statement_position_ =
            rinfo()->data() - debug_info_->shared()->start_position();
      }
      ASSERT(position_ >= 0);
      ASSERT(statement_position_ >= 0);
    }

    // Check for breakable code target. Look in the original code as setting
    // break points can cause the code targets in the running (debugged) code to
    // be of a different kind than in the original code.
    if (is_code_target(rmode())) {
      Address target = original_rinfo()->target_address();
      Code* code = Debug::GetCodeTarget(target);
      if (code->is_inline_cache_stub() || is_js_construct_call(rmode())) {
        break_point_++;
        return;
      }
      if (code->kind() == Code::STUB) {
        if (type_ == ALL_BREAK_LOCATIONS) {
          if (Debug::IsBreakStub(code)) {
            break_point_++;
            return;
          }
        } else {
          ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
          if (Debug::IsSourceBreakStub(code)) {
            break_point_++;
            return;
          }
        }
      }
    }

    // Check for break at return.
    // Currently is_exit_js_frame is used on ARM.
    if (is_js_return(rmode()) || is_exit_js_frame(rmode())) {
      // Set the positions to the end of the function.
      if (debug_info_->shared()->HasSourceCode()) {
        position_ = debug_info_->shared()->end_position() -
                    debug_info_->shared()->start_position();
      } else {
        position_ = 0;
      }
      statement_position_ = position_;
      break_point_++;
      return;
    }
  }
}


void BreakLocationIterator::Next(int count) {
  while (count > 0) {
    Next();
    count--;
  }
}


// Find the break point closest to the supplied address.
void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
  // Run through all break points to locate the one closest to the address.
  int closest_break_point = 0;
  int distance = kMaxInt;
  while (!Done()) {
    // Check if this break point is closer that what was previously found.
    if (this->pc() < pc && pc - this->pc() < distance) {
      closest_break_point = break_point();
      distance = pc - this->pc();
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
    Next();
  }

  // Move to the break point found.
  Reset();
  Next(closest_break_point);
}


// Find the break point closest to the supplied source position.
void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
  // Run through all break points to locate the one closest to the source
  // position.
  int closest_break_point = 0;
  int distance = kMaxInt;
  while (!Done()) {
    // Check if this break point is closer that what was previously found.
    if (position <= statement_position() &&
        statement_position() - position < distance) {
      closest_break_point = break_point();
      distance = statement_position() - position;
      // Check whether we can't get any closer.
      if (distance == 0) break;
    }
    Next();
  }

  // Move to the break point found.
  Reset();
  Next(closest_break_point);
}


void BreakLocationIterator::Reset() {
  // Create relocation iterators for the two code objects.
  if (reloc_iterator_ != NULL) delete reloc_iterator_;
  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
  reloc_iterator_ = new RelocIterator(debug_info_->code());
  reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());

  // Position at the first break point.
  break_point_ = -1;
  position_ = 1;
  statement_position_ = 1;
  Next();
}


bool BreakLocationIterator::Done() const {
  return RinfoDone();
}


void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
  // If there is not already a real break point here patch code with debug
  // break.
  if (!HasBreakPoint()) {
    SetDebugBreak();
  }
  ASSERT(IsDebugBreak());
  // Set the break point information.
  DebugInfo::SetBreakPoint(debug_info_, code_position(),
                           position(), statement_position(),
                           break_point_object);
}


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


void BreakLocationIterator::SetOneShot() {
  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
    ASSERT(IsDebugBreak());
    return;
  }

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


void BreakLocationIterator::ClearOneShot() {
  // If there is a real break point here no more to do.
  if (HasBreakPoint()) {
    ASSERT(IsDebugBreak());
    return;
  }

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


void BreakLocationIterator::SetDebugBreak() {
  // If there is already a break point here just return. This might happen if
  // the same code is flodded with break points twice. Flodding 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;
  }

  if (is_js_return(rmode())) {
    // This path is currently only used on IA32 as JSExitFrame on ARM uses a
    // stub.
    // Patch the JS frame exit code with a debug break call. See
    // VisitReturnStatement and ExitJSFrame in codegen-ia32.cc for the
    // precise return instructions sequence.
    ASSERT(Debug::kIa32JSReturnSequenceLength >=
           Debug::kIa32CallInstructionLength);
    rinfo()->patch_code_with_call(Debug::debug_break_return_entry()->entry(),
        Debug::kIa32JSReturnSequenceLength - Debug::kIa32CallInstructionLength);
  } else {
    // Patch the original code with the current address as the current address
    // might have changed by the inline caching since the code was copied.
    original_rinfo()->set_target_address(rinfo()->target_address());

    // Patch the code to invoke the builtin debug break function matching the
    // calling convention used by the call site.
    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
    rinfo()->set_target_address(dbgbrk_code->entry());
  }
  ASSERT(IsDebugBreak());
}


void BreakLocationIterator::ClearDebugBreak() {
  if (is_js_return(rmode())) {
    // Restore the JS frame exit code.
    rinfo()->patch_code(original_rinfo()->pc(),
                        Debug::kIa32JSReturnSequenceLength);
  } else {
    // Patch the code to the original invoke.
    rinfo()->set_target_address(original_rinfo()->target_address());
  }
  ASSERT(!IsDebugBreak());
}


void BreakLocationIterator::PrepareStepIn() {
  // Step in can only be prepared if currently positioned on an IC call or
  // construct call.
  Address target = rinfo()->target_address();
  Code* code = Debug::GetCodeTarget(target);
  if (code->is_call_stub()) {
    // Step in through IC call is handled by the runtime system. Therefore make
    // sure that the any current IC is cleared and the runtime system is
    // called. If the executing code has a debug break at the location change
    // the call in the original code as it is the code there that will be
    // executed in place of the debug break call.
    Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());
    if (IsDebugBreak()) {
      original_rinfo()->set_target_address(stub->entry());
    } else {
      rinfo()->set_target_address(stub->entry());
    }
  } else {
    // Step in through constructs call requires no changs to the running code.
    ASSERT(is_js_construct_call(rmode()));
  }
}


// Check whether the break point is at a position which will exit the function.
bool BreakLocationIterator::IsExit() const {
  // Currently is_exit_js_frame is used on ARM.
  return (is_js_return(rmode()) || is_exit_js_frame(rmode()));
}


bool BreakLocationIterator::HasBreakPoint() {
  return debug_info_->HasBreakPoint(code_position());
}


// Check whether there is a debug break at the current position.
bool BreakLocationIterator::IsDebugBreak() {
  if (is_js_return(rmode())) {
    // This is IA32 specific but works as long as the ARM version
    // still uses a stub for JSExitFrame.
    //
    // TODO(1240753): Make the test architecture independent or split
    // parts of the debugger into architecture dependent files.
    return (*(rinfo()->pc()) == 0xE8);
  } else {
    return Debug::IsDebugBreak(rinfo()->target_address());
  }
}


Object* BreakLocationIterator::BreakPointObjects() {
  return debug_info_->GetBreakPointObjects(code_position());
}


bool BreakLocationIterator::RinfoDone() const {
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
  return reloc_iterator_->done();
}


void BreakLocationIterator::RinfoNext() {
  reloc_iterator_->next();
  reloc_iterator_original_->next();
#ifdef DEBUG
  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
  if (!reloc_iterator_->done()) {
    ASSERT(rmode() == original_rmode());
  }
#endif
}


bool Debug::has_break_points_ = false;
DebugInfoListNode* Debug::debug_info_list_ = NULL;


// Threading support.
void Debug::ThreadInit() {
  thread_local_.last_step_action_ = StepNone;
  thread_local_.last_statement_position_ = kNoPosition;
  thread_local_.step_count_ = 0;
  thread_local_.last_fp_ = 0;
  thread_local_.step_into_fp_ = 0;
  thread_local_.after_break_target_ = 0;
}


JSCallerSavedBuffer Debug::registers_;
Debug::ThreadLocal Debug::thread_local_;


char* Debug::ArchiveDebug(char* storage) {
  char* to = storage;
  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
  to += sizeof(ThreadLocal);
  memcpy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
  ThreadInit();
  ASSERT(to <= storage + ArchiveSpacePerThread());
  return storage + ArchiveSpacePerThread();
}


char* Debug::RestoreDebug(char* storage) {
  char* from = storage;
  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
  from += sizeof(ThreadLocal);
  memcpy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
  ASSERT(from <= storage + ArchiveSpacePerThread());
  return storage + ArchiveSpacePerThread();
}


int Debug::ArchiveSpacePerThread() {
  return sizeof(ThreadLocal) + sizeof(registers_);
}


// Default break enabled.
bool Debug::disable_break_ = false;

// Default call debugger on uncaught exception.
bool Debug::break_on_exception_ = false;
bool Debug::break_on_uncaught_exception_ = true;

Handle<Context> Debug::debug_context_ = Handle<Context>();
Code* Debug::debug_break_return_entry_ = NULL;
Code* Debug::debug_break_return_ = NULL;


void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Object> obj, void* data) {
  DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
  RemoveDebugInfo(node->debug_info());
#ifdef DEBUG
  node = Debug::debug_info_list_;
  while (node != NULL) {
    ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
    node = node->next();
  }
#endif
}


DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
  // Globalize the request debug info object and make it weak.
  debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
                          this, Debug::HandleWeakDebugInfo);
}


DebugInfoListNode::~DebugInfoListNode() {
  GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
}


void Debug::Setup(bool create_heap_objects) {
  ThreadInit();
  if (create_heap_objects) {
    // Get code to handle entry to debug break on return.
    debug_break_return_entry_ =
        Builtins::builtin(Builtins::Return_DebugBreakEntry);
    ASSERT(debug_break_return_entry_->IsCode());

    // Get code to handle debug break on return.
    debug_break_return_ =
        Builtins::builtin(Builtins::Return_DebugBreak);
    ASSERT(debug_break_return_->IsCode());
  }
}


bool Debug::CompileDebuggerScript(int index) {
  HandleScope scope;

  // Bail out if the index is invalid.
  if (index == -1) {
    return false;
  }

  // Find source and name for the requested script.
  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
  Vector<const char> name = Natives::GetScriptName(index);
  Handle<String> script_name = Factory::NewStringFromAscii(name);

  // Compile the script.
  bool allow_natives_syntax = FLAG_allow_natives_syntax;
  FLAG_allow_natives_syntax = true;
  Handle<JSFunction> boilerplate;
  boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
  FLAG_allow_natives_syntax = allow_natives_syntax;

  // Silently ignore stack overflows during compilation.
  if (boilerplate.is_null()) {
    ASSERT(Top::has_pending_exception());
    Top::clear_pending_exception();
    return false;
  }

  // Execute the boilerplate function in the debugger context.
  Handle<Context> context = Top::global_context();
  bool caught_exception = false;
  Handle<JSFunction> function =
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
  Handle<Object> result =
      Execution::TryCall(function, Handle<Object>(context->global()),
                         0, NULL, &caught_exception);

  // Check for caught exceptions.
  if (caught_exception) {
    MessageHandler::ReportMessage("error_loading_debugger", NULL,
                                  HandleVector<Object>(&result, 1));
    return false;
  }

  // Mark this script as native and return successfully.
  Handle<Script> script(Script::cast(function->shared()->script()));
  script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
  return true;
}


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

  // Bail out if we're already in the process of compiling the native
  // JavaScript source code for the debugger.
  if (Debugger::compiling_natives()) return false;

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

  // Create the debugger context.
  HandleScope scope;
  Handle<Context> context =
      Bootstrapper::CreateEnvironment(Handle<Object>::null(),
                                      v8::Handle<ObjectTemplate>(),
                                      NULL);

  // Use the debugger context.
  SaveContext save;
  Top::set_context(*context);
  Top::set_security_context(*context);

  // Expose the builtins object in the debugger context.
  Handle<String> key = Factory::LookupAsciiSymbol("builtins");
  Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
  SetProperty(global, key, Handle<Object>(global->builtins()), NONE);

  // Compile the JavaScript for the debugger in the debugger context.
  Debugger::set_compiling_natives(true);
  bool caught_exception =
      !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
      !CompileDebuggerScript(Natives::GetIndex("debug"));
  Debugger::set_compiling_natives(false);

  // Check for caught exceptions.
  if (caught_exception) return false;

  // Debugger loaded.
  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
  return true;
}


void Debug::Unload() {
  // Return debugger is not loaded.
  if (!IsLoaded()) {
    return;
  }

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


void Debug::Iterate(ObjectVisitor* v) {
#define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field)));
  VISIT(debug_break_return_entry_);
  VISIT(debug_break_return_);
#undef VISIT
}


Object* Debug::Break(Arguments args) {
  HandleScope scope;
  ASSERT(args.length() == 0);

  // Get the top-most JavaScript frame.
  JavaScriptFrameIterator it;
  JavaScriptFrame* frame = it.frame();

  // Just continue if breaks are disabled or debugger cannot be loaded.
  if (disable_break() || !Load()) {
    SetAfterBreakTarget(frame);
    return Heap::undefined_value();
  }

  SaveBreakFrame save;
  EnterDebuggerContext enter;

  // Postpone interrupt during breakpoint processing.
  PostponeInterruptsScope postpone;

  // Get the debug info (create it if it does not exist).
  Handle<SharedFunctionInfo> shared =
      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);

  // Find the break point where execution has stopped.
  BreakLocationIterator break_location_iterator(debug_info,
                                                ALL_BREAK_LOCATIONS);
  break_location_iterator.FindBreakLocationFromAddress(frame->pc());

  // Check whether step next reached a new statement.
  if (!StepNextContinue(&break_location_iterator, frame)) {
    // Decrease steps left if performing multiple steps.
    if (thread_local_.step_count_ > 0) {
      thread_local_.step_count_--;
    }
  }

  // If there is one or more real break points check whether any of these are
  // triggered.
  Handle<Object> break_points_hit(Heap::undefined_value());
  if (break_location_iterator.HasBreakPoint()) {
    Handle<Object> break_point_objects =
        Handle<Object>(break_location_iterator.BreakPointObjects());
    break_points_hit = CheckBreakPoints(break_point_objects);
  }

  // Notify debugger if a real break point is triggered or if performing single
  // stepping with no more steps to perform. Otherwise do another step.
  if (!break_points_hit->IsUndefined() ||
    (thread_local_.last_step_action_ != StepNone &&
     thread_local_.step_count_ == 0)) {
    // Clear all current stepping setup.
    ClearStepping();

    // Notify the debug event listeners.
    Debugger::OnDebugBreak(break_points_hit);
  } else if (thread_local_.last_step_action_ != StepNone) {
    // Hold on to last step action as it is cleared by the call to
    // ClearStepping.
    StepAction step_action = thread_local_.last_step_action_;
    int step_count = thread_local_.step_count_;

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

    // Set up for the remaining steps.
    PrepareStep(step_action, step_count);
  }

  // Install jump to the call address which was overwritten.
  SetAfterBreakTarget(frame);

  return Heap::undefined_value();
}


// Check the break point objects for whether one or more are actually
// triggered. This function returns a JSArray with the break point objects
// which is triggered.
Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
  int break_points_hit_count = 0;
  Handle<JSArray> break_points_hit = Factory::NewJSArray(1);

  // If there are multiple break points they are in a Fixedrray.
  ASSERT(!break_point_objects->IsUndefined());
  if (break_point_objects->IsFixedArray()) {
    Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
    for (int i = 0; i < array->length(); i++) {
      Handle<Object> o(array->get(i));
      if (CheckBreakPoint(o)) {
        break_points_hit->SetElement(break_points_hit_count++, *o);
      }
    }
  } else {
    if (CheckBreakPoint(break_point_objects)) {
      break_points_hit->SetElement(break_points_hit_count++,
                                   *break_point_objects);
    }
  }

  // Return undefined if no break points where triggered.
  if (break_points_hit_count == 0) {
    return Factory::undefined_value();
  }
  return break_points_hit;
}


// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
  // Ignore check if break point object is not a JSObject.
  if (!break_point_object->IsJSObject()) return true;

  // Get the function CheckBreakPoint (defined in debug.js).
  Handle<JSFunction> check_break_point =
    Handle<JSFunction>(JSFunction::cast(
      debug_context()->global()->GetProperty(
          *Factory::LookupAsciiSymbol("IsBreakPointTriggered"))));

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

  // Call HandleBreakPointx.
  bool caught_exception = false;
  const int argc = 2;
  Object** argv[argc] = {
    break_id.location(),
    reinterpret_cast<Object**>(break_point_object.location())
  };
  Handle<Object> result = Execution::TryCall(check_break_point,
                                             Top::builtins(), argc, argv,
                                             &caught_exception);

  // If exception or non boolean result handle as not triggered
  if (caught_exception || !result->IsBoolean()) {
    return false;
  }

  // Return whether the break point is triggered.
  return *result == Heap::true_value();
}


// Check whether the function has debug information.
bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
  return !shared->debug_info()->IsUndefined();
}


// Return the debug info for this function. EnsureDebugInfo must be called
// prior to ensure the debug info has been generated for shared.
Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
  ASSERT(HasDebugInfo(shared));
  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
}


void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
                          int source_position,
                          Handle<Object> break_point_object) {
  if (!EnsureDebugInfo(shared)) {
    // Return if retrieving debug info failed.
    return;
  }

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

  // Find the break point and change it.
  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
  it.FindBreakLocationFromPosition(source_position);
  it.SetBreakPoint(break_point_object);

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


void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
  DebugInfoListNode* node = debug_info_list_;
  while (node != NULL) {
    Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
                                                   break_point_object);
    if (!result->IsUndefined()) {
      // Get information in the break point.
      BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
      Handle<DebugInfo> debug_info = node->debug_info();
      Handle<SharedFunctionInfo> shared(debug_info->shared());
      int source_position =  break_point_info->statement_position()->value();

      // Source positions starts with zero.
      ASSERT(source_position >= 0);

      // Find the break point and clear it.
      BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
      it.FindBreakLocationFromPosition(source_position);
      it.ClearBreakPoint(break_point_object);

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

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


void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
  // Make sure the function has setup the debug info.
  if (!EnsureDebugInfo(shared)) {
    // Return if we failed to retrieve the debug info.
    return;
  }

  // Flood the function with break points.
  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
  while (!it.Done()) {
    it.SetOneShot();
    it.Next();
  }
}


void Debug::FloodHandlerWithOneShot() {
  StackFrame::Id id = Top::break_frame_id();
  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
    JavaScriptFrame* frame = it.frame();
    if (frame->HasHandler()) {
      Handle<SharedFunctionInfo> shared =
          Handle<SharedFunctionInfo>(
              JSFunction::cast(frame->function())->shared());
      // Flood the function with the catch block with break points
      FloodWithOneShot(shared);
      return;
    }
  }
}


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


void Debug::PrepareStep(StepAction step_action, int step_count) {
  HandleScope scope;
  ASSERT(Debug::InDebugger());

  // Remember this step action and count.
  thread_local_.last_step_action_ = step_action;
  thread_local_.step_count_ = step_count;

  // 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 id = Top::break_frame_id();
  JavaScriptFrameIterator frames_it(id);
  JavaScriptFrame* frame = frames_it.frame();

  // First of all ensure there is one-shot break points in the top handler
  // if any.
  FloodHandlerWithOneShot();

  // If the function on the top frame is unresolved perform step out. This will
  // be the case when calling unknown functions 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 = JSFunction::cast(frames_it.frame()->function());
    FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
    return;
  }

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

  // Find the break location where execution has stopped.
  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
  it.FindBreakLocationFromAddress(frame->pc());

  // Compute whether or not the target is a call target.
  bool is_call_target = false;
  if (is_code_target(it.rinfo()->rmode())) {
    Address target = it.rinfo()->target_address();
    Code* code = Debug::GetCodeTarget(target);
    if (code->is_call_stub()) is_call_target = true;
  }

  // If this is the last break code target step out is the only posibility.
  if (it.IsExit() || step_action == StepOut) {
    // Step out: If there is a JavaScript caller frame, we need to
    // flood it with breakpoints.
    frames_it.Advance();
    if (!frames_it.done()) {
      // Fill the function to return to with one-shot break points.
      JSFunction* function = JSFunction::cast(frames_it.frame()->function());
      FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
    }
  } else if (!(is_call_target || is_js_construct_call(it.rmode())) ||
             step_action == StepNext || step_action == StepMin) {
    // Step next or step min.

    // Fill the current function with one-shot break points.
    FloodWithOneShot(shared);

    // Remember source position and frame to handle step next.
    thread_local_.last_statement_position_ =
        debug_info->code()->SourceStatementPosition(frame->pc());
    thread_local_.last_fp_ = frame->fp();
  } else {
    // Fill the current function with one-shot break points even for step in on
    // a call target as the function called might be a native function for
    // which step in will not stop.
    FloodWithOneShot(shared);

    // Step in or Step in min
    it.PrepareStepIn();
    ActivateStepIn(frame);
  }
}


// Check whether the current debug break should be reported to the debugger. It
// is used to have step next and step in only report break back to the debugger
// if on a different frame or in a different statement. In some situations
// there will be several break points in the same statement when the code is
// flodded with one-shot break points. This function helps to perform several
// steps before reporting break back to the debugger.
bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
                             JavaScriptFrame* frame) {
  // If the step last action was step next or step in make sure that a new
  // statement is hit.
  if (thread_local_.last_step_action_ == StepNext ||
      thread_local_.last_step_action_ == StepIn) {
    // Never continue if returning from function.
    if (break_location_iterator->IsExit()) return false;

    // Continue if we are still on the same frame and in the same statement.
    int current_statement_position =
        break_location_iterator->code()->SourceStatementPosition(frame->pc());
    return thread_local_.last_fp_ == frame->fp() &&
           thread_local_.last_statement_position_ == current_statement_position;
  }

  // No step next action - don't continue.
  return false;
}


// Check whether the code object at the specified address is a debug break code
// object.
bool Debug::IsDebugBreak(Address addr) {
  Code* code = GetCodeTarget(addr);
  return code->ic_state() == DEBUG_BREAK;
}


// Check whether a code stub with the specified major key is a possible break
// point location when looking for source break locations.
bool Debug::IsSourceBreakStub(Code* code) {
  CodeStub::Major major_key = code->major_key();
  return major_key == CodeStub::CallFunction;
}


// Check whether a code stub with the specified major key is a possible break
// location.
bool Debug::IsBreakStub(Code* code) {
  CodeStub::Major major_key = code->major_key();
  return major_key == CodeStub::CallFunction ||
         major_key == CodeStub::StackCheck;
}


// Find the builtin to use for invoking the debug break
Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
  // Find the builtin debug break function matching the calling convention
  // used by the call site.
  RelocMode mode = rinfo->rmode();

  if (is_code_target(mode)) {
    Address target = rinfo->target_address();
    Code* code = Debug::GetCodeTarget(target);
    if (code->is_inline_cache_stub()) {
      if (code->is_call_stub()) {
        return ComputeCallDebugBreak(code->arguments_count());
      }
      if (code->is_load_stub()) {
        return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
      }
      if (code->is_store_stub()) {
        return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
      }
      if (code->is_keyed_load_stub()) {
        Handle<Code> result =
            Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
        return result;
      }
      if (code->is_keyed_store_stub()) {
        Handle<Code> result =
            Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
        return result;
      }
    }
    if (is_js_construct_call(mode)) {
      Handle<Code> result =
          Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
      return result;
    }
    // Currently is_exit_js_frame is used on ARM.
    if (is_exit_js_frame(mode)) {
      return Handle<Code>(Builtins::builtin(Builtins::Return_DebugBreak));
    }
    if (code->kind() == Code::STUB) {
      ASSERT(code->major_key() == CodeStub::CallFunction ||
             code->major_key() == CodeStub::StackCheck);
      Handle<Code> result =
          Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
      return result;
    }
  }

  UNREACHABLE();
  return Handle<Code>::null();
}


// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
    Handle<SharedFunctionInfo> shared) {
  if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value());
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
  if (debug_info->GetBreakPointCount() == 0) {
    return Handle<Object>(Heap::undefined_value());
  }
  Handle<FixedArray> locations =
      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));
      if (break_point_info->GetBreakPointCount() > 0) {
        locations->set(count++, break_point_info->statement_position());
      }
    }
  }
  return locations;
}


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

  // Clear multiple step counter.
  thread_local_.step_count_ = 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 automaticaly
  // removed from the list.

  DebugInfoListNode* node = debug_info_list_;
  while (node != NULL) {
    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
    while (!it.Done()) {
      it.ClearOneShot();
      it.Next();
    }
    node = node->next();
  }
}


void Debug::ActivateStepIn(StackFrame* frame) {
  thread_local_.step_into_fp_ = frame->fp();
}


void Debug::ClearStepIn() {
  thread_local_.step_into_fp_ = 0;
}


void Debug::ClearStepNext() {
  thread_local_.last_step_action_ = StepNone;
  thread_local_.last_statement_position_ = kNoPosition;
  thread_local_.last_fp_ = 0;
}


bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
  if (shared->is_compiled()) return true;
  return CompileLazyShared(shared, CLEAR_EXCEPTION);
}


// Ensures the debug information is present for shared.
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
  // Return if we already have the debug info for shared.
  if (HasDebugInfo(shared)) return true;

  // Ensure shared in compiled. Return false if this failed.
  if (!EnsureCompiled(shared)) return false;

  // Create the debug info object.
  Handle<DebugInfo> debug_info =
      Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE));

  // Get the function original code.
  Handle<Code> code(shared->code());

  // Debug info contains function, a copy of the original code and the executing
  // code.
  debug_info->set_shared(*shared);
  debug_info->set_original_code(*Factory::CopyCode(code));
  debug_info->set_code(*code);

  // Link debug info to function.
  shared->set_debug_info(*debug_info);

  // Initially no active break points.
  debug_info->set_break_points(
      *Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));

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

  // Now there is at least one break point.
  has_break_points_ = true;

  return true;
}


void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
  ASSERT(debug_info_list_ != NULL);
  // 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() == *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());
      }
      current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
      delete current;

      // If there are no more debug info objects there are not more break
      // points.
      has_break_points_ = debug_info_list_ != NULL;

      return;
    }
    // Move to next in list.
    prev = current;
    current = current->next();
  }
  UNREACHABLE();
}


void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
  // Get the executing function in which the debug break occurred.
  Handle<SharedFunctionInfo> shared =
      Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
  if (!EnsureDebugInfo(shared)) {
    // Return if we failed to retrieve the debug info.
    return;
  }
  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
  Handle<Code> code(debug_info->code());
  Handle<Code> original_code(debug_info->original_code());
#ifdef DEBUG
  // Get the code which is actually executing.
  Handle<Code> frame_code(frame->FindCode());
  ASSERT(frame_code.is_identical_to(code));
#endif

  // Find the call address in the running code. This address holds the call to
  // either a DebugBreakXXX or to the debug break return entry code if the
  // break point is still active after processing the break point.
  Address addr = frame->pc() - Assembler::kTargetAddrToReturnAddrDist;

  // Check if the location is at JS exit.
  bool at_js_exit = false;
  RelocIterator it(debug_info->code());
  while (!it.done()) {
    if (is_js_return(it.rinfo()->rmode())) {
      at_js_exit = it.rinfo()->pc() == addr - 1;
    }
    it.next();
  }

  // Handle the jump to continue execution after break point depending on the
  // break location.
  if (at_js_exit) {
    // First check if the call in the code is still the debug break return
    // entry code. If it is the break point is still active. If not the break
    // point was removed during break point processing.
    if (Assembler::target_address_at(addr) ==
        debug_break_return_entry()->entry()) {
      // Break point still active. Jump to the corresponding place in the
      // original code.
      addr +=  original_code->instruction_start() - code->instruction_start();
    }

    // Move one byte back to where the call instruction was placed.
    thread_local_.after_break_target_ = addr - 1;
  } else {
    // Check if there still is a debug break call at the target address. If the
    // break point has been removed it will have disappeared. If it have
    // disappeared don't try to look in the original code as the running code
    // will have the right address. This takes care of the case where the last
    // break point is removed from the function and therefore no "original code"
    // is available. If the debug break call is still there find the address in
    // the original code.
    if (IsDebugBreak(Assembler::target_address_at(addr))) {
      // If the break point is still there find the call address which was
      // overwritten in the original code by the call to DebugBreakXXX.

      // Find the corresponding address in the original code.
      addr += original_code->instruction_start() - code->instruction_start();
    }

    // Install jump to the call address in the original code. This will be the
    // call which was overwritten by the call to DebugBreakXXX.
    thread_local_.after_break_target_ = Assembler::target_address_at(addr);
  }
}


Code* Debug::GetCodeTarget(Address target) {
  // Maybe this can be refactored with the stuff in ic-inl.h?
  Code* result =
      Code::cast(HeapObject::FromAddress(target - Code::kHeaderSize));
  return result;
}


bool Debug::IsDebugGlobal(GlobalObject* global) {
  return IsLoaded() && global == Debug::debug_context()->global();
}


bool Debugger::debugger_active_ = false;
bool Debugger::compiling_natives_ = false;
DebugMessageThread* Debugger::message_thread_ = NULL;
v8::DebugMessageHandler Debugger::debug_message_handler_ = NULL;
void* Debugger::debug_message_handler_data_ = NULL;


Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
                                      int argc, Object*** argv,
                                      bool* caught_exception) {
  ASSERT(Top::context() == *Debug::debug_context());

  // Create the execution state object.
  Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
  Handle<Object> constructor(Top::global()->GetProperty(*constructor_str));
  ASSERT(constructor->IsJSFunction());
  if (!constructor->IsJSFunction()) {
    *caught_exception = true;
    return Factory::undefined_value();
  }
  Handle<Object> js_object = Execution::TryCall(
      Handle<JSFunction>::cast(constructor),
      Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
      caught_exception);
  return js_object;
}


Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
  // Create the execution state object.
  Handle<Object> break_id = Factory::NewNumberFromInt(Top::break_id());
  const int argc = 1;
  Object** argv[argc] = { break_id.location() };
  return MakeJSObject(CStrVector("MakeExecutionState"),
                      argc, argv, caught_exception);
}


Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
                                        Handle<Object> break_points_hit,
                                        bool* caught_exception) {
  // Create the new break event object.
  const int argc = 2;
  Object** argv[argc] = { exec_state.location(),
                          break_points_hit.location() };
  return MakeJSObject(CStrVector("MakeBreakEvent"),
                      argc,
                      argv,
                      caught_exception);
}


Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
                                            Handle<Object> exception,
                                            bool uncaught,
                                            bool* caught_exception) {
  // Create the new exception event object.
  const int argc = 3;
  Object** argv[argc] = { exec_state.location(),
                          exception.location(),
                          uncaught ? Factory::true_value().location() :
                                     Factory::false_value().location()};
  return MakeJSObject(CStrVector("MakeExceptionEvent"),
                      argc, argv, caught_exception);
}


Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
                                              bool* caught_exception) {
  // Create the new function event object.
  const int argc = 1;
  Object** argv[argc] = { function.location() };
  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
                      argc, argv, caught_exception);
}


Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
                                          Handle<Object> script_function,
                                          bool* caught_exception) {
  // Create the compile event object.
  Handle<Object> exec_state = MakeExecutionState(caught_exception);
  Handle<Object> script_source(script->source());
  Handle<Object> script_name(script->name());
  const int argc = 3;
  Object** argv[argc] = { script_source.location(),
                          script_name.location(),
                          script_function.location() };
  return MakeJSObject(CStrVector("MakeCompileEvent"),
                      argc,
                      argv,
                      caught_exception);
}


Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
                                        Handle<Object> request,
                                        bool stopped) {
  // Get the function ProcessDebugRequest (declared in debug.js).
  Handle<JSFunction> process_denbug_request =
    Handle<JSFunction>(JSFunction::cast(
    Debug::debug_context()->global()->GetProperty(
        *Factory::LookupAsciiSymbol("ProcessDebugRequest"))));

  // Call ProcessDebugRequest expect String result. The ProcessDebugRequest
  // will never throw an exception (see debug.js).
  bool caught_exception;
  const int argc = 3;
  Object** argv[argc] = { exec_state.location(),
                          request.location(),
                          stopped ? Factory::true_value().location() :
                                    Factory::false_value().location()};
  Handle<Object> result = Execution::TryCall(process_denbug_request,
                                             Factory::undefined_value(),
                                             argc, argv,
                                             &caught_exception);
  if (caught_exception) {
    return Factory::empty_symbol();
  }

  return Handle<String>::cast(result);
}


bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
  // Get the function IsPlainBreakRequest (defined in debug.js).
  Handle<JSFunction> process_debug_request =
    Handle<JSFunction>(JSFunction::cast(
    Debug::debug_context()->global()->GetProperty(
        *Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));

  // Call ProcessDebugRequest expect String result.
  bool caught_exception;
  const int argc = 1;
  Object** argv[argc] = { request.location() };
  Handle<Object> result = Execution::TryCall(process_debug_request,
                                             Factory::undefined_value(),
                                             argc, argv,
                                             &caught_exception);
  if (caught_exception) {
    return false;
  }
  return *result == Heap::true_value();
}


void Debugger::OnException(Handle<Object> exception, bool uncaught) {
  HandleScope scope;

  // Bail out based on state or if there is no listener for this event
  if (Debug::InDebugger()) return;
  if (!Debugger::EventActive(v8::Exception)) return;

  // Bail out if exception breaks are not active
  if (uncaught) {
    // Uncaught exceptions are reported by either flags.
    if (!(Debug::break_on_uncaught_exception() ||
          Debug::break_on_exception())) return;
  } else {
    // Caught exceptions are reported is activated.
    if (!Debug::break_on_exception()) return;
  }

  // Enter the debugger.  Bail out if the debugger cannot be loaded.
  if (!Debug::Load()) return;
  SaveBreakFrame save;
  EnterDebuggerContext enter;

  // Clear all current stepping setup.
  Debug::ClearStepping();
  // Create the event data object.
  bool caught_exception = false;
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
  Handle<Object> event_data;
  if (!caught_exception) {
    event_data = MakeExceptionEvent(exec_state, exception, uncaught,
                                    &caught_exception);
  }
  // Bail out and don't call debugger if exception.
  if (caught_exception) {
    return;
  }

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


void Debugger::OnDebugBreak(Handle<Object> break_points_hit) {
  HandleScope scope;

  // Debugger has already been entered by caller.
  ASSERT(Top::context() == *Debug::debug_context());

  // Bail out if there is no listener for this event
  if (!Debugger::EventActive(v8::Break)) return;

  // Debugger must be entered in advance.
  ASSERT(Top::context() == *Debug::debug_context());

  // Create the event data object.
  bool caught_exception = false;
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
  Handle<Object> event_data;
  if (!caught_exception) {
    event_data = MakeBreakEvent(exec_state, break_points_hit,
                                &caught_exception);
  }
  // Bail out and don't call debugger if exception.
  if (caught_exception) {
    return;
  }

  // Process debug event
  ProcessDebugEvent(v8::Break, event_data);
}


void Debugger::OnBeforeCompile(Handle<Script> script) {
  HandleScope scope;

  // Bail out based on state or if there is no listener for this event
  if (Debug::InDebugger()) return;
  if (compiling_natives()) return;
  if (!EventActive(v8::BeforeCompile)) return;

  // Enter the debugger.  Bail out if the debugger cannot be loaded.
  if (!Debug::Load()) return;
  SaveBreakFrame save;
  EnterDebuggerContext enter;

  // Create the event data object.
  bool caught_exception = false;
  Handle<Object> event_data = MakeCompileEvent(script,
                                               Factory::undefined_value(),
                                               &caught_exception);
  // Bail out and don't call debugger if exception.
  if (caught_exception) {
    return;
  }

  // Process debug event
  ProcessDebugEvent(v8::BeforeCompile, event_data);
}


// Handle debugger actions when a new script is compiled.
void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
  HandleScope scope;

  // No compile events while compiling natives.
  if (compiling_natives()) return;

  // No more to do if not debugging.
  if (!debugger_active()) return;

  // Enter the debugger.  Bail out if the debugger cannot be loaded.
  if (!Debug::Load()) return;
  SaveBreakFrame save;
  EnterDebuggerContext enter;

  // If debugging there might be script break points registered for this
  // script. Make sure that these break points are set.

  // Get the function UpdateScriptBreakPoints (defined in debug-delay.js).
  Handle<Object> update_script_break_points =
      Handle<Object>(Debug::debug_context()->global()->GetProperty(
          *Factory::LookupAsciiSymbol("UpdateScriptBreakPoints")));
  if (!update_script_break_points->IsJSFunction()) {
    return;
  }
  ASSERT(update_script_break_points->IsJSFunction());

  // Wrap the script object in a proper JS object before passing it
  // to JavaScript.
  Handle<JSValue> wrapper = GetScriptWrapper(script);

  // Call UpdateScriptBreakPoints expect no exceptions.
  bool caught_exception = false;
  const int argc = 1;
  Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
  Handle<Object> result = Execution::TryCall(
      Handle<JSFunction>::cast(update_script_break_points),
      Top::builtins(), argc, argv,
      &caught_exception);
  if (caught_exception) {
    return;
  }
  // Bail out based on state or if there is no listener for this event
  if (Debug::InDebugger()) return;
  if (!Debugger::EventActive(v8::AfterCompile)) return;

  // Create the compile state object.
  Handle<Object> event_data = MakeCompileEvent(script,
                                               Factory::undefined_value(),
                                               &caught_exception);
  // Bail out and don't call debugger if exception.
  if (caught_exception) {
    return;
  }
  // Process debug event
  ProcessDebugEvent(v8::AfterCompile, event_data);
}


void Debugger::OnNewFunction(Handle<JSFunction> function) {
  return;
  HandleScope scope;

  // Bail out based on state or if there is no listener for this event
  if (Debug::InDebugger()) return;
  if (compiling_natives()) return;
  if (!Debugger::EventActive(v8::NewFunction)) return;

  // Enter the debugger.  Bail out if the debugger cannot be loaded.
  if (!Debug::Load()) return;
  SaveBreakFrame save;
  EnterDebuggerContext enter;

  // Create the event object.
  bool caught_exception = false;
  Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
  // Bail out and don't call debugger if exception.
  if (caught_exception) {
    return;
  }
  // Process debug event.
  ProcessDebugEvent(v8::NewFunction, event_data);
}


void Debugger::ProcessDebugEvent(v8::DebugEvent event,
                                 Handle<Object> event_data) {
  // Create the execution state.
  bool caught_exception = false;
  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
  if (caught_exception) {
    return;
  }
  // First notify the builtin debugger.
  if (message_thread_ != NULL) {
    message_thread_->DebugEvent(event, exec_state, event_data);
  }
  // Notify registered debug event listeners. The list can contain both C and
  // JavaScript functions.
  v8::NeanderArray listeners(Factory::debug_event_listeners());
  int length = listeners.length();
  for (int i = 0; i < length; i++) {
    if (listeners.get(i)->IsUndefined()) continue;   // Skip deleted ones.
    v8::NeanderObject listener(JSObject::cast(listeners.get(i)));
    Handle<Object> callback_data(listener.get(1));
    if (listener.get(0)->IsProxy()) {
      // C debug event listener.
      Handle<Proxy> callback_obj(Proxy::cast(listener.get(0)));
      v8::DebugEventCallback callback =
            FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
      callback(event,
               v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
               v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
               v8::Utils::ToLocal(callback_data));
    } else {
      // JavaScript debug event listener.
      ASSERT(listener.get(0)->IsJSFunction());
      Handle<JSFunction> fun(JSFunction::cast(listener.get(0)));

      // Invoke the JavaScript debug event listener.
      const int argc = 4;
      Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
                              exec_state.location(),
                              event_data.location(),
                              callback_data.location() };
      Handle<Object> result = Execution::TryCall(fun, Top::global(),
                                                 argc, argv, &caught_exception);
      if (caught_exception) {
        // Silently ignore exceptions from debug event listeners.
      }
    }
  }
}


void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data) {
  debug_message_handler_ = handler;
  debug_message_handler_data_ = data;
  if (!message_thread_) {
    message_thread_  = new DebugMessageThread();
    message_thread_->Start();
  }
  UpdateActiveDebugger();
}


// Posts an output message from the debugger to the debug_message_handler
// callback.  This callback is part of the public API.  Messages are
// kept internally as Vector<uint16_t> strings, which are allocated in various
// places and deallocated by the calling function sometime after this call.
void Debugger::SendMessage(Vector< uint16_t> message) {
  if (debug_message_handler_ != NULL) {
    debug_message_handler_(message.start(), message.length(),
                           debug_message_handler_data_);
  }
}


void Debugger::ProcessCommand(Vector<const uint16_t> command) {
  if (message_thread_ != NULL) {
    message_thread_->ProcessCommand(
        Vector<uint16_t>(const_cast<uint16_t *>(command.start()),
                         command.length()));
  }
}


void Debugger::UpdateActiveDebugger() {
  v8::NeanderArray listeners(Factory::debug_event_listeners());
  int length = listeners.length();
  bool active_listener = false;
  for (int i = 0; i < length && !active_listener; i++) {
    active_listener = !listeners.get(i)->IsUndefined();
  }
  set_debugger_active((Debugger::message_thread_ != NULL &&
                       Debugger::debug_message_handler_ != NULL) ||
                       active_listener);
  if (!debugger_active() && message_thread_)
    message_thread_->OnDebuggerInactive();
}


DebugMessageThread::DebugMessageThread()
    : host_running_(true),
      command_queue_(kQueueInitialSize),
      message_queue_(kQueueInitialSize) {
  command_received_ = OS::CreateSemaphore(0);
  message_received_ = OS::CreateSemaphore(0);
}

// Does not free resources held by DebugMessageThread
// because this cannot be done thread-safely.
DebugMessageThread::~DebugMessageThread() {
}


// Puts an event coming from V8 on the queue.  Creates
// a copy of the JSON formatted event string managed by the V8.
// Called by the V8 thread.
// The new copy of the event string is destroyed in Run().
void DebugMessageThread::SendMessage(Vector<uint16_t> message) {
  Vector<uint16_t> message_copy = message.Clone();
  Logger::DebugTag("Put message on event message_queue.");
  message_queue_.Put(message_copy);
  message_received_->Signal();
}


void DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
  v8::HandleScope scope;
  // Call toJSONProtocol on the debug event object.
  v8::Local<v8::Object> api_event_data =
      v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
  v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
  v8::Local<v8::Function> fun =
      v8::Function::Cast(*api_event_data->Get(fun_name));
  v8::TryCatch try_catch;
  v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
  v8::Local<v8::String> json_event_string;
  if (!try_catch.HasCaught()) {
    if (!json_event->IsUndefined()) {
      json_event_string = json_event->ToString();
      if (FLAG_trace_debug_json) {
        PrintLn(json_event_string);
      }
      v8::String::Value val(json_event_string);
      Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
                          json_event_string->Length());
      SendMessage(str);
    } else {
      SendMessage(Vector<uint16_t>::empty());
    }
  } else {
    PrintLn(try_catch.Exception());
    SendMessage(Vector<uint16_t>::empty());
  }
}


// Compare a two byte string to an null terminated ASCII string.
bool DebugMessageThread::TwoByteEqualsAscii(Vector<uint16_t> two_byte,
                                            const char* ascii) {
  for (int i = 0; i < two_byte.length(); i++) {
    if (ascii[i] == '\0') {
      return false;
    }
    if (two_byte[i] != static_cast<uint16_t>(ascii[i])) {
      return false;
    }
  }
  return ascii[two_byte.length()] == '\0';
}


void DebugMessageThread::Run() {
  // Sends debug events to an installed debugger message callback.
  while (true) {
    // Wait and Get are paired so that semaphore count equals queue length.
    message_received_->Wait();
    Logger::DebugTag("Get message from event message_queue.");
    Vector<uint16_t> message = message_queue_.Get();
    if (message.length() > 0) {
      Debugger::SendMessage(message);
    }
  }
}


// This method is called by the V8 thread whenever a debug event occurs in
// the VM.
void DebugMessageThread::DebugEvent(v8::DebugEvent event,
                                    Handle<Object> exec_state,
                                    Handle<Object> event_data) {
  if (!Debug::Load()) return;

  // Process the individual events.
  bool interactive = false;
  switch (event) {
    case v8::Break:
      interactive = true;  // Break event is always interavtive
      break;
    case v8::Exception:
      interactive = true;  // Exception event is always interavtive
      break;
    case v8::BeforeCompile:
      break;
    case v8::AfterCompile:
      break;
    case v8::NewFunction:
      break;
    default:
      UNREACHABLE();
  }

  // Done if not interactive.
  if (!interactive) return;

  // Get the DebugCommandProcessor.
  v8::Local<v8::Object> api_exec_state =
      v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
  v8::Local<v8::String> fun_name =
      v8::String::New("debugCommandProcessor");
  v8::Local<v8::Function> fun =
      v8::Function::Cast(*api_exec_state->Get(fun_name));
  v8::TryCatch try_catch;
  v8::Local<v8::Object> cmd_processor =
      v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
  if (try_catch.HasCaught()) {
    PrintLn(try_catch.Exception());
    return;
  }

  // First process all pending commands in the queue. During this processing
  // each message is checked to see if it is a plain break command. If there is
  // a plain break request in the queue or if the queue is empty a break event
  // is sent to the debugger.
  bool plain_break = false;
  if (command_queue_.IsEmpty()) {
    plain_break = true;
  } else {
    // Drain queue.
    while (!command_queue_.IsEmpty()) {
      command_received_->Wait();
      Logger::DebugTag("Get command from command_queue, in drain queue loop.");
      Vector<uint16_t> command = command_queue_.Get();
      // Support for sending a break command as just "break" instead of an
      // actual JSON break command.
      // If break is made into a separate API call, function
      // TwoByteEqualsASCII can be removed.
      if (TwoByteEqualsAscii(command, "break")) {
        plain_break = true;
        continue;
      }

      // Get the command as a string object.
      Handle<String> command_string;
      if (!command.is_empty()) {
        command_string = Factory::NewStringFromTwoByte(
                             Vector<const uint16_t>(
                                 reinterpret_cast<const uint16_t*>(
                                     command.start()),
                                 command.length()));
      } else {
        command_string = Handle<String>();
      }

      // Process the request.
      Handle<String> message_string = Debugger::ProcessRequest(exec_state,
                                                                command_string,
                                                                false);
      // Convert text result to UTF-16 string and send it.
      v8::String::Value val(Utils::ToLocal(message_string));
      Vector<uint16_t> message(reinterpret_cast<uint16_t*>(*val),
                                message_string->length());
      SendMessage(message);

      // Check whether one of the commands is a plain break request.
      if (!plain_break) {
        plain_break = Debugger::IsPlainBreakRequest(message_string);
      }
    }
  }

  // If this break event is not to go to the debugger just return.
  if (!plain_break) return;

  // Notify the debugger that a debug event has occoured.
  host_running_ = false;
  SetEventJSONFromEvent(event_data);

  // Wait for commands from the debugger.
  while (true) {
    command_received_->Wait();
    Logger::DebugTag("Get command from command queue, in interactive loop.");
    Vector<uint16_t> command = command_queue_.Get();
    ASSERT(!host_running_);
    if (!Debugger::debugger_active()) {
      host_running_ = true;
      return;
    }

    // Invoke the JavaScript to convert the debug command line to a JSON
    // request, invoke the JSON request and convert the JSON response to a text
    // representation.
    v8::Local<v8::String> fun_name;
    v8::Local<v8::Function> fun;
    v8::Local<v8::Value> args[1];
    v8::TryCatch try_catch;
    fun_name = v8::String::New("processDebugCommand");
    fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
    args[0] = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
                              command.length());
    v8::Local<v8::Value> result_val = fun->Call(cmd_processor, 1, args);

    // Get the result of the command.
    v8::Local<v8::String> result_string;
    bool running = false;
    if (!try_catch.HasCaught()) {
      // Get the result as an object.
      v8::Local<v8::Object> result = v8::Object::Cast(*result_val);

      // Log the JSON request/response.
      if (FLAG_trace_debug_json) {
        PrintLn(result->Get(v8::String::New("request")));
        PrintLn(result->Get(v8::String::New("response")));
      }

      // Get the running state.
      running = result->Get(v8::String::New("running"))->ToBoolean()->Value();

      // Get result text.
      v8::Local<v8::Value> text_result =
          result->Get(v8::String::New("response"));
      if (!text_result->IsUndefined()) {
        result_string = text_result->ToString();
      } else {
        result_string = v8::String::New("");
      }
    } else {
      // In case of failure the result text is the exception text.
      result_string = try_catch.Exception()->ToString();
    }

    // Convert text result to C string.
    v8::String::Value val(result_string);
    Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
                        result_string->Length());

    // Set host_running_ correctly for nested debugger evaluations.
    host_running_ = running;

    // Return the result.
    SendMessage(str);

    // Return from debug event processing is VM should be running.
    if (running) {
      return;
    }
  }
}


// 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.  This is where the API client hands off
// processing of the command to the DebugMessageThread thread.
// The new copy of the command is destroyed in HandleCommand().
void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) {
  Vector<uint16_t> command_copy = command.Clone();
  Logger::DebugTag("Put command on command_queue.");
  command_queue_.Put(command_copy);
  // If not in a break schedule a break and send the "request queued" response.
  if (host_running_) {
    v8::Debug::DebugBreak();
    uint16_t buffer[14] = {'r', 'e', 'q', 'u', 'e', 's', 't', ' ',
        'q', 'u', 'e', 'u', 'e', 'd'};
    SendMessage(Vector<uint16_t>(buffer, 14));
  }
  command_received_->Signal();
}


void DebugMessageThread::OnDebuggerInactive() {
  // Send an empty command to the debugger if in a break to make JavaScript run
  // again if the debugger is closed.
  if (!host_running_) {
    ProcessCommand(Vector<uint16_t>::empty());
  }
}


MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
  messages_ = NewArray<Vector<uint16_t> >(size);
}


MessageQueue::~MessageQueue() {
  DeleteArray(messages_);
}


Vector<uint16_t> MessageQueue::Get() {
  ASSERT(!IsEmpty());
  int result = start_;
  start_ = (start_ + 1) % size_;
  return messages_[result];
}


void MessageQueue::Put(const Vector<uint16_t>& message) {
  if ((end_ + 1) % size_ == start_) {
    Expand();
  }
  messages_[end_] = message;
  end_ = (end_ + 1) % size_;
}


void MessageQueue::Expand() {
  MessageQueue new_queue(size_ * 2);
  while (!IsEmpty()) {
    new_queue.Put(Get());
  }
  Vector<uint16_t>* array_to_free = messages_;
  *this = new_queue;
  new_queue.messages_ = array_to_free;
  // Automatic destructor called on new_queue, freeing array_to_free.
}


LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
  lock_ = OS::CreateMutex();
}


LockingMessageQueue::~LockingMessageQueue() {
  delete lock_;
}


bool LockingMessageQueue::IsEmpty() const {
  ScopedLock sl(lock_);
  return queue_.IsEmpty();
}


Vector<uint16_t> LockingMessageQueue::Get() {
  ScopedLock sl(lock_);
  Vector<uint16_t> result = queue_.Get();
  Logger::DebugEvent("Get", result);
  return result;
}


void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
  ScopedLock sl(lock_);
  queue_.Put(message);
  Logger::DebugEvent("Put", message);
}


void LockingMessageQueue::Clear() {
  ScopedLock sl(lock_);
  queue_.Clear();
}


} }  // namespace v8::internal
