Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / v8 / src / debug.cc
index d7667f1..3ecf8ba 100644 (file)
@@ -1,29 +1,6 @@
 // Copyright 2012 the V8 project authors. 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.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
 
 #include "v8.h"
 
@@ -53,9 +30,6 @@
 namespace v8 {
 namespace internal {
 
-#ifdef ENABLE_DEBUGGER_SUPPORT
-
-
 Debug::Debug(Isolate* isolate)
     : has_break_points_(false),
       script_cache_(NULL),
@@ -63,10 +37,11 @@ Debug::Debug(Isolate* isolate)
       disable_break_(false),
       break_on_exception_(false),
       break_on_uncaught_exception_(false),
-      debug_break_return_(NULL),
-      debug_break_slot_(NULL),
+      promise_catch_handlers_(0),
+      promise_getters_(0),
       isolate_(isolate) {
   memset(registers_, 0, sizeof(JSCallerSavedBuffer));
+  ThreadInit();
 }
 
 
@@ -406,6 +381,7 @@ bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
     if (target_code->kind() == Code::STUB) {
       return target_code->major_key() == CodeStub::CallFunction;
     }
+    return target_code->is_call_stub();
   }
   return false;
 }
@@ -688,21 +664,6 @@ void ScriptCache::HandleWeakScript(
 }
 
 
-void Debug::SetUp(bool create_heap_objects) {
-  ThreadInit();
-  if (create_heap_objects) {
-    // Get code to handle debug break on return.
-    debug_break_return_ =
-        isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
-    ASSERT(debug_break_return_->IsCode());
-    // Get code to handle debug break in debug break slots.
-    debug_break_slot_ =
-        isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
-    ASSERT(debug_break_slot_->IsCode());
-  }
-}
-
-
 void Debug::HandleWeakDebugInfo(
     const v8::WeakCallbackData<v8::Value, void>& data) {
   Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
@@ -753,8 +714,8 @@ bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
   Handle<String> source_code =
       isolate->bootstrapper()->NativesSourceLookup(index);
   Vector<const char> name = Natives::GetScriptName(index);
-  Handle<String> script_name = factory->NewStringFromAscii(name);
-  ASSERT(!script_name.is_null());
+  Handle<String> script_name =
+      factory->NewStringFromAscii(name).ToHandleChecked();
   Handle<Context> context = isolate->native_context();
 
   // Compile the script.
@@ -774,19 +735,19 @@ bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
   }
 
   // Execute the shared function in the debugger context.
-  bool caught_exception;
   Handle<JSFunction> function =
       factory->NewFunctionFromSharedFunctionInfo(function_info, context);
 
-  Handle<Object> exception =
+  Handle<Object> exception;
+  MaybeHandle<Object> result =
       Execution::TryCall(function,
                          Handle<Object>(context->global_object(), isolate),
                          0,
                          NULL,
-                         &caught_exception);
+                         &exception);
 
   // Check for caught exceptions.
-  if (caught_exception) {
+  if (result.is_null()) {
     ASSERT(!isolate->has_pending_exception());
     MessageLocation computed_location;
     isolate->ComputeLocation(&computed_location);
@@ -847,7 +808,7 @@ bool Debug::Load() {
   Handle<String> key = isolate_->factory()->InternalizeOneByteString(
       STATIC_ASCII_VECTOR("builtins"));
   Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
-  RETURN_IF_EMPTY_HANDLE_VALUE(
+  RETURN_ON_EXCEPTION_VALUE(
       isolate_,
       JSReceiver::SetProperty(global,
                               key,
@@ -906,12 +867,6 @@ void Debug::PreemptionWhileInDebugger() {
 }
 
 
-void Debug::Iterate(ObjectVisitor* v) {
-  v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
-  v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
-}
-
-
 Object* Debug::Break(Arguments args) {
   Heap* heap = isolate_->heap();
   HandleScope scope(isolate_);
@@ -1061,7 +1016,7 @@ Object* Debug::Break(Arguments args) {
 }
 
 
-RUNTIME_FUNCTION(Object*, Debug_Break) {
+RUNTIME_FUNCTION(Debug_Break) {
   return isolate->debug()->Break(args);
 }
 
@@ -1116,31 +1071,26 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
   Handle<String> is_break_point_triggered_string =
       factory->InternalizeOneByteString(
           STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
+  Handle<GlobalObject> debug_global(debug_context()->global_object());
   Handle<JSFunction> check_break_point =
-    Handle<JSFunction>(JSFunction::cast(
-        debug_context()->global_object()->GetPropertyNoExceptionThrown(
-            *is_break_point_triggered_string)));
+    Handle<JSFunction>::cast(Object::GetProperty(
+        debug_global, is_break_point_triggered_string).ToHandleChecked());
 
   // Get the break id as an object.
   Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
 
   // Call HandleBreakPointx.
-  bool caught_exception;
   Handle<Object> argv[] = { break_id, break_point_object };
-  Handle<Object> result = Execution::TryCall(check_break_point,
-                                             isolate_->js_builtins_object(),
-                                             ARRAY_SIZE(argv),
-                                             argv,
-                                             &caught_exception);
-
-  // If exception or non boolean result handle as not triggered
-  if (caught_exception || !result->IsBoolean()) {
+  Handle<Object> result;
+  if (!Execution::TryCall(check_break_point,
+                          isolate_->js_builtins_object(),
+                          ARRAY_SIZE(argv),
+                          argv).ToHandle(&result)) {
     return false;
   }
 
   // Return whether the break point is triggered.
-  ASSERT(!result.is_null());
-  return (*result)->IsTrue();
+  return result->IsTrue();
 }
 
 
@@ -1348,6 +1298,53 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) {
 }
 
 
+void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) {
+  Handle<JSFunction> promise_getter_global = Handle<JSFunction>::cast(
+      isolate_->global_handles()->Create(*promise_getter));
+  StackHandler* handler =
+      StackHandler::FromAddress(Isolate::handler(isolate_->thread_local_top()));
+  promise_getters_.Add(promise_getter_global);
+  promise_catch_handlers_.Add(handler);
+}
+
+
+void Debug::PromiseHandleEpilogue() {
+  if (promise_catch_handlers_.length() == 0) return;
+  promise_catch_handlers_.RemoveLast();
+  Handle<Object> promise_getter = promise_getters_.RemoveLast();
+  isolate_->global_handles()->Destroy(promise_getter.location());
+}
+
+
+Handle<Object> Debug::GetPromiseForUncaughtException() {
+  Handle<Object> undefined = isolate_->factory()->undefined_value();
+  if (promise_getters_.length() == 0) return undefined;
+  Handle<JSFunction> promise_getter = promise_getters_.last();
+  StackHandler* promise_catch = promise_catch_handlers_.last();
+  // Find the top-most try-catch handler.
+  StackHandler* handler = StackHandler::FromAddress(
+      Isolate::handler(isolate_->thread_local_top()));
+  while (handler != NULL && !handler->is_catch()) {
+    handler = handler->next();
+  }
+#ifdef DEBUG
+  // Make sure that our promise catch handler is in the list of handlers,
+  // even if it's not the top-most try-catch handler.
+  StackHandler* temp = handler;
+  while (temp != promise_catch && !temp->is_catch()) {
+    temp = temp->next();
+    CHECK(temp != NULL);
+  }
+#endif  // DEBUG
+
+  if (handler == promise_catch) {
+    return Execution::Call(
+        isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked();
+  }
+  return undefined;
+}
+
+
 void Debug::PrepareStep(StepAction step_action,
                         int step_count,
                         StackFrame::Id frame_id) {
@@ -1425,6 +1422,9 @@ void Debug::PrepareStep(StepAction step_action,
       bool is_call_target = false;
       Address target = it.rinfo()->target_address();
       Code* code = Code::GetCodeFromTargetAddress(target);
+      if (code->is_call_stub()) {
+        is_call_target = true;
+      }
       if (code->is_inline_cache_stub()) {
         is_inline_cache_stub = true;
         is_load_or_store = !is_call_target;
@@ -1439,8 +1439,9 @@ void Debug::PrepareStep(StepAction step_action,
         maybe_call_function_stub =
             Code::GetCodeFromTargetAddress(original_target);
       }
-      if (maybe_call_function_stub->kind() == Code::STUB &&
-          maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
+      if ((maybe_call_function_stub->kind() == Code::STUB &&
+           maybe_call_function_stub->major_key() == CodeStub::CallFunction) ||
+          maybe_call_function_stub->kind() == Code::CALL_IC) {
         // Save reference to the code as we may need it to find out arguments
         // count for 'step in' later.
         call_function_stub = Handle<Code>(maybe_call_function_stub);
@@ -1496,6 +1497,7 @@ void Debug::PrepareStep(StepAction step_action,
     } else if (!call_function_stub.is_null()) {
       // If it's CallFunction stub ensure target function is compiled and flood
       // it with one shot breakpoints.
+      bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
 
       // Find out number of arguments from the stub minor key.
       // Reverse lookup required as the minor key cannot be retrieved
@@ -1511,11 +1513,13 @@ void Debug::PrepareStep(StepAction step_action,
       uint32_t key = Smi::cast(*obj)->value();
       // Argc in the stub is the number of arguments passed - not the
       // expected arguments of the called function.
-      int call_function_arg_count =
-          CallFunctionStub::ExtractArgcFromMinorKey(
+      int call_function_arg_count = is_call_ic
+          ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
+          : CallFunctionStub::ExtractArgcFromMinorKey(
               CodeStub::MinorKeyFromKey(key));
-      ASSERT(call_function_stub->major_key() ==
-             CodeStub::MajorKeyFromKey(key));
+
+      ASSERT(is_call_ic ||
+             call_function_stub->major_key() == CodeStub::MajorKeyFromKey(key));
 
       // Find target function on the expression stack.
       // Expression stack looks like this (top to bottom):
@@ -1643,6 +1647,9 @@ Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
   // used by the call site.
   if (code->is_inline_cache_stub()) {
     switch (code->kind()) {
+      case Code::CALL_IC:
+        return isolate->builtins()->CallICStub_DebugBreak();
+
       case Code::LOAD_IC:
         return isolate->builtins()->LoadIC_DebugBreak();
 
@@ -1671,11 +1678,7 @@ Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
   }
   if (code->kind() == Code::STUB) {
     ASSERT(code->major_key() == CodeStub::CallFunction);
-    if (code->has_function_cache()) {
-      return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
-    } else {
-      return isolate->builtins()->CallFunctionStub_DebugBreak();
-    }
+    return isolate->builtins()->CallFunctionStub_DebugBreak();
   }
 
   UNREACHABLE();
@@ -1878,6 +1881,59 @@ static void CollectActiveFunctionsFromThread(
 }
 
 
+// Figure out how many bytes of "pc_offset" correspond to actual code by
+// subtracting off the bytes that correspond to constant/veneer pools.  See
+// Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
+// is only useful for architectures using constant pools or veneer pools.
+static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
+  ASSERT_EQ(code->kind(), Code::FUNCTION);
+  ASSERT(!code->has_debug_break_slots());
+  ASSERT_LE(0, pc_offset);
+  ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start());
+
+  int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
+             RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
+  byte *pc = code->instruction_start() + pc_offset;
+  int code_offset = pc_offset;
+  for (RelocIterator it(code, mask); !it.done(); it.next()) {
+    RelocInfo* info = it.rinfo();
+    if (info->pc() >= pc) break;
+    ASSERT(RelocInfo::IsConstPool(info->rmode()));
+    code_offset -= static_cast<int>(info->data());
+    ASSERT_LE(0, code_offset);
+  }
+
+  return code_offset;
+}
+
+
+// The inverse of ComputeCodeOffsetFromPcOffset.
+static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
+  ASSERT_EQ(code->kind(), Code::FUNCTION);
+
+  int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
+             RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
+             RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
+  int reloc = 0;
+  for (RelocIterator it(code, mask); !it.done(); it.next()) {
+    RelocInfo* info = it.rinfo();
+    if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
+    if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
+      reloc += Assembler::kDebugBreakSlotLength;
+    } else {
+      ASSERT(RelocInfo::IsConstPool(info->rmode()));
+      reloc += static_cast<int>(info->data());
+    }
+  }
+
+  int pc_offset = code_offset + reloc;
+
+  ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end());
+
+  return pc_offset;
+}
+
+
 static void RedirectActivationsToRecompiledCodeOnThread(
     Isolate* isolate,
     ThreadLocalTop* top) {
@@ -1899,51 +1955,13 @@ static void RedirectActivationsToRecompiledCodeOnThread(
       continue;
     }
 
-    // Iterate over the RelocInfo in the original code to compute the sum of the
-    // constant pools and veneer pools sizes. (See Assembler::CheckConstPool()
-    // and Assembler::CheckVeneerPool())
-    // Note that this is only useful for architectures using constant pools or
-    // veneer pools.
-    int pool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
-                    RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
-    int frame_pool_size = 0;
-    for (RelocIterator it(*frame_code, pool_mask); !it.done(); it.next()) {
-      RelocInfo* info = it.rinfo();
-      if (info->pc() >= frame->pc()) break;
-      frame_pool_size += static_cast<int>(info->data());
-    }
-    intptr_t frame_offset =
-      frame->pc() - frame_code->instruction_start() - frame_pool_size;
-
-    // Iterate over the RelocInfo for new code to find the number of bytes
-    // generated for debug slots and constant pools.
-    int debug_break_slot_bytes = 0;
-    int new_code_pool_size = 0;
-    int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
-               RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
-               RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
-    for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
-      // Check if the pc in the new code with debug break
-      // slots is before this slot.
-      RelocInfo* info = it.rinfo();
-      intptr_t new_offset = info->pc() - new_code->instruction_start() -
-                            new_code_pool_size - debug_break_slot_bytes;
-      if (new_offset >= frame_offset) {
-        break;
-      }
-
-      if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
-        debug_break_slot_bytes += Assembler::kDebugBreakSlotLength;
-      } else {
-        ASSERT(RelocInfo::IsConstPool(info->rmode()));
-        // The size of the pools is encoded in the data.
-        new_code_pool_size += static_cast<int>(info->data());
-      }
-    }
+    int old_pc_offset =
+        static_cast<int>(frame->pc() - frame_code->instruction_start());
+    int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
+    int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
 
     // Compute the equivalent pc in the new code.
-    byte* new_pc = new_code->instruction_start() + frame_offset +
-                   debug_break_slot_bytes + new_code_pool_size;
+    byte* new_pc = new_code->instruction_start() + new_pc_offset;
 
     if (FLAG_trace_deopt) {
       PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
@@ -1999,6 +2017,55 @@ class ActiveFunctionsRedirector : public ThreadVisitor {
 };
 
 
+class ForceDebuggerActive {
+ public:
+  explicit ForceDebuggerActive(Isolate *isolate) {
+    isolate_ = isolate;
+    old_state_ = isolate->debugger()->force_debugger_active();
+    isolate_->debugger()->set_force_debugger_active(true);
+  }
+
+  ~ForceDebuggerActive() {
+    isolate_->debugger()->set_force_debugger_active(old_state_);
+  }
+
+ private:
+  Isolate *isolate_;
+  bool old_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(ForceDebuggerActive);
+};
+
+
+void Debug::MaybeRecompileFunctionForDebugging(Handle<JSFunction> function) {
+  ASSERT_EQ(Code::FUNCTION, function->code()->kind());
+  ASSERT_EQ(function->code(), function->shared()->code());
+
+  if (function->code()->has_debug_break_slots()) return;
+
+  ForceDebuggerActive force_debugger_active(isolate_);
+  MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function);
+  // Recompilation can fail.  In that case leave the code as it was.
+  if (!code.is_null())
+    function->ReplaceCode(*code.ToHandleChecked());
+  ASSERT_EQ(function->code(), function->shared()->code());
+}
+
+
+void Debug::RecompileAndRelocateSuspendedGenerators(
+    const List<Handle<JSGeneratorObject> > &generators) {
+  for (int i = 0; i < generators.length(); i++) {
+    Handle<JSFunction> fun(generators[i]->function());
+
+    MaybeRecompileFunctionForDebugging(fun);
+
+    int code_offset = generators[i]->continuation();
+    int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
+    generators[i]->set_continuation(pc_offset);
+  }
+}
+
+
 void Debug::PrepareForBreakPoints() {
   // If preparing for the first break point make sure to deoptimize all
   // functions as debugging does not work with optimized code.
@@ -2018,6 +2085,21 @@ void Debug::PrepareForBreakPoints() {
     // is used both in GC and non-GC code.
     List<Handle<JSFunction> > active_functions(100);
 
+    // A list of all suspended generators.
+    List<Handle<JSGeneratorObject> > suspended_generators;
+
+    // A list of all generator functions.  We need to recompile all functions,
+    // but we don't know until after visiting the whole heap which generator
+    // functions have suspended activations and which do not.  As in the case of
+    // functions with activations on the stack, we need to be careful with
+    // generator functions with suspended activations because although they
+    // should be recompiled, recompilation can fail, and we need to avoid
+    // leaving the heap in an inconsistent state.
+    //
+    // We could perhaps avoid this list and instead re-use the GC metadata
+    // links.
+    List<Handle<JSFunction> > generator_functions;
+
     {
       // We are going to iterate heap to find all functions without
       // debug break slots.
@@ -2055,6 +2137,11 @@ void Debug::PrepareForBreakPoints() {
           if (function->IsBuiltin()) continue;
           if (shared->code()->gc_metadata() == active_code_marker) continue;
 
+          if (shared->is_generator()) {
+            generator_functions.Add(Handle<JSFunction>(function, isolate_));
+            continue;
+          }
+
           Code::Kind kind = function->code()->kind();
           if (kind == Code::FUNCTION &&
               !function->code()->has_debug_break_slots()) {
@@ -2074,6 +2161,24 @@ void Debug::PrepareForBreakPoints() {
               function->shared()->set_code(*lazy_compile);
             }
           }
+        } else if (obj->IsJSGeneratorObject()) {
+          JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
+          if (!gen->is_suspended()) continue;
+
+          JSFunction* fun = gen->function();
+          ASSERT_EQ(fun->code()->kind(), Code::FUNCTION);
+          if (fun->code()->has_debug_break_slots()) continue;
+
+          int pc_offset = gen->continuation();
+          ASSERT_LT(0, pc_offset);
+
+          int code_offset =
+              ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
+
+          // This will be fixed after we recompile the functions.
+          gen->set_continuation(code_offset);
+
+          suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
         }
       }
 
@@ -2084,41 +2189,35 @@ void Debug::PrepareForBreakPoints() {
       }
     }
 
+    // Recompile generator functions that have suspended activations, and
+    // relocate those activations.
+    RecompileAndRelocateSuspendedGenerators(suspended_generators);
+
+    // Mark generator functions that didn't have suspended activations for lazy
+    // recompilation.  Note that this set does not include any active functions.
+    for (int i = 0; i < generator_functions.length(); i++) {
+      Handle<JSFunction> &function = generator_functions[i];
+      if (function->code()->kind() != Code::FUNCTION) continue;
+      if (function->code()->has_debug_break_slots()) continue;
+      function->set_code(*lazy_compile);
+      function->shared()->set_code(*lazy_compile);
+    }
+
     // Now recompile all functions with activation frames and and
-    // patch the return address to run in the new compiled code.
+    // patch the return address to run in the new compiled code.  It could be
+    // that some active functions were recompiled already by the suspended
+    // generator recompilation pass above; a generator with suspended
+    // activations could also have active activations.  That's fine.
     for (int i = 0; i < active_functions.length(); i++) {
       Handle<JSFunction> function = active_functions[i];
       Handle<SharedFunctionInfo> shared(function->shared());
 
-      if (function->code()->kind() == Code::FUNCTION &&
-          function->code()->has_debug_break_slots()) {
-        // Nothing to do. Function code already had debug break slots.
-        continue;
-      }
-
       // If recompilation is not possible just skip it.
-      if (shared->is_toplevel() ||
-          !shared->allows_lazy_compilation() ||
-          shared->code()->kind() == Code::BUILTIN) {
-        continue;
-      }
-
-      // Make sure that the shared full code is compiled with debug
-      // break slots.
-      if (!shared->code()->has_debug_break_slots()) {
-        // Try to compile the full code with debug break slots. If it
-        // fails just keep the current code.
-        bool prev_force_debugger_active =
-            isolate_->debugger()->force_debugger_active();
-        isolate_->debugger()->set_force_debugger_active(true);
-        Handle<Code> code = Compiler::GetCodeForDebugging(function);
-        function->ReplaceCode(*code);
-        isolate_->debugger()->set_force_debugger_active(
-            prev_force_debugger_active);
-      }
+      if (shared->is_toplevel()) continue;
+      if (!shared->allows_lazy_compilation()) continue;
+      if (shared->code()->kind() == Code::BUILTIN) continue;
 
-      // Keep function code in sync with shared function info.
-      function->set_code(shared->code());
+      MaybeRecompileFunctionForDebugging(function);
     }
 
     RedirectActivationsToRecompiledCodeOnThread(isolate_,
@@ -2227,10 +2326,10 @@ Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
       // will compile all inner functions that cannot be compiled without a
       // context, because Compiler::BuildFunctionInfo checks whether the
       // debugger is active.
-      Handle<Code> result = target_function.is_null()
+      MaybeHandle<Code> maybe_result = target_function.is_null()
           ? Compiler::GetUnoptimizedCode(target)
           : Compiler::GetUnoptimizedCode(target_function);
-      if (result.is_null()) return isolate_->heap()->undefined_value();
+      if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
     }
   }  // End while loop.
 
@@ -2463,14 +2562,14 @@ void Debug::ClearMirrorCache() {
   // Clear the mirror cache.
   Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
       STATIC_ASCII_VECTOR("ClearMirrorCache"));
-  Handle<Object> fun(
-      isolate_->global_object()->GetPropertyNoExceptionThrown(*function_name),
-      isolate_);
+  Handle<Object> fun = Object::GetProperty(
+      isolate_->global_object(), function_name).ToHandleChecked();
   ASSERT(fun->IsJSFunction());
-  bool caught_exception;
-  Execution::TryCall(Handle<JSFunction>::cast(fun),
+  Execution::TryCall(
+      Handle<JSFunction>::cast(fun),
       Handle<JSObject>(Debug::debug_context()->global_object()),
-      0, NULL, &caught_exception);
+      0,
+      NULL);
 }
 
 
@@ -2591,113 +2690,82 @@ Debugger::Debugger(Isolate* isolate)
 Debugger::~Debugger() {}
 
 
-Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
-                                      int argc,
-                                      Handle<Object> argv[],
-                                      bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeJSObject(
+    Vector<const char> constructor_name,
+    int argc,
+    Handle<Object> argv[]) {
   ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
 
   // Create the execution state object.
   Handle<String> constructor_str =
       isolate_->factory()->InternalizeUtf8String(constructor_name);
   ASSERT(!constructor_str.is_null());
-  Handle<Object> constructor(
-      isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
-      isolate_);
+  Handle<Object> constructor = Object::GetProperty(
+      isolate_->global_object(), constructor_str).ToHandleChecked();
   ASSERT(constructor->IsJSFunction());
-  if (!constructor->IsJSFunction()) {
-    *caught_exception = true;
-    return isolate_->factory()->undefined_value();
-  }
-  Handle<Object> js_object = Execution::TryCall(
+  if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
+  return Execution::TryCall(
       Handle<JSFunction>::cast(constructor),
       Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
       argc,
-      argv,
-      caught_exception);
-  return js_object;
+      argv);
 }
 
 
-Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeExecutionState() {
   // Create the execution state object.
   Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
       isolate_->debug()->break_id());
   Handle<Object> argv[] = { break_id };
-  return MakeJSObject(CStrVector("MakeExecutionState"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
+  return MakeJSObject(CStrVector("MakeExecutionState"), ARRAY_SIZE(argv), argv);
 }
 
 
-Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
-                                        Handle<Object> break_points_hit,
-                                        bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeBreakEvent(Handle<Object> break_points_hit) {
+  Handle<Object> exec_state;
+  if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
   // Create the new break event object.
   Handle<Object> argv[] = { exec_state, break_points_hit };
-  return MakeJSObject(CStrVector("MakeBreakEvent"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
+  return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv);
 }
 
 
-Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
-                                            Handle<Object> exception,
-                                            bool uncaught,
-                                            bool* caught_exception) {
-  Factory* factory = isolate_->factory();
+MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
+                                                 bool uncaught,
+                                                 Handle<Object> promise) {
+  Handle<Object> exec_state;
+  if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
   // Create the new exception event object.
   Handle<Object> argv[] = { exec_state,
                             exception,
-                            factory->ToBoolean(uncaught) };
-  return MakeJSObject(CStrVector("MakeExceptionEvent"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
+                            isolate_->factory()->ToBoolean(uncaught),
+                            promise };
+  return MakeJSObject(CStrVector("MakeExceptionEvent"), ARRAY_SIZE(argv), argv);
 }
 
 
-Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
-                                              bool* caught_exception) {
-  // Create the new function event object.
-  Handle<Object> argv[] = { function };
-  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
-}
-
-
-Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
-                                          bool before,
-                                          bool* caught_exception) {
-  Factory* factory = isolate_->factory();
+MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
+                                               bool before) {
+  Handle<Object> exec_state;
+  if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
   // Create the compile event object.
-  Handle<Object> exec_state = MakeExecutionState(caught_exception);
-  Handle<Object> script_wrapper = GetScriptWrapper(script);
+  Handle<Object> script_wrapper = Script::GetWrapper(script);
   Handle<Object> argv[] = { exec_state,
                             script_wrapper,
-                            factory->ToBoolean(before) };
-  return MakeJSObject(CStrVector("MakeCompileEvent"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
+                            isolate_->factory()->ToBoolean(before) };
+  return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv);
 }
 
 
-Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
-                                                  bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeScriptCollectedEvent(int id) {
+  Handle<Object> exec_state;
+  if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
   // Create the script collected event object.
-  Handle<Object> exec_state = MakeExecutionState(caught_exception);
   Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
   Handle<Object> argv[] = { exec_state, id_object };
 
-  return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
-                      ARRAY_SIZE(argv),
-                      argv,
-                      caught_exception);
+  return MakeJSObject(
+      CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv);
 }
 
 
@@ -2709,6 +2777,9 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
   if (debug->InDebugger()) return;
   if (!Debugger::EventActive(v8::Exception)) return;
 
+  Handle<Object> promise = debug->GetPromiseForUncaughtException();
+  uncaught |= !promise->IsUndefined();
+
   // Bail out if exception breaks are not active
   if (uncaught) {
     // Uncaught exceptions are reported by either flags.
@@ -2725,16 +2796,12 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
 
   // 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) {
+  if (!MakeExceptionEvent(
+          exception, uncaught, promise).ToHandle(&event_data)) {
     return;
   }
 
@@ -2758,17 +2825,9 @@ void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
   ASSERT(isolate_->context() == *isolate_->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;
-  }
+  if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
 
   // Process debug event.
   ProcessDebugEvent(v8::Break,
@@ -2790,12 +2849,9 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
   if (debugger.FailedToEnter()) return;
 
   // Create the event data object.
-  bool caught_exception = false;
-  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
+  Handle<Object> event_data;
   // Bail out and don't call debugger if exception.
-  if (caught_exception) {
-    return;
-  }
+  if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
 
   // Process debug event.
   ProcessDebugEvent(v8::BeforeCompile,
@@ -2833,11 +2889,10 @@ void Debugger::OnAfterCompile(Handle<Script> script,
   Handle<String> update_script_break_points_string =
       isolate_->factory()->InternalizeOneByteString(
           STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
+  Handle<GlobalObject> debug_global(debug->debug_context()->global_object());
   Handle<Object> update_script_break_points =
-      Handle<Object>(
-          debug->debug_context()->global_object()->GetPropertyNoExceptionThrown(
-              *update_script_break_points_string),
-          isolate_);
+      Object::GetProperty(
+          debug_global, update_script_break_points_string).ToHandleChecked();
   if (!update_script_break_points->IsJSFunction()) {
     return;
   }
@@ -2845,17 +2900,14 @@ void Debugger::OnAfterCompile(Handle<Script> script,
 
   // Wrap the script object in a proper JS object before passing it
   // to JavaScript.
-  Handle<JSValue> wrapper = GetScriptWrapper(script);
+  Handle<Object> wrapper = Script::GetWrapper(script);
 
   // Call UpdateScriptBreakPoints expect no exceptions.
-  bool caught_exception;
   Handle<Object> argv[] = { wrapper };
-  Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
-                     isolate_->js_builtins_object(),
-                     ARRAY_SIZE(argv),
-                     argv,
-                     &caught_exception);
-  if (caught_exception) {
+  if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
+                         isolate_->js_builtins_object(),
+                         ARRAY_SIZE(argv),
+                         argv).is_null()) {
     return;
   }
   // Bail out based on state or if there is no listener for this event
@@ -2863,17 +2915,12 @@ void Debugger::OnAfterCompile(Handle<Script> script,
   if (!Debugger::EventActive(v8::AfterCompile)) return;
 
   // Create the compile state object.
-  Handle<Object> event_data = MakeCompileEvent(script,
-                                               false,
-                                               &caught_exception);
+  Handle<Object> event_data;
   // Bail out and don't call debugger if exception.
-  if (caught_exception) {
-    return;
-  }
+  if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
+
   // Process debug event.
-  ProcessDebugEvent(v8::AfterCompile,
-                    Handle<JSObject>::cast(event_data),
-                    true);
+  ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
 }
 
 
@@ -2890,13 +2937,9 @@ void Debugger::OnScriptCollected(int id) {
   if (debugger.FailedToEnter()) return;
 
   // Create the script collected state object.
-  bool caught_exception = false;
-  Handle<Object> event_data = MakeScriptCollectedEvent(id,
-                                                       &caught_exception);
+  Handle<Object> event_data;
   // Bail out and don't call debugger if exception.
-  if (caught_exception) {
-    return;
-  }
+  if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return;
 
   // Process debug event.
   ProcessDebugEvent(v8::ScriptCollected,
@@ -2916,11 +2959,10 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
   }
 
   // Create the execution state.
-  bool caught_exception = false;
-  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
-  if (caught_exception) {
-    return;
-  }
+  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,
@@ -2991,12 +3033,10 @@ void Debugger::CallJSEventCallback(v8::DebugEvent event,
                             exec_state,
                             event_data,
                             event_listener_data_ };
-  bool caught_exception;
   Execution::TryCall(fun,
                      isolate_->global_object(),
                      ARRAY_SIZE(argv),
-                     argv,
-                     &caught_exception);
+                     argv);
   // Silently ignore exceptions from debug event listeners.
 }
 
@@ -3248,7 +3288,8 @@ void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
 
 
 void Debugger::ListenersChanged() {
-  if (IsDebuggerActive()) {
+  bool active = IsDebuggerActive();
+  if (active) {
     // Disable the compilation cache when the debugger is active.
     isolate_->compilation_cache()->Disable();
     debugger_unload_pending_ = false;
@@ -3350,9 +3391,8 @@ bool Debugger::IsDebuggerActive() {
 }
 
 
-Handle<Object> Debugger::Call(Handle<JSFunction> fun,
-                              Handle<Object> data,
-                              bool* pending_exception) {
+MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun,
+                                   Handle<Object> data) {
   // When calling functions in the debugger prevent it from beeing unloaded.
   Debugger::never_unload_debugger_ = true;
 
@@ -3363,22 +3403,19 @@ Handle<Object> Debugger::Call(Handle<JSFunction> fun,
   }
 
   // Create the execution state.
-  bool caught_exception = false;
-  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
-  if (caught_exception) {
+  Handle<Object> exec_state;
+  if (!MakeExecutionState().ToHandle(&exec_state)) {
     return isolate_->factory()->undefined_value();
   }
 
   Handle<Object> argv[] = { exec_state, data };
-  Handle<Object> result = Execution::Call(
+  return Execution::Call(
       isolate_,
       fun,
       Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
                      isolate_),
       ARRAY_SIZE(argv),
-      argv,
-      pending_exception);
-  return result;
+      argv);
 }
 
 
@@ -3397,7 +3434,7 @@ bool Debugger::StartAgent(const char* name, int port,
     // Once become suspended, V8 will stay so indefinitely long, until remote
     // debugger connects and issues "continue" command.
     Debugger::message_handler_ = StubMessageHandler2;
-    v8::Debug::DebugBreak();
+    v8::Debug::DebugBreak(reinterpret_cast<v8::Isolate*>(isolate_));
   }
 
   if (agent_ == NULL) {
@@ -3597,20 +3634,21 @@ v8::Handle<v8::Object> MessageImpl::GetEventData() const {
 
 
 v8::Handle<v8::String> MessageImpl::GetJSON() const {
-  v8::EscapableHandleScope scope(
-      reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
+  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 = GetProperty(event_data_, "toJSONProtocol");
+    Handle<Object> fun = Object::GetProperty(
+        isolate, event_data_, "toJSONProtocol").ToHandleChecked();
     if (!fun->IsJSFunction()) {
       return v8::Handle<v8::String>();
     }
-    bool caught_exception;
-    Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
-                                             event_data_,
-                                             0, NULL, &caught_exception);
-    if (caught_exception || !json->IsString()) {
+
+    MaybeHandle<Object> maybe_json =
+        Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
+    Handle<Object> json;
+    if (!maybe_json.ToHandle(&json) || !json->IsString()) {
       return v8::Handle<v8::String>();
     }
     return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
@@ -3815,6 +3853,4 @@ void MessageDispatchHelperThread::Run() {
   }
 }
 
-#endif  // ENABLE_DEBUGGER_SUPPORT
-
 } }  // namespace v8::internal