| Index: src/debug.cc
 | 
| ===================================================================
 | 
| --- src/debug.cc	(revision 9531)
 | 
| +++ src/debug.cc	(working copy)
 | 
| @@ -40,6 +40,7 @@
 | 
|  #include "global-handles.h"
 | 
|  #include "ic.h"
 | 
|  #include "ic-inl.h"
 | 
| +#include "isolate-inl.h"
 | 
|  #include "list.h"
 | 
|  #include "messages.h"
 | 
|  #include "natives.h"
 | 
| @@ -401,15 +402,15 @@
 | 
|    // Step in can only be prepared if currently positioned on an IC call,
 | 
|    // construct call or CallFunction stub call.
 | 
|    Address target = rinfo()->target_address();
 | 
| -  Handle<Code> code(Code::GetCodeFromTargetAddress(target));
 | 
| -  if (code->is_call_stub() || code->is_keyed_call_stub()) {
 | 
| +  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
 | 
| +  if (target_code->is_call_stub() || target_code->is_keyed_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(),
 | 
| -                                                      code->kind());
 | 
| +    Handle<Code> stub = ComputeCallDebugPrepareStepIn(
 | 
| +        target_code->arguments_count(), target_code->kind());
 | 
|      if (IsDebugBreak()) {
 | 
|        original_rinfo()->set_target_address(stub->entry());
 | 
|      } else {
 | 
| @@ -419,7 +420,7 @@
 | 
|  #ifdef DEBUG
 | 
|      // All the following stuff is needed only for assertion checks so the code
 | 
|      // is wrapped in ifdef.
 | 
| -    Handle<Code> maybe_call_function_stub = code;
 | 
| +    Handle<Code> maybe_call_function_stub = target_code;
 | 
|      if (IsDebugBreak()) {
 | 
|        Address original_target = original_rinfo()->target_address();
 | 
|        maybe_call_function_stub =
 | 
| @@ -436,8 +437,9 @@
 | 
|      // Step in through CallFunction stub should also be prepared by caller of
 | 
|      // this function (Debug::PrepareStep) which should flood target function
 | 
|      // with breakpoints.
 | 
| -    ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub()
 | 
| -           || is_call_function_stub);
 | 
| +    ASSERT(RelocInfo::IsConstructCall(rmode()) ||
 | 
| +           target_code->is_inline_cache_stub() ||
 | 
| +           is_call_function_stub);
 | 
|  #endif
 | 
|    }
 | 
|  }
 | 
| @@ -474,11 +476,11 @@
 | 
|    RelocInfo::Mode mode = rmode();
 | 
|    if (RelocInfo::IsCodeTarget(mode)) {
 | 
|      Address target = rinfo()->target_address();
 | 
| -    Handle<Code> code(Code::GetCodeFromTargetAddress(target));
 | 
| +    Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
 | 
|  
 | 
|      // 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(code, mode));
 | 
| +    Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
 | 
|      rinfo()->set_target_address(dbgbrk_code->entry());
 | 
|    }
 | 
|  }
 | 
| @@ -772,7 +774,7 @@
 | 
|  
 | 
|    // Execute the shared function in the debugger context.
 | 
|    Handle<Context> context = isolate->global_context();
 | 
| -  bool caught_exception = false;
 | 
| +  bool caught_exception;
 | 
|    Handle<JSFunction> function =
 | 
|        factory->NewFunctionFromSharedFunctionInfo(function_info, context);
 | 
|  
 | 
| @@ -1103,7 +1105,7 @@
 | 
|    Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
 | 
|  
 | 
|    // Call HandleBreakPointx.
 | 
| -  bool caught_exception = false;
 | 
| +  bool caught_exception;
 | 
|    const int argc = 2;
 | 
|    Object** argv[argc] = {
 | 
|      break_id.location(),
 | 
| @@ -1732,6 +1734,10 @@
 | 
|    if (!has_break_points_) {
 | 
|      Deoptimizer::DeoptimizeAll();
 | 
|  
 | 
| +    // We are going to iterate heap to find all functions without
 | 
| +    // debug break slots.
 | 
| +    isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
 | 
| +
 | 
|      AssertNoAllocation no_allocation;
 | 
|      Builtins* builtins = isolate_->builtins();
 | 
|      Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile);
 | 
| @@ -1997,9 +2003,10 @@
 | 
|  
 | 
|    // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
 | 
|    // rid of all the cached script wrappers and the second gets rid of the
 | 
| -  // scripts which are no longer referenced.
 | 
| -  heap->CollectAllGarbage(false);
 | 
| -  heap->CollectAllGarbage(false);
 | 
| +  // scripts which are no longer referenced.  The second also sweeps precisely,
 | 
| +  // which saves us doing yet another GC to make the heap iterable.
 | 
| +  heap->CollectAllGarbage(Heap::kNoGCFlags);
 | 
| +  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask);
 | 
|  
 | 
|    ASSERT(script_cache_ == NULL);
 | 
|    script_cache_ = new ScriptCache();
 | 
| @@ -2007,6 +2014,8 @@
 | 
|    // Scan heap for Script objects.
 | 
|    int count = 0;
 | 
|    HeapIterator iterator;
 | 
| +  AssertNoAllocation no_allocation;
 | 
| +
 | 
|    for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
 | 
|      if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
 | 
|        script_cache_->Add(Handle<Script>(Script::cast(obj)));
 | 
| @@ -2047,7 +2056,7 @@
 | 
|  
 | 
|    // Perform GC to get unreferenced scripts evicted from the cache before
 | 
|    // returning the content.
 | 
| -  isolate_->heap()->CollectAllGarbage(false);
 | 
| +  isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags);
 | 
|  
 | 
|    // Get the scripts from the cache.
 | 
|    return script_cache_->GetScripts();
 | 
| @@ -2345,7 +2354,7 @@
 | 
|    Handle<JSValue> wrapper = GetScriptWrapper(script);
 | 
|  
 | 
|    // Call UpdateScriptBreakPoints expect no exceptions.
 | 
| -  bool caught_exception = false;
 | 
| +  bool caught_exception;
 | 
|    const int argc = 1;
 | 
|    Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
 | 
|    Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
 | 
| @@ -2486,7 +2495,7 @@
 | 
|                            exec_state.location(),
 | 
|                            Handle<Object>::cast(event_data).location(),
 | 
|                            event_listener_data_.location() };
 | 
| -  bool caught_exception = false;
 | 
| +  bool caught_exception;
 | 
|    Execution::TryCall(fun, isolate_->global(), argc, argv, &caught_exception);
 | 
|    // Silently ignore exceptions from debug event listeners.
 | 
|  }
 | 
| @@ -2929,6 +2938,94 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +EnterDebugger::EnterDebugger()
 | 
| +    : isolate_(Isolate::Current()),
 | 
| +      prev_(isolate_->debug()->debugger_entry()),
 | 
| +      it_(isolate_),
 | 
| +      has_js_frames_(!it_.done()),
 | 
| +      save_(isolate_) {
 | 
| +  Debug* debug = isolate_->debug();
 | 
| +  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
 | 
| +  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
 | 
| +
 | 
| +  // Link recursive debugger entry.
 | 
| +  debug->set_debugger_entry(this);
 | 
| +
 | 
| +  // Store the previous break id and frame id.
 | 
| +  break_id_ = debug->break_id();
 | 
| +  break_frame_id_ = debug->break_frame_id();
 | 
| +
 | 
| +  // Create the new break info. If there is no JavaScript frames there is no
 | 
| +  // break frame id.
 | 
| +  if (has_js_frames_) {
 | 
| +    debug->NewBreak(it_.frame()->id());
 | 
| +  } else {
 | 
| +    debug->NewBreak(StackFrame::NO_ID);
 | 
| +  }
 | 
| +
 | 
| +  // Make sure that debugger is loaded and enter the debugger context.
 | 
| +  load_failed_ = !debug->Load();
 | 
| +  if (!load_failed_) {
 | 
| +    // NOTE the member variable save which saves the previous context before
 | 
| +    // this change.
 | 
| +    isolate_->set_context(*debug->debug_context());
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +EnterDebugger::~EnterDebugger() {
 | 
| +  ASSERT(Isolate::Current() == isolate_);
 | 
| +  Debug* debug = isolate_->debug();
 | 
| +
 | 
| +  // Restore to the previous break state.
 | 
| +  debug->SetBreak(break_frame_id_, break_id_);
 | 
| +
 | 
| +  // Check for leaving the debugger.
 | 
| +  if (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()) {
 | 
| +      // Try to avoid any pending debug break breaking in the clear mirror
 | 
| +      // cache JavaScript code.
 | 
| +      if (isolate_->stack_guard()->IsDebugBreak()) {
 | 
| +        debug->set_interrupts_pending(DEBUGBREAK);
 | 
| +        isolate_->stack_guard()->Continue(DEBUGBREAK);
 | 
| +      }
 | 
| +      debug->ClearMirrorCache();
 | 
| +    }
 | 
| +
 | 
| +    // Request preemption and debug break when leaving the last debugger entry
 | 
| +    // if any of these where recorded while debugging.
 | 
| +    if (debug->is_interrupt_pending(PREEMPT)) {
 | 
| +      // This re-scheduling of preemption is to avoid starvation in some
 | 
| +      // debugging scenarios.
 | 
| +      debug->clear_interrupt_pending(PREEMPT);
 | 
| +      isolate_->stack_guard()->Preempt();
 | 
| +    }
 | 
| +    if (debug->is_interrupt_pending(DEBUGBREAK)) {
 | 
| +      debug->clear_interrupt_pending(DEBUGBREAK);
 | 
| +      isolate_->stack_guard()->DebugBreak();
 | 
| +    }
 | 
| +
 | 
| +    // If there are commands in the queue when leaving the debugger request
 | 
| +    // that these commands are processed.
 | 
| +    if (isolate_->debugger()->HasCommands()) {
 | 
| +      isolate_->stack_guard()->DebugCommand();
 | 
| +    }
 | 
| +
 | 
| +    // If leaving the debugger with the debugger no longer active unload it.
 | 
| +    if (!isolate_->debugger()->IsDebuggerActive()) {
 | 
| +      isolate_->debugger()->UnloadDebugger();
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  // Leaving this debugger entry.
 | 
| +  debug->set_debugger_entry(prev_);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  MessageImpl MessageImpl::NewEvent(DebugEvent event,
 | 
|                                    bool running,
 | 
|                                    Handle<JSObject> exec_state,
 | 
| 
 |