Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/debug/arm/debug-arm.cc b/src/debug/arm/debug-arm.cc
index 2d4cbf1..5fdda4f 100644
--- a/src/debug/arm/debug-arm.cc
+++ b/src/debug/arm/debug-arm.cc
@@ -62,6 +62,10 @@
   patcher.masm()->blx(ip);
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  Instr current_instr = Assembler::instr_at(pc);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/arm64/debug-arm64.cc b/src/debug/arm64/debug-arm64.cc
index c2b60a9..3e4b67c 100644
--- a/src/debug/arm64/debug-arm64.cc
+++ b/src/debug/arm64/debug-arm64.cc
@@ -74,6 +74,10 @@
   patcher.blr(ip0);
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  Instruction* current_instr = reinterpret_cast<Instruction*>(pc);
+  return !current_instr->IsNop(Assembler::DEBUG_BREAK_NOP);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index e19b93e..8114c21 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -111,7 +111,7 @@
   // Skip the global proxy as it has no properties and always delegates to the
   // real global object.
   if (result->IsJSGlobalProxy()) {
-    PrototypeIterator iter(isolate, result);
+    PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result));
     // TODO(verwaest): This will crash when the global proxy is detached.
     result = PrototypeIterator::GetCurrent<JSObject>(iter);
   }
@@ -128,7 +128,7 @@
       inlined_jsframe_index_(inlined_jsframe_index) {
   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
   Handle<JSFunction> local_function =
-      handle(JSFunction::cast(frame_inspector.GetFunction()));
+      Handle<JSFunction>::cast(frame_inspector.GetFunction());
   Handle<Context> outer_context(local_function->context());
   native_context_ = Handle<Context>(outer_context->native_context());
   Handle<JSFunction> global_function(native_context_->closure());
@@ -302,8 +302,7 @@
   if (maybe.FromJust()) return;
 
   // FunctionGetArguments can't throw an exception.
-  Handle<JSObject> arguments =
-      Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
+  Handle<JSObject> arguments = Accessors::FunctionGetArguments(function);
   Handle<String> arguments_str = isolate_->factory()->arguments_string();
   JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
                                            NONE)
@@ -347,6 +346,7 @@
       // within debug-evaluate.
       continue;
     }
+    if (value->IsTheHole()) continue;  // Value is not initialized yet (in TDZ).
     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
   }
 }
diff --git a/src/debug/debug-frames.cc b/src/debug/debug-frames.cc
index 012d291..25634be 100644
--- a/src/debug/debug-frames.cc
+++ b/src/debug/debug-frames.cc
@@ -15,6 +15,7 @@
   has_adapted_arguments_ = frame_->has_adapted_arguments();
   is_bottommost_ = inlined_jsframe_index == 0;
   is_optimized_ = frame_->is_optimized();
+  is_interpreted_ = frame_->is_interpreted();
   // Calculate the deoptimized frame.
   if (frame->is_optimized()) {
     // TODO(turbofan): Revisit once we support deoptimization.
@@ -44,33 +45,41 @@
                        : frame_->ComputeParametersCount();
 }
 
-
-Object* FrameInspector::GetFunction() {
-  return is_optimized_ ? deoptimized_frame_->GetFunction() : frame_->function();
+Handle<Object> FrameInspector::GetFunction() {
+  return is_optimized_ ? deoptimized_frame_->GetFunction()
+                       : handle(frame_->function(), isolate_);
 }
 
-
-Object* FrameInspector::GetParameter(int index) {
+Handle<Object> FrameInspector::GetParameter(int index) {
   return is_optimized_ ? deoptimized_frame_->GetParameter(index)
-                       : frame_->GetParameter(index);
+                       : handle(frame_->GetParameter(index), isolate_);
 }
 
-
-Object* FrameInspector::GetExpression(int index) {
+Handle<Object> FrameInspector::GetExpression(int index) {
   // TODO(turbofan): Revisit once we support deoptimization.
   if (frame_->LookupCode()->is_turbofanned() &&
       frame_->function()->shared()->asm_function() &&
       !FLAG_turbo_asm_deoptimization) {
-    return isolate_->heap()->undefined_value();
+    return isolate_->factory()->undefined_value();
   }
   return is_optimized_ ? deoptimized_frame_->GetExpression(index)
-                       : frame_->GetExpression(index);
+                       : handle(frame_->GetExpression(index), isolate_);
 }
 
 
 int FrameInspector::GetSourcePosition() {
-  return is_optimized_ ? deoptimized_frame_->GetSourcePosition()
-                       : frame_->LookupCode()->SourcePosition(frame_->pc());
+  if (is_optimized_) {
+    return deoptimized_frame_->GetSourcePosition();
+  } else if (is_interpreted_) {
+    InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
+    BytecodeArray* bytecode_array =
+        frame->function()->shared()->bytecode_array();
+    return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
+  } else {
+    Code* code = frame_->LookupCode();
+    int offset = static_cast<int>(frame_->pc() - code->instruction_start());
+    return code->SourcePosition(offset);
+  }
 }
 
 
@@ -80,9 +89,9 @@
              : frame_->IsConstructor();
 }
 
-
-Object* FrameInspector::GetContext() {
-  return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context();
+Handle<Object> FrameInspector::GetContext() {
+  return is_optimized_ ? deoptimized_frame_->GetContext()
+                       : handle(frame_->context(), isolate_);
 }
 
 
@@ -92,6 +101,7 @@
   DCHECK(has_adapted_arguments_);
   frame_ = frame;
   is_optimized_ = frame_->is_optimized();
+  is_interpreted_ = frame_->is_interpreted();
   DCHECK(!is_optimized_);
 }
 
@@ -109,10 +119,10 @@
     Handle<String> name(scope_info->ParameterName(i));
     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
 
-    Handle<Object> value(i < GetParametersCount()
-                             ? GetParameter(i)
-                             : isolate_->heap()->undefined_value(),
-                         isolate_);
+    Handle<Object> value =
+        i < GetParametersCount()
+            ? GetParameter(i)
+            : Handle<Object>::cast(isolate_->factory()->undefined_value());
     DCHECK(!value->IsTheHole());
 
     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
@@ -122,8 +132,7 @@
   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
     if (scope_info->LocalIsSynthetic(i)) continue;
     Handle<String> name(scope_info->StackLocalName(i));
-    Handle<Object> value(GetExpression(scope_info->StackLocalIndex(i)),
-                         isolate_);
+    Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
     if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
 
     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
diff --git a/src/debug/debug-frames.h b/src/debug/debug-frames.h
index c0d20bb..c04fd2b 100644
--- a/src/debug/debug-frames.h
+++ b/src/debug/debug-frames.h
@@ -21,12 +21,12 @@
   ~FrameInspector();
 
   int GetParametersCount();
-  Object* GetFunction();
-  Object* GetParameter(int index);
-  Object* GetExpression(int index);
+  Handle<Object> GetFunction();
+  Handle<Object> GetParameter(int index);
+  Handle<Object> GetExpression(int index);
   int GetSourcePosition();
   bool IsConstructor();
-  Object* GetContext();
+  Handle<Object> GetContext();
 
   JavaScriptFrame* GetArgumentsFrame() { return frame_; }
   void SetArgumentsFrame(JavaScriptFrame* frame);
@@ -48,6 +48,7 @@
   DeoptimizedFrameInfo* deoptimized_frame_;
   Isolate* isolate_;
   bool is_optimized_;
+  bool is_interpreted_;
   bool is_bottommost_;
   bool has_adapted_arguments_;
 
diff --git a/src/debug/debug-scopes.cc b/src/debug/debug-scopes.cc
index 15a0594..e785384 100644
--- a/src/debug/debug-scopes.cc
+++ b/src/debug/debug-scopes.cc
@@ -28,7 +28,7 @@
     return;
   }
 
-  context_ = Handle<Context>(Context::cast(frame_inspector->GetContext()));
+  context_ = Handle<Context>::cast(frame_inspector->GetContext());
 
   // Catch the case when the debugger stops in an internal function.
   Handle<JSFunction> function = GetFunction();
@@ -58,12 +58,8 @@
     // return, which requires a debug info to be available.
     Handle<DebugInfo> debug_info(shared_info->GetDebugInfo());
 
-    // PC points to the instruction after the current one, possibly a break
-    // location as well. So the "- 1" to exclude it from the search.
-    Address call_pc = GetFrame()->pc() - 1;
-
     // Find the break point where execution has stopped.
-    BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
+    BreakLocation location = BreakLocation::FromFrame(debug_info, GetFrame());
 
     ignore_nested_scopes = location.IsReturn();
   }
@@ -462,7 +458,8 @@
       isolate_->factory()->NewJSObject(isolate_->object_function());
   frame_inspector_->MaterializeStackLocals(local_scope, function);
 
-  Handle<Context> frame_context(Context::cast(frame_inspector_->GetContext()));
+  Handle<Context> frame_context =
+      Handle<Context>::cast(frame_inspector_->GetContext());
 
   HandleScope scope(isolate_);
   Handle<SharedFunctionInfo> shared(function->shared());
@@ -471,7 +468,7 @@
   if (!scope_info->HasContext()) return local_scope;
 
   // Third fill all context locals.
-  Handle<Context> function_context(frame_context->declaration_context());
+  Handle<Context> function_context(frame_context->closure_context());
   CopyContextLocalsToScopeObject(scope_info, function_context, local_scope);
 
   // Finally copy any properties from the function context extension.
@@ -480,8 +477,8 @@
       function_context->has_extension() &&
       !function_context->IsNativeContext()) {
     bool success = CopyContextExtensionToScopeObject(
-        handle(function_context->extension_object(), isolate_),
-        local_scope, JSReceiver::INCLUDE_PROTOS);
+        handle(function_context->extension_object(), isolate_), local_scope,
+        INCLUDE_PROTOS);
     if (!success) return MaybeHandle<JSObject>();
   }
 
@@ -510,8 +507,7 @@
   // be variables introduced by eval.
   if (context->has_extension()) {
     bool success = CopyContextExtensionToScopeObject(
-        handle(context->extension_object(), isolate_), closure_scope,
-        JSReceiver::OWN_ONLY);
+        handle(context->extension_object(), isolate_), closure_scope, OWN_ONLY);
     DCHECK(success);
     USE(success);
   }
@@ -559,8 +555,7 @@
     // Fill all extension variables.
     if (context->extension_object() != nullptr) {
       bool success = CopyContextExtensionToScopeObject(
-          handle(context->extension_object()), block_scope,
-          JSReceiver::OWN_ONLY);
+          handle(context->extension_object()), block_scope, OWN_ONLY);
       DCHECK(success);
       USE(success);
     }
@@ -798,10 +793,9 @@
   }
 }
 
-
 bool ScopeIterator::CopyContextExtensionToScopeObject(
     Handle<JSObject> extension, Handle<JSObject> scope_object,
-    JSReceiver::KeyCollectionType type) {
+    KeyCollectionType type) {
   Handle<FixedArray> keys;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
       isolate_, keys, JSReceiver::GetKeys(extension, type, ENUMERABLE_STRINGS),
diff --git a/src/debug/debug-scopes.h b/src/debug/debug-scopes.h
index d4e335a..fbdf632 100644
--- a/src/debug/debug-scopes.h
+++ b/src/debug/debug-scopes.h
@@ -96,8 +96,7 @@
   }
 
   inline Handle<JSFunction> GetFunction() {
-    return Handle<JSFunction>(
-        JSFunction::cast(frame_inspector_->GetFunction()));
+    return Handle<JSFunction>::cast(frame_inspector_->GetFunction());
   }
 
   static bool InternalizedStringMatch(void* key1, void* key2) {
@@ -139,7 +138,7 @@
                                       Handle<JSObject> scope_object);
   bool CopyContextExtensionToScopeObject(Handle<JSObject> extension,
                                          Handle<JSObject> scope_object,
-                                         JSReceiver::KeyCollectionType type);
+                                         KeyCollectionType type);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
 };
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index bd45b71..93c914c 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -16,6 +16,8 @@
 #include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
 #include "src/global-handles.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
 #include "src/isolate-inl.h"
 #include "src/list.h"
 #include "src/log.h"
@@ -58,29 +60,39 @@
   return v8::Utils::ToLocal(native_context);
 }
 
-
-BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
-                             int position, int statement_position)
+BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
+                             int code_offset, int position,
+                             int statement_position)
     : debug_info_(debug_info),
-      pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
-      rmode_(rinfo->rmode()),
-      data_(rinfo->data()),
+      code_offset_(code_offset),
+      type_(type),
       position_(position),
       statement_position_(statement_position) {}
 
+BreakLocation::Iterator* BreakLocation::GetIterator(
+    Handle<DebugInfo> debug_info, BreakLocatorType type) {
+  if (debug_info->abstract_code()->IsBytecodeArray()) {
+    return new BytecodeArrayIterator(debug_info, type);
+  } else {
+    return new CodeIterator(debug_info, type);
+  }
+}
 
-BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
-                                  BreakLocatorType type)
+BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
     : debug_info_(debug_info),
-      reloc_iterator_(debug_info->code(), GetModeMask(type)),
       break_index_(-1),
       position_(1),
-      statement_position_(1) {
+      statement_position_(1) {}
+
+BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
+                                          BreakLocatorType type)
+    : Iterator(debug_info),
+      reloc_iterator_(debug_info->abstract_code()->GetCode(),
+                      GetModeMask(type)) {
   if (!Done()) Next();
 }
 
-
-int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
+int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
   int mask = 0;
   mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
   mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
@@ -93,13 +105,11 @@
   return mask;
 }
 
-
-void BreakLocation::Iterator::Next() {
+void BreakLocation::CodeIterator::Next() {
   DisallowHeapAllocation no_gc;
   DCHECK(!Done());
 
-  // Iterate through reloc info for code and original code stopping at each
-  // breakable code target.
+  // Iterate through reloc info stopping at each breakable code target.
   bool first = break_index_ == -1;
   while (!Done()) {
     if (!first) reloc_iterator_.next();
@@ -141,43 +151,154 @@
   break_index_++;
 }
 
-
-// Find the break point at the supplied address, or the closest one before
-// the address.
-BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
-                                         Address pc) {
-  Iterator it(debug_info, ALL_BREAK_LOCATIONS);
-  it.SkipTo(BreakIndexFromAddress(debug_info, pc));
-  return it.GetBreakLocation();
+BreakLocation BreakLocation::CodeIterator::GetBreakLocation() {
+  DebugBreakType type;
+  if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
+    type = DEBUG_BREAK_SLOT_AT_RETURN;
+  } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
+    type = DEBUG_BREAK_SLOT_AT_CALL;
+  } else if (RelocInfo::IsDebuggerStatement(rmode())) {
+    type = DEBUGGER_STATEMENT;
+  } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
+    type = DEBUG_BREAK_SLOT;
+  } else {
+    type = NOT_DEBUG_BREAK;
+  }
+  return BreakLocation(debug_info_, type, code_offset(), position(),
+                       statement_position());
 }
 
+BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
+    Handle<DebugInfo> debug_info, BreakLocatorType type)
+    : Iterator(debug_info),
+      source_position_iterator_(
+          debug_info->abstract_code()->GetBytecodeArray()),
+      break_locator_type_(type),
+      start_position_(debug_info->shared()->start_position()) {
+  if (!Done()) Next();
+}
+
+void BreakLocation::BytecodeArrayIterator::Next() {
+  DisallowHeapAllocation no_gc;
+  DCHECK(!Done());
+  bool first = break_index_ == -1;
+  while (!Done()) {
+    if (!first) source_position_iterator_.Advance();
+    first = false;
+    if (Done()) return;
+    position_ = source_position_iterator_.source_position() - start_position_;
+    if (source_position_iterator_.is_statement()) {
+      statement_position_ = position_;
+    }
+    DCHECK(position_ >= 0);
+    DCHECK(statement_position_ >= 0);
+    break_index_++;
+
+    enum DebugBreakType type = GetDebugBreakType();
+    if (type == NOT_DEBUG_BREAK) continue;
+
+    if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
+
+    DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
+    if (type == DEBUG_BREAK_SLOT_AT_CALL ||
+        type == DEBUG_BREAK_SLOT_AT_RETURN) {
+      break;
+    }
+  }
+}
+
+BreakLocation::DebugBreakType
+BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
+  BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
+  interpreter::Bytecode bytecode =
+      interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
+
+  if (bytecode == interpreter::Bytecode::kDebugger) {
+    return DEBUGGER_STATEMENT;
+  } else if (bytecode == interpreter::Bytecode::kReturn) {
+    return DEBUG_BREAK_SLOT_AT_RETURN;
+  } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) {
+    return DEBUG_BREAK_SLOT_AT_CALL;
+  } else if (source_position_iterator_.is_statement()) {
+    return DEBUG_BREAK_SLOT;
+  } else {
+    return NOT_DEBUG_BREAK;
+  }
+}
+
+BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
+  return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(),
+                       position(), statement_position());
+}
 
 // Find the break point at the supplied address, or the closest one before
 // the address.
-void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
-                                             Address pc,
-                                             List<BreakLocation>* result_out) {
-  int break_index = BreakIndexFromAddress(debug_info, pc);
-  Iterator it(debug_info, ALL_BREAK_LOCATIONS);
-  it.SkipTo(break_index);
-  int statement_position = it.statement_position();
-  while (!it.Done() && it.statement_position() == statement_position) {
-    result_out->Add(it.GetBreakLocation());
-    it.Next();
+BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
+                                            int offset) {
+  base::SmartPointer<Iterator> it(GetIterator(debug_info));
+  it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
+  return it->GetBreakLocation();
+}
+
+FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
+  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+  frame->Summarize(&frames);
+  return frames.first();
+}
+
+int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
+  // Code offset points to the instruction after the call. Subtract 1 to
+  // exclude that instruction from the search. For bytecode, the code offset
+  // still points to the call.
+  return is_interpreted ? code_offset : code_offset - 1;
+}
+
+BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
+                                       JavaScriptFrame* frame) {
+  FrameSummary summary = GetFirstFrameSummary(frame);
+  int call_offset =
+      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
+  return FromCodeOffset(debug_info, call_offset);
+}
+
+// Find the break point at the supplied address, or the closest one before
+// the address.
+void BreakLocation::FromCodeOffsetSameStatement(
+    Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) {
+  int break_index = BreakIndexFromCodeOffset(debug_info, offset);
+  base::SmartPointer<Iterator> it(GetIterator(debug_info));
+  it->SkipTo(break_index);
+  int statement_position = it->statement_position();
+  while (!it->Done() && it->statement_position() == statement_position) {
+    result_out->Add(it->GetBreakLocation());
+    it->Next();
   }
 }
 
 
-int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
-                                         Address pc) {
+void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info,
+                                            int statement_position,
+                                            List<BreakLocation>* result_out) {
+  for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
+       it->Next()) {
+    if (it->statement_position() == statement_position) {
+      result_out->Add(it->GetBreakLocation());
+    }
+  }
+}
+
+int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
+                                            int offset) {
   // Run through all break points to locate the one closest to the address.
   int closest_break = 0;
   int distance = kMaxInt;
-  for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) {
+  DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
+  for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
+       it->Next()) {
     // Check if this break point is closer that what was previously found.
-    if (it.pc() <= pc && pc - it.pc() < distance) {
-      closest_break = it.break_index();
-      distance = static_cast<int>(pc - it.pc());
+    if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
+      closest_break = it->break_index();
+      distance = offset - it->code_offset();
       // Check whether we can't get any closer.
       if (distance == 0) break;
     }
@@ -191,28 +312,26 @@
                                           BreakPositionAlignment alignment) {
   // Run through all break points to locate the one closest to the source
   // position.
-  int closest_break = 0;
   int distance = kMaxInt;
-
-  for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) {
+  base::SmartPointer<Iterator> it(GetIterator(debug_info));
+  BreakLocation closest_break = it->GetBreakLocation();
+  while (!it->Done()) {
     int next_position;
     if (alignment == STATEMENT_ALIGNED) {
-      next_position = it.statement_position();
+      next_position = it->statement_position();
     } else {
       DCHECK(alignment == BREAK_POSITION_ALIGNED);
-      next_position = it.position();
+      next_position = it->position();
     }
     if (position <= next_position && next_position - position < distance) {
-      closest_break = it.break_index();
+      closest_break = it->GetBreakLocation();
       distance = next_position - position;
       // Check whether we can't get any closer.
       if (distance == 0) break;
     }
+    it->Next();
   }
-
-  Iterator it(debug_info, ALL_BREAK_LOCATIONS);
-  it.SkipTo(closest_break);
-  return it.GetBreakLocation();
+  return closest_break;
 }
 
 
@@ -222,14 +341,14 @@
   if (!HasBreakPoint()) SetDebugBreak();
   DCHECK(IsDebugBreak() || IsDebuggerStatement());
   // Set the break point information.
-  DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
+  DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_,
                            statement_position_, break_point_object);
 }
 
 
 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
   // Clear the break point information.
-  DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
+  DebugInfo::ClearBreakPoint(debug_info_, code_offset_, break_point_object);
   // If there are no more break points here remove the debug break.
   if (!HasBreakPoint()) {
     ClearDebugBreak();
@@ -280,11 +399,23 @@
   if (IsDebugBreak()) return;
 
   DCHECK(IsDebugBreakSlot());
-  Isolate* isolate = debug_info_->GetIsolate();
-  Builtins* builtins = isolate->builtins();
-  Handle<Code> target =
-      IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
-  DebugCodegen::PatchDebugBreakSlot(isolate, pc(), target);
+  if (abstract_code()->IsCode()) {
+    Code* code = abstract_code()->GetCode();
+    DCHECK(code->kind() == Code::FUNCTION);
+    Builtins* builtins = isolate()->builtins();
+    Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
+                                     : builtins->Slot_DebugBreak();
+    Address pc = code->instruction_start() + code_offset();
+    DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
+  } else {
+    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
+    interpreter::Bytecode bytecode =
+        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
+    interpreter::Bytecode debugbreak =
+        interpreter::Bytecodes::GetDebugBreak(bytecode);
+    bytecode_array->set(code_offset(),
+                        interpreter::Bytecodes::ToByte(debugbreak));
+  }
   DCHECK(IsDebugBreak());
 }
 
@@ -294,7 +425,16 @@
   if (IsDebuggerStatement()) return;
 
   DCHECK(IsDebugBreakSlot());
-  DebugCodegen::ClearDebugBreakSlot(debug_info_->GetIsolate(), pc());
+  if (abstract_code()->IsCode()) {
+    Code* code = abstract_code()->GetCode();
+    DCHECK(code->kind() == Code::FUNCTION);
+    Address pc = code->instruction_start() + code_offset();
+    DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
+  } else {
+    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
+    BytecodeArray* original = debug_info_->original_bytecode_array();
+    bytecode_array->set(code_offset(), original->get(code_offset()));
+  }
   DCHECK(!IsDebugBreak());
 }
 
@@ -302,15 +442,24 @@
 bool BreakLocation::IsDebugBreak() const {
   if (IsDebuggerStatement()) return false;
   DCHECK(IsDebugBreakSlot());
-  return rinfo().IsPatchedDebugBreakSlotSequence();
+  if (abstract_code()->IsCode()) {
+    Code* code = abstract_code()->GetCode();
+    DCHECK(code->kind() == Code::FUNCTION);
+    Address pc = code->instruction_start() + code_offset();
+    return DebugCodegen::DebugBreakSlotIsPatched(pc);
+  } else {
+    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
+    interpreter::Bytecode bytecode =
+        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
+    return interpreter::Bytecodes::IsDebugBreak(bytecode);
+  }
 }
 
 
 Handle<Object> BreakLocation::BreakPointObjects() const {
-  return debug_info_->GetBreakPointObjects(pc_offset_);
+  return debug_info_->GetBreakPointObjects(code_offset_);
 }
 
-
 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
   uint32_t mask = 1 << feature;
   // Only count one sample per feature and isolate.
@@ -444,22 +593,16 @@
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
 
   // Find the break location where execution has stopped.
-  // PC points to the instruction after the current one, possibly a break
-  // location as well. So the "- 1" to exclude it from the search.
-  Address call_pc = frame->pc() - 1;
-  BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
+  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
 
   // Find actual break points, if any, and trigger debug break event.
-  if (break_points_active_ && location.HasBreakPoint()) {
-    Handle<Object> break_point_objects = location.BreakPointObjects();
-    Handle<Object> break_points_hit = CheckBreakPoints(break_point_objects);
-    if (!break_points_hit->IsUndefined()) {
-      // Clear all current stepping setup.
-      ClearStepping();
-      // Notify the debug event listeners.
-      OnDebugBreak(break_points_hit, false);
-      return;
-    }
+  Handle<Object> break_points_hit = CheckBreakPoints(&location);
+  if (!break_points_hit->IsUndefined()) {
+    // Clear all current stepping setup.
+    ClearStepping();
+    // Notify the debug event listeners.
+    OnDebugBreak(break_points_hit, false);
+    return;
   }
 
   // No break point. Check for stepping.
@@ -480,11 +623,14 @@
       // Step next should not break in a deeper frame.
       if (current_fp < target_fp) return;
     // Fall through.
-    case StepIn:
+    case StepIn: {
+      FrameSummary summary = GetFirstFrameSummary(frame);
+      int offset = summary.code_offset();
       step_break = location.IsReturn() || (current_fp != last_fp) ||
                    (thread_local_.last_statement_position_ !=
-                    location.code()->SourceStatementPosition(frame->pc()));
+                    location.abstract_code()->SourceStatementPosition(offset));
       break;
+    }
     case StepFrame:
       step_break = current_fp != last_fp;
       break;
@@ -503,12 +649,17 @@
 }
 
 
-// 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) {
+// Find break point objects for this location, if any, and evaluate them.
+// Return an array of break point objects that evaluated true.
+Handle<Object> Debug::CheckBreakPoints(BreakLocation* location,
+                                       bool* has_break_points) {
   Factory* factory = isolate_->factory();
+  bool has_break_points_to_check =
+      break_points_active_ && location->HasBreakPoint();
+  if (has_break_points) *has_break_points = has_break_points_to_check;
+  if (!has_break_points_to_check) return factory->undefined_value();
 
+  Handle<Object> break_point_objects = location->BreakPointObjects();
   // Count the number of break points hit. If there are multiple break points
   // they are in a FixedArray.
   Handle<FixedArray> break_points_hit;
@@ -518,9 +669,9 @@
     Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
     break_points_hit = factory->NewFixedArray(array->length());
     for (int i = 0; i < array->length(); i++) {
-      Handle<Object> o(array->get(i), isolate_);
-      if (CheckBreakPoint(o)) {
-        break_points_hit->set(break_points_hit_count++, *o);
+      Handle<Object> break_point_object(array->get(i), isolate_);
+      if (CheckBreakPoint(break_point_object)) {
+        break_points_hit->set(break_points_hit_count++, *break_point_object);
       }
     }
   } else {
@@ -529,25 +680,51 @@
       break_points_hit->set(break_points_hit_count++, *break_point_objects);
     }
   }
-
-  // Return undefined if no break points were triggered.
-  if (break_points_hit_count == 0) {
-    return factory->undefined_value();
-  }
-  // Return break points hit as a JSArray.
+  if (break_points_hit_count == 0) return factory->undefined_value();
   Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
   result->set_length(Smi::FromInt(break_points_hit_count));
   return result;
 }
 
 
+bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
+  // A break location is considered muted if break locations on the current
+  // statement have at least one break point, and all of these break points
+  // evaluate to false. Aside from not triggering a debug break event at the
+  // break location, we also do not trigger one for debugger statements, nor
+  // an exception event on exception at this location.
+  Object* fun = frame->function();
+  if (!fun->IsJSFunction()) return false;
+  JSFunction* function = JSFunction::cast(fun);
+  if (!function->shared()->HasDebugInfo()) return false;
+  HandleScope scope(isolate_);
+  Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
+  // Enter the debugger.
+  DebugScope debug_scope(this);
+  if (debug_scope.failed()) return false;
+  BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
+  List<BreakLocation> break_locations;
+  BreakLocation::AllForStatementPosition(
+      debug_info, current_position.statement_position(), &break_locations);
+  bool has_break_points_at_all = false;
+  for (int i = 0; i < break_locations.length(); i++) {
+    bool has_break_points;
+    Handle<Object> check_result =
+        CheckBreakPoints(&break_locations[i], &has_break_points);
+    has_break_points_at_all |= has_break_points;
+    if (has_break_points && !check_result->IsUndefined()) return false;
+  }
+  return has_break_points_at_all;
+}
+
+
 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
                                         Handle<Object> args[]) {
   PostponeInterruptsScope no_interrupts(isolate_);
   AssertDebugContext();
   Handle<Object> holder = isolate_->natives_utils_object();
   Handle<JSFunction> fun = Handle<JSFunction>::cast(
-      Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked());
+      Object::GetProperty(isolate_, holder, name).ToHandleChecked());
   Handle<Object> undefined = isolate_->factory()->undefined_value();
   return Execution::TryCall(isolate_, fun, undefined, argc, args);
 }
@@ -668,11 +845,8 @@
           Handle<BreakPointInfo>::cast(result);
       Handle<DebugInfo> debug_info = node->debug_info();
 
-      // Find the break point and clear it.
-      Address pc =
-          debug_info->code()->entry() + break_point_info->code_position();
-
-      BreakLocation location = BreakLocation::FromAddress(debug_info, pc);
+      BreakLocation location = BreakLocation::FromCodeOffset(
+          debug_info, break_point_info->code_offset());
       location.ClearBreakPoint(break_point_object);
 
       // If there are no more break points left remove the debug info for this
@@ -694,9 +868,10 @@
 void Debug::ClearAllBreakPoints() {
   for (DebugInfoListNode* node = debug_info_list_; node != NULL;
        node = node->next()) {
-    for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
-         !it.Done(); it.Next()) {
-      it.GetBreakLocation().ClearDebugBreak();
+    for (base::SmartPointer<BreakLocation::Iterator> it(
+             BreakLocation::GetIterator(node->debug_info()));
+         !it->Done(); it->Next()) {
+      it->GetBreakLocation().ClearDebugBreak();
     }
   }
   // Remove all debug info.
@@ -727,8 +902,10 @@
 
   // Flood the function with break points.
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
-  for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) {
-    it.GetBreakLocation().SetOneShot();
+  for (base::SmartPointer<BreakLocation::Iterator> it(
+           BreakLocation::GetIterator(debug_info, type));
+       !it->Done(); it->Next()) {
+    it->GetBreakLocation().SetOneShot();
   }
 }
 
@@ -751,13 +928,6 @@
 }
 
 
-FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
-  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
-  frame->Summarize(&frames);
-  return frames.first();
-}
-
-
 void Debug::PrepareStepIn(Handle<JSFunction> function) {
   if (!is_active()) return;
   if (last_step_action() < StepIn) return;
@@ -779,8 +949,7 @@
   JavaScriptFrameIterator it(isolate_);
   while (!it.done()) {
     JavaScriptFrame* frame = it.frame();
-    int stack_slots = 0;  // The computed stack slot count is not used.
-    if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) break;
+    if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
     it.Advance();
   }
 
@@ -843,18 +1012,21 @@
 
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
   // Refresh frame summary if the code has been recompiled for debugging.
-  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
+  if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
+    summary = GetFirstFrameSummary(frame);
+  }
 
-  // PC points to the instruction after the current one, possibly a break
-  // location as well. So the "- 1" to exclude it from the search.
-  Address call_pc = summary.pc() - 1;
-  BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc);
+  int call_offset =
+      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
+  BreakLocation location =
+      BreakLocation::FromCodeOffset(debug_info, call_offset);
 
   // At a return statement we will step out either way.
   if (location.IsReturn()) step_action = StepOut;
 
   thread_local_.last_statement_position_ =
-      debug_info->code()->SourceStatementPosition(summary.pc());
+      debug_info->abstract_code()->SourceStatementPosition(
+          summary.code_offset());
   thread_local_.last_fp_ = frame->UnpaddedFP();
 
   switch (step_action) {
@@ -961,9 +1133,10 @@
   // removed from the list.
   for (DebugInfoListNode* node = debug_info_list_; node != NULL;
        node = node->next()) {
-    for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
-         !it.Done(); it.Next()) {
-      it.GetBreakLocation().ClearOneShot();
+    for (base::SmartPointer<BreakLocation::Iterator> it(
+             BreakLocation::GetIterator(node->debug_info()));
+         !it->Done(); it->Next()) {
+      it->GetBreakLocation().ClearOneShot();
     }
   }
 }
@@ -1070,6 +1243,15 @@
       if (frame->is_optimized()) continue;
       if (!function->Inlines(shared_)) continue;
 
+      if (frame->is_interpreted()) {
+        InterpretedFrame* interpreted_frame =
+            reinterpret_cast<InterpretedFrame*>(frame);
+        BytecodeArray* debug_copy =
+            shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray();
+        interpreted_frame->PatchBytecodeArray(debug_copy);
+        continue;
+      }
+
       Code* frame_code = frame->LookupCode();
       DCHECK(frame_code->kind() == Code::FUNCTION);
       if (frame_code->has_debug_break_slots()) continue;
@@ -1127,11 +1309,15 @@
   // Make sure we abort incremental marking.
   isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                                       "prepare for break points");
+  bool is_interpreted = shared->HasBytecodeArray();
 
   {
+    // TODO(yangguo): with bytecode, we still walk the heap to find all
+    // optimized code for the function to deoptimize. We can probably be
+    // smarter here and avoid the heap walk.
     HeapIterator iterator(isolate_->heap());
     HeapObject* obj;
-    bool include_generators = shared->is_generator();
+    bool include_generators = !is_interpreted && shared->is_generator();
 
     while ((obj = iterator.next())) {
       if (obj->IsJSFunction()) {
@@ -1140,6 +1326,7 @@
         if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
           Deoptimizer::DeoptimizeFunction(function);
         }
+        if (is_interpreted) continue;
         if (function->shared() == *shared) functions.Add(handle(function));
       } else if (include_generators && obj->IsJSGeneratorObject()) {
         JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
@@ -1155,7 +1342,12 @@
     }
   }
 
-  if (!shared->HasDebugCode()) {
+  // We do not need to replace code to debug bytecode.
+  DCHECK(!is_interpreted || functions.length() == 0);
+  DCHECK(!is_interpreted || suspended_generators.length() == 0);
+
+  // We do not need to recompile to debug bytecode.
+  if (!is_interpreted && !shared->HasDebugCode()) {
     DCHECK(functions.length() > 0);
     if (!Compiler::CompileDebugCode(functions.first())) return false;
   }
@@ -1326,10 +1518,16 @@
     return false;
   }
 
-  if (!PrepareFunctionForBreakPoints(shared)) return false;
-
-  CreateDebugInfo(shared);
-
+  if (shared->HasBytecodeArray()) {
+    // To prepare bytecode for debugging, we already need to have the debug
+    // info (containing the debug copy) upfront, but since we do not recompile,
+    // preparing for break points cannot fail.
+    CreateDebugInfo(shared);
+    CHECK(PrepareFunctionForBreakPoints(shared));
+  } else {
+    if (!PrepareFunctionForBreakPoints(shared)) return false;
+    CreateDebugInfo(shared);
+  }
   return true;
 }
 
@@ -1363,7 +1561,7 @@
         prev->set_next(current->next());
       }
       delete current;
-      shared->set_debug_info(isolate_->heap()->undefined_value());
+      shared->set_debug_info(DebugInfo::uninitialized());
       return;
     }
     // Move to next in list.
@@ -1374,14 +1572,25 @@
   UNREACHABLE();
 }
 
-
-void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
-  after_break_target_ = NULL;
-
-  if (LiveEdit::SetAfterBreakTarget(this)) return;  // LiveEdit did the job.
-
-  // Continue just after the slot.
-  after_break_target_ = frame->pc();
+Object* Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
+  if (frame->is_interpreted()) {
+    // Find the handler from the original bytecode array.
+    InterpretedFrame* interpreted_frame =
+        reinterpret_cast<InterpretedFrame*>(frame);
+    SharedFunctionInfo* shared = interpreted_frame->function()->shared();
+    BytecodeArray* bytecode_array = shared->bytecode_array();
+    int bytecode_offset = interpreted_frame->GetBytecodeOffset();
+    interpreter::Bytecode bytecode =
+        interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
+    return isolate_->interpreter()->GetBytecodeHandler(bytecode);
+  } else {
+    after_break_target_ = NULL;
+    if (!LiveEdit::SetAfterBreakTarget(this)) {
+      // Continue just after the slot.
+      after_break_target_ = frame->pc();
+    }
+    return isolate_->heap()->undefined_value();
+  }
 }
 
 
@@ -1394,21 +1603,14 @@
 
   // With no debug info there are no break points, so we can't be at a return.
   if (!shared->HasDebugInfo()) return false;
-  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
-  Handle<Code> code(debug_info->code());
-#ifdef DEBUG
-  // Get the code which is actually executing.
-  Handle<Code> frame_code(frame->LookupCode());
-  DCHECK(frame_code.is_identical_to(code));
-#endif
 
-  // Find the reloc info matching the start of the debug break slot.
-  Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
-  int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
-  for (RelocIterator it(*code, mask); !it.done(); it.next()) {
-    if (it.rinfo()->pc() == slot_pc) return true;
-  }
-  return false;
+  DCHECK(!frame->is_optimized());
+  FrameSummary summary = GetFirstFrameSummary(frame);
+
+  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
+  BreakLocation location =
+      BreakLocation::FromCodeOffset(debug_info, summary.code_offset());
+  return location.IsReturn();
 }
 
 
@@ -1466,16 +1668,18 @@
 
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
   // Refresh frame summary if the code has been recompiled for debugging.
-  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame);
+  if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
+    summary = GetFirstFrameSummary(frame);
+  }
 
-  // Find range of break points starting from the break point where execution
-  // has stopped.
-  Address call_pc = summary.pc() - 1;
+  int call_offset =
+      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
   List<BreakLocation> locations;
-  BreakLocation::FromAddressSameStatement(debug_info, call_pc, &locations);
+  BreakLocation::FromCodeOffsetSameStatement(debug_info, call_offset,
+                                             &locations);
 
   for (BreakLocation location : locations) {
-    if (location.pc() <= summary.pc()) {
+    if (location.code_offset() <= summary.code_offset()) {
       // The break point is near our pc. Could be a step-in possibility,
       // that is currently taken by active debugger call.
       if (break_frame_id() == StackFrame::NO_ID) {
@@ -1619,6 +1823,12 @@
     if (!break_on_exception_) return;
   }
 
+  {
+    // Check whether the break location is muted.
+    JavaScriptFrameIterator it(isolate_);
+    if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return;
+  }
+
   DebugScope debug_scope(this);
   if (debug_scope.failed()) return;
 
@@ -1636,8 +1846,7 @@
 }
 
 
-void Debug::OnDebugBreak(Handle<Object> break_points_hit,
-                            bool auto_continue) {
+void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
   // The caller provided for DebugScope.
   AssertDebugContext();
   // Bail out if there is no listener for this event
@@ -2071,6 +2280,8 @@
           JSFunction::cast(fun)->context()->global_object();
       // Don't stop in debugger functions.
       if (IsDebugGlobal(global)) return;
+      // Don't stop if the break location is muted.
+      if (IsMutedAtCurrentLocation(it.frame())) return;
     }
   }
 
diff --git a/src/debug/debug.h b/src/debug/debug.h
index 7dcc2b5..81db9e5 100644
--- a/src/debug/debug.h
+++ b/src/debug/debug.h
@@ -16,6 +16,7 @@
 #include "src/flags.h"
 #include "src/frames.h"
 #include "src/hashmap.h"
+#include "src/interpreter/source-position-table.h"
 #include "src/runtime/runtime.h"
 #include "src/string-stream.h"
 #include "src/v8threads.h"
@@ -64,24 +65,32 @@
  public:
   // Find the break point at the supplied address, or the closest one before
   // the address.
-  static BreakLocation FromAddress(Handle<DebugInfo> debug_info, Address pc);
+  static BreakLocation FromCodeOffset(Handle<DebugInfo> debug_info, int offset);
 
-  static void FromAddressSameStatement(Handle<DebugInfo> debug_info, Address pc,
-                                       List<BreakLocation>* result_out);
+  static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
+                                 JavaScriptFrame* frame);
+
+  static void FromCodeOffsetSameStatement(Handle<DebugInfo> debug_info,
+                                          int offset,
+                                          List<BreakLocation>* result_out);
+
+  static void AllForStatementPosition(Handle<DebugInfo> debug_info,
+                                      int statement_position,
+                                      List<BreakLocation>* result_out);
 
   static BreakLocation FromPosition(Handle<DebugInfo> debug_info, int position,
                                     BreakPositionAlignment alignment);
 
   bool IsDebugBreak() const;
 
-  inline bool IsReturn() const {
-    return RelocInfo::IsDebugBreakSlotAtReturn(rmode_);
-  }
-  inline bool IsCall() const {
-    return RelocInfo::IsDebugBreakSlotAtCall(rmode_);
+  inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
+  inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
+  inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
+  inline bool IsDebuggerStatement() const {
+    return type_ == DEBUGGER_STATEMENT;
   }
   inline bool HasBreakPoint() const {
-    return debug_info_->HasBreakPoint(pc_offset_);
+    return debug_info_->HasBreakPoint(code_offset_);
   }
 
   Handle<Object> BreakPointObjects() const;
@@ -92,79 +101,118 @@
   void SetOneShot();
   void ClearOneShot();
 
-
-  inline RelocInfo rinfo() const {
-    return RelocInfo(debug_info_->GetIsolate(), pc(), rmode(), data_, code());
-  }
-
   inline int position() const { return position_; }
   inline int statement_position() const { return statement_position_; }
 
-  inline Address pc() const { return code()->entry() + pc_offset_; }
+  inline int code_offset() const { return code_offset_; }
+  inline Isolate* isolate() { return debug_info_->GetIsolate(); }
 
-  inline RelocInfo::Mode rmode() const { return rmode_; }
+  inline AbstractCode* abstract_code() const {
+    return debug_info_->abstract_code();
+  }
 
-  inline Code* code() const { return debug_info_->code(); }
+ protected:
+  enum DebugBreakType {
+    NOT_DEBUG_BREAK,
+    DEBUGGER_STATEMENT,
+    DEBUG_BREAK_SLOT,
+    DEBUG_BREAK_SLOT_AT_CALL,
+    DEBUG_BREAK_SLOT_AT_RETURN
+  };
 
- private:
-  BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, int position,
-                int statement_position);
+  BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
+                int code_offset, int position, int statement_position);
 
   class Iterator {
    public:
-    Iterator(Handle<DebugInfo> debug_info, BreakLocatorType type);
+    virtual ~Iterator() {}
 
-    BreakLocation GetBreakLocation() {
-      return BreakLocation(debug_info_, rinfo(), position(),
-                           statement_position());
-    }
-
-    inline bool Done() const { return reloc_iterator_.done(); }
-    void Next();
+    virtual BreakLocation GetBreakLocation() = 0;
+    virtual bool Done() const = 0;
+    virtual void Next() = 0;
 
     void SkipTo(int count) {
       while (count-- > 0) Next();
     }
 
-    inline RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
-    inline RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
-    inline Address pc() { return rinfo()->pc(); }
+    virtual int code_offset() = 0;
     int break_index() const { return break_index_; }
     inline int position() const { return position_; }
     inline int statement_position() const { return statement_position_; }
 
-   private:
-    static int GetModeMask(BreakLocatorType type);
+   protected:
+    explicit Iterator(Handle<DebugInfo> debug_info);
 
     Handle<DebugInfo> debug_info_;
-    RelocIterator reloc_iterator_;
     int break_index_;
     int position_;
     int statement_position_;
 
+   private:
     DisallowHeapAllocation no_gc_;
-
     DISALLOW_COPY_AND_ASSIGN(Iterator);
   };
 
+  class CodeIterator : public Iterator {
+   public:
+    CodeIterator(Handle<DebugInfo> debug_info, BreakLocatorType type);
+    ~CodeIterator() override {}
+
+    BreakLocation GetBreakLocation() override;
+    bool Done() const override { return reloc_iterator_.done(); }
+    void Next() override;
+
+    int code_offset() override {
+      return static_cast<int>(
+          rinfo()->pc() -
+          debug_info_->abstract_code()->GetCode()->instruction_start());
+    }
+
+   private:
+    static int GetModeMask(BreakLocatorType type);
+    RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
+    RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
+
+    RelocIterator reloc_iterator_;
+    DISALLOW_COPY_AND_ASSIGN(CodeIterator);
+  };
+
+  class BytecodeArrayIterator : public Iterator {
+   public:
+    BytecodeArrayIterator(Handle<DebugInfo> debug_info, BreakLocatorType type);
+    ~BytecodeArrayIterator() override {}
+
+    BreakLocation GetBreakLocation() override;
+    bool Done() const override { return source_position_iterator_.done(); }
+    void Next() override;
+
+    int code_offset() override {
+      return source_position_iterator_.bytecode_offset();
+    }
+
+   private:
+    DebugBreakType GetDebugBreakType();
+
+    interpreter::SourcePositionTableIterator source_position_iterator_;
+    BreakLocatorType break_locator_type_;
+    int start_position_;
+    DISALLOW_COPY_AND_ASSIGN(BytecodeArrayIterator);
+  };
+
+  static Iterator* GetIterator(Handle<DebugInfo> debug_info,
+                               BreakLocatorType type = ALL_BREAK_LOCATIONS);
+
+ private:
   friend class Debug;
 
-  static int BreakIndexFromAddress(Handle<DebugInfo> debug_info, Address pc);
+  static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, int offset);
 
   void SetDebugBreak();
   void ClearDebugBreak();
 
-  inline bool IsDebuggerStatement() const {
-    return RelocInfo::IsDebuggerStatement(rmode_);
-  }
-  inline bool IsDebugBreakSlot() const {
-    return RelocInfo::IsDebugBreakSlot(rmode_);
-  }
-
   Handle<DebugInfo> debug_info_;
-  int pc_offset_;
-  RelocInfo::Mode rmode_;
-  intptr_t data_;
+  int code_offset_;
+  DebugBreakType type_;
   int position_;
   int statement_position_;
 };
@@ -383,7 +431,7 @@
   // Internal logic
   bool Load();
   void Break(Arguments args, JavaScriptFrame*);
-  void SetAfterBreakTarget(JavaScriptFrame* frame);
+  Object* SetAfterBreakTarget(JavaScriptFrame* frame);
 
   // Scripts handling.
   Handle<FixedArray> GetLoadedScripts();
@@ -555,7 +603,9 @@
   void ClearOneShot();
   void ActivateStepOut(StackFrame* frame);
   void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info);
-  Handle<Object> CheckBreakPoints(Handle<Object> break_point);
+  Handle<Object> CheckBreakPoints(BreakLocation* location,
+                                  bool* has_break_points = nullptr);
+  bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
   bool CheckBreakPoint(Handle<Object> break_point_object);
   MaybeHandle<Object> CallFunction(const char* name, int argc,
                                    Handle<Object> args[]);
@@ -739,6 +789,7 @@
 
   static void PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                   Handle<Code> code);
+  static bool DebugBreakSlotIsPatched(Address pc);
   static void ClearDebugBreakSlot(Isolate* isolate, Address pc);
 };
 
diff --git a/src/debug/debug.js b/src/debug/debug.js
index bc2c696..6849bf5 100644
--- a/src/debug/debug.js
+++ b/src/debug/debug.js
@@ -147,10 +147,8 @@
   } else {
     this.number_ = next_break_point_number++;
   }
-  this.hit_count_ = 0;
   this.active_ = true;
   this.condition_ = null;
-  this.ignoreCount_ = 0;
 }
 
 
@@ -169,11 +167,6 @@
 };
 
 
-BreakPoint.prototype.hit_count = function() {
-  return this.hit_count_;
-};
-
-
 BreakPoint.prototype.active = function() {
   if (this.script_break_point()) {
     return this.script_break_point().active();
@@ -190,11 +183,6 @@
 };
 
 
-BreakPoint.prototype.ignoreCount = function() {
-  return this.ignoreCount_;
-};
-
-
 BreakPoint.prototype.script_break_point = function() {
   return this.script_break_point_;
 };
@@ -215,11 +203,6 @@
 };
 
 
-BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
-  this.ignoreCount_ = ignoreCount;
-};
-
-
 BreakPoint.prototype.isTriggered = function(exec_state) {
   // Break point not active - not triggered.
   if (!this.active()) return false;
@@ -239,18 +222,6 @@
     }
   }
 
-  // Update the hit count.
-  this.hit_count_++;
-  if (this.script_break_point_) {
-    this.script_break_point_.hit_count_++;
-  }
-
-  // If the break point has an ignore count it is not triggered.
-  if (this.ignoreCount_ > 0) {
-    this.ignoreCount_--;
-    return false;
-  }
-
   // Break point triggered.
   return true;
 };
@@ -283,10 +254,8 @@
   this.groupId_ = opt_groupId;
   this.position_alignment_ = IS_UNDEFINED(opt_position_alignment)
       ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
-  this.hit_count_ = 0;
   this.active_ = true;
   this.condition_ = null;
-  this.ignoreCount_ = 0;
   this.break_points_ = [];
 }
 
@@ -299,10 +268,8 @@
   copy.number_ = next_break_point_number++;
   script_break_points.push(copy);
 
-  copy.hit_count_ = this.hit_count_;
   copy.active_ = this.active_;
   copy.condition_ = this.condition_;
-  copy.ignoreCount_ = this.ignoreCount_;
   return copy;
 };
 
@@ -362,11 +329,6 @@
 };
 
 
-ScriptBreakPoint.prototype.hit_count = function() {
-  return this.hit_count_;
-};
-
-
 ScriptBreakPoint.prototype.active = function() {
   return this.active_;
 };
@@ -377,11 +339,6 @@
 };
 
 
-ScriptBreakPoint.prototype.ignoreCount = function() {
-  return this.ignoreCount_;
-};
-
-
 ScriptBreakPoint.prototype.enable = function() {
   this.active_ = true;
 };
@@ -397,16 +354,6 @@
 };
 
 
-ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
-  this.ignoreCount_ = ignoreCount;
-
-  // Set ignore count on all break points created from this script break point.
-  for (var i = 0; i < this.break_points_.length; i++) {
-    this.break_points_[i].setIgnoreCount(ignoreCount);
-  }
-};
-
-
 // Check whether a script matches this script break point. Currently this is
 // only based on script name.
 ScriptBreakPoint.prototype.matchesScript = function(script) {
@@ -461,7 +408,6 @@
 
   // Create a break point object and set the break point.
   var break_point = MakeBreakPoint(position, this);
-  break_point.setIgnoreCount(this.ignoreCount());
   var actual_position = %SetScriptBreakPoint(script, position,
                                              this.position_alignment_,
                                              break_point);
@@ -726,13 +672,6 @@
 };
 
 
-Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
-  if (ignoreCount < 0) throw MakeError(kDebugger, 'Invalid argument');
-  var break_point = this.findBreakPoint(break_point_number, false);
-  break_point.setIgnoreCount(ignoreCount);
-};
-
-
 Debug.clearBreakPoint = function(break_point_number) {
   var break_point = this.findBreakPoint(break_point_number, true);
   if (break_point) {
@@ -857,14 +796,6 @@
 };
 
 
-Debug.changeScriptBreakPointIgnoreCount = function(
-    break_point_number, ignoreCount) {
-  if (ignoreCount < 0) throw MakeError(kDebugger, 'Invalid argument');
-  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
-  script_break_point.setIgnoreCount(ignoreCount);
-};
-
-
 Debug.scriptBreakPoints = function() {
   return script_break_points;
 };
@@ -1503,7 +1434,6 @@
   var enabled = IS_UNDEFINED(request.arguments.enabled) ?
       true : request.arguments.enabled;
   var condition = request.arguments.condition;
-  var ignoreCount = request.arguments.ignoreCount;
   var groupId = request.arguments.groupId;
 
   // Check for legal arguments.
@@ -1569,9 +1499,6 @@
 
   // Set additional break point properties.
   var break_point = Debug.findBreakPoint(break_point_number);
-  if (ignoreCount) {
-    Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
-  }
   if (!enabled) {
     Debug.disableBreakPoint(break_point_number);
   }
@@ -1617,7 +1544,6 @@
   var break_point = TO_NUMBER(request.arguments.breakpoint);
   var enabled = request.arguments.enabled;
   var condition = request.arguments.condition;
-  var ignoreCount = request.arguments.ignoreCount;
 
   // Check for legal arguments.
   if (!break_point) {
@@ -1638,11 +1564,6 @@
   if (!IS_UNDEFINED(condition)) {
     Debug.changeBreakPointCondition(break_point, condition);
   }
-
-  // Change ignore count if supplied
-  if (!IS_UNDEFINED(ignoreCount)) {
-    Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
-  }
 };
 
 
@@ -1717,10 +1638,8 @@
       line: break_point.line(),
       column: break_point.column(),
       groupId: break_point.groupId(),
-      hit_count: break_point.hit_count(),
       active: break_point.active(),
       condition: break_point.condition(),
-      ignoreCount: break_point.ignoreCount(),
       actual_locations: break_point.actual_locations()
     };
 
@@ -2396,7 +2315,7 @@
     frame_mirror = this.exec_state_.frame();
   }
 
-  var result_description = Debug.LiveEdit.RestartFrame(frame_mirror);
+  var result_description = frame_mirror.restart();
   response.body = {result: result_description};
 };
 
diff --git a/src/debug/ia32/debug-ia32.cc b/src/debug/ia32/debug-ia32.cc
index d489a01..95f2bc6 100644
--- a/src/debug/ia32/debug-ia32.cc
+++ b/src/debug/ia32/debug-ia32.cc
@@ -50,6 +50,9 @@
   DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  return !Assembler::IsNop(pc);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
index f1f3f23..91c990d 100644
--- a/src/debug/liveedit.cc
+++ b/src/debug/liveedit.cc
@@ -1857,8 +1857,8 @@
     HandleScope scope(isolate);
 
     for (int i = 0; i < len; i++) {
-      Handle<JSValue> jsvalue =
-          Handle<JSValue>::cast(FixedArray::get(shared_info_array, i));
+      Handle<JSValue> jsvalue = Handle<JSValue>::cast(
+          FixedArray::get(*shared_info_array, i, isolate));
       Handle<SharedFunctionInfo> shared =
           UnwrapSharedFunctionInfoFromJSValue(jsvalue);
 
diff --git a/src/debug/mips/debug-mips.cc b/src/debug/mips/debug-mips.cc
index c5c58d0..1d9f7d6 100644
--- a/src/debug/mips/debug-mips.cc
+++ b/src/debug/mips/debug-mips.cc
@@ -56,6 +56,10 @@
   patcher.masm()->Call(v8::internal::t9);
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  Instr current_instr = Assembler::instr_at(pc);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/mips64/debug-mips64.cc b/src/debug/mips64/debug-mips64.cc
index 1d65fd9..0646a24 100644
--- a/src/debug/mips64/debug-mips64.cc
+++ b/src/debug/mips64/debug-mips64.cc
@@ -58,6 +58,10 @@
   patcher.masm()->Call(v8::internal::t9);
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  Instr current_instr = Assembler::instr_at(pc);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/mirrors.js b/src/debug/mirrors.js
index 1fd5fa9..8b9dd02 100644
--- a/src/debug/mirrors.js
+++ b/src/debug/mirrors.js
@@ -812,7 +812,7 @@
     // Skip properties which are defined through accessors.
     var property = properties[i];
     if (property.propertyType() != PropertyType.AccessorConstant) {
-      if (%_ObjectEquals(property.value_, value.value_)) {
+      if (property.value_ === value.value_) {
         return property;
       }
     }
diff --git a/src/debug/ppc/debug-ppc.cc b/src/debug/ppc/debug-ppc.cc
index c5ddab8..aab5399 100644
--- a/src/debug/ppc/debug-ppc.cc
+++ b/src/debug/ppc/debug-ppc.cc
@@ -64,6 +64,10 @@
   patcher.masm()->bctrl();
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  Instr current_instr = Assembler::instr_at(pc);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/x64/debug-x64.cc b/src/debug/x64/debug-x64.cc
index 0d56ea7..f7fbe76 100644
--- a/src/debug/x64/debug-x64.cc
+++ b/src/debug/x64/debug-x64.cc
@@ -51,6 +51,9 @@
   DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  return !Assembler::IsNop(pc);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {
diff --git a/src/debug/x87/debug-x87.cc b/src/debug/x87/debug-x87.cc
index 8c04e02..8ddb82f 100644
--- a/src/debug/x87/debug-x87.cc
+++ b/src/debug/x87/debug-x87.cc
@@ -50,6 +50,9 @@
   DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 }
 
+bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
+  return !Assembler::IsNop(pc);
+}
 
 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
                                           DebugBreakCallHelperMode mode) {