| Index: src/debug/debug.cc
 | 
| diff --git a/src/debug/debug.cc b/src/debug/debug.cc
 | 
| index 733ea9b02dbb0c9c1dd362645abbd20941a0a401..22a8b49016132f07e9786a3f162d2f5b080cdfcc 100644
 | 
| --- a/src/debug/debug.cc
 | 
| +++ b/src/debug/debug.cc
 | 
| @@ -33,17 +33,6 @@
 | 
|  namespace v8 {
 | 
|  namespace internal {
 | 
|  
 | 
| -namespace {
 | 
| -
 | 
| -inline 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;
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
|  Debug::Debug(Isolate* isolate)
 | 
|      : debug_context_(Handle<Context>()),
 | 
|        event_listener_(Handle<Object>()),
 | 
| @@ -65,53 +54,135 @@ Debug::Debug(Isolate* isolate)
 | 
|    ThreadInit();
 | 
|  }
 | 
|  
 | 
| +BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
 | 
| +                                       JavaScriptFrame* frame) {
 | 
| +  FrameSummary summary = FrameSummary::GetFirst(frame);
 | 
| +  int offset = summary.code_offset();
 | 
| +  Handle<AbstractCode> abstract_code = summary.abstract_code();
 | 
| +  if (abstract_code->IsCode()) offset = offset - 1;
 | 
| +  auto it = BreakIterator::GetIterator(debug_info, abstract_code);
 | 
| +  it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
 | 
| +  return it->GetBreakLocation();
 | 
| +}
 | 
|  
 | 
| -static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
 | 
| -  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
 | 
| -  // Isolate::context() may have been NULL when "script collected" event
 | 
| -  // occured.
 | 
| -  if (context.is_null()) return v8::Local<v8::Context>();
 | 
| -  Handle<Context> native_context(context->native_context());
 | 
| -  return v8::Utils::ToLocal(native_context);
 | 
| +void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
 | 
| +                                          JavaScriptFrame* frame,
 | 
| +                                          List<BreakLocation>* result_out) {
 | 
| +  FrameSummary summary = FrameSummary::GetFirst(frame);
 | 
| +  int offset = summary.code_offset();
 | 
| +  Handle<AbstractCode> abstract_code = summary.abstract_code();
 | 
| +  if (abstract_code->IsCode()) offset = offset - 1;
 | 
| +  int statement_position;
 | 
| +  {
 | 
| +    auto it = BreakIterator::GetIterator(debug_info, abstract_code);
 | 
| +    it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
 | 
| +    statement_position = it->statement_position();
 | 
| +  }
 | 
| +  for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
 | 
| +       !it->Done(); it->Next()) {
 | 
| +    if (it->statement_position() == statement_position) {
 | 
| +      result_out->Add(it->GetBreakLocation());
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
 | 
| +                                            Handle<AbstractCode> abstract_code,
 | 
| +                                            int offset) {
 | 
| +  // Run through all break points to locate the one closest to the address.
 | 
| +  int closest_break = 0;
 | 
| +  int distance = kMaxInt;
 | 
| +  DCHECK(0 <= offset && offset < abstract_code->Size());
 | 
| +  for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
 | 
| +       !it->Done(); it->Next()) {
 | 
| +    // Check if this break point is closer that what was previously found.
 | 
| +    if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
 | 
| +      closest_break = it->break_index();
 | 
| +      distance = offset - it->code_offset();
 | 
| +      // Check whether we can't get any closer.
 | 
| +      if (distance == 0) break;
 | 
| +    }
 | 
| +  }
 | 
| +  return closest_break;
 | 
|  }
 | 
|  
 | 
| -BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
 | 
| -                             int code_offset, int position,
 | 
| -                             int statement_position)
 | 
| -    : debug_info_(debug_info),
 | 
| -      code_offset_(code_offset),
 | 
| -      type_(type),
 | 
| -      position_(position),
 | 
| -      statement_position_(statement_position) {}
 | 
| +bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
 | 
| +  // First check whether there is a break point with the same source position.
 | 
| +  if (!debug_info->HasBreakPoint(position_)) return false;
 | 
| +  // Then check whether a break point at that source position would have
 | 
| +  // the same code offset. Otherwise it's just a break location that we can
 | 
| +  // step to, but not actually a location where we can put a break point.
 | 
| +  if (abstract_code_->IsCode()) {
 | 
| +    DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode());
 | 
| +    CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +    it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
 | 
| +    return it.code_offset() == code_offset_;
 | 
| +  } else {
 | 
| +    DCHECK(abstract_code_->IsBytecodeArray());
 | 
| +    BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +    it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
 | 
| +    return it.code_offset() == code_offset_;
 | 
| +  }
 | 
| +}
 | 
|  
 | 
| -BreakLocation::Iterator* BreakLocation::GetIterator(
 | 
| -    Handle<DebugInfo> debug_info, BreakLocatorType type) {
 | 
| -  if (debug_info->abstract_code()->IsBytecodeArray()) {
 | 
| -    return new BytecodeArrayIterator(debug_info, type);
 | 
| +std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
 | 
| +    Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code,
 | 
| +    BreakLocatorType type) {
 | 
| +  if (abstract_code->IsBytecodeArray()) {
 | 
| +    DCHECK(debug_info->HasDebugBytecodeArray());
 | 
| +    return std::unique_ptr<BreakIterator>(
 | 
| +        new BytecodeArrayBreakIterator(debug_info, type));
 | 
|    } else {
 | 
| -    return new CodeIterator(debug_info, type);
 | 
| +    DCHECK(abstract_code->IsCode());
 | 
| +    DCHECK(debug_info->HasDebugCode());
 | 
| +    return std::unique_ptr<BreakIterator>(
 | 
| +        new CodeBreakIterator(debug_info, type));
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
 | 
| -    : debug_info_(debug_info), break_index_(-1) {
 | 
| +BreakIterator::BreakIterator(Handle<DebugInfo> debug_info,
 | 
| +                             BreakLocatorType type)
 | 
| +    : debug_info_(debug_info), break_index_(-1), break_locator_type_(type) {
 | 
|    position_ = debug_info->shared()->start_position();
 | 
|    statement_position_ = position_;
 | 
|  }
 | 
|  
 | 
| -BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
 | 
| -                                          BreakLocatorType type)
 | 
| -    : Iterator(debug_info),
 | 
| -      reloc_iterator_(debug_info->abstract_code()->GetCode(),
 | 
| -                      GetModeMask(type)),
 | 
| +int BreakIterator::BreakIndexFromPosition(int source_position,
 | 
| +                                          BreakPositionAlignment alignment) {
 | 
| +  int distance = kMaxInt;
 | 
| +  int closest_break = break_index();
 | 
| +  while (!Done()) {
 | 
| +    int next_position;
 | 
| +    if (alignment == STATEMENT_ALIGNED) {
 | 
| +      next_position = statement_position();
 | 
| +    } else {
 | 
| +      DCHECK(alignment == BREAK_POSITION_ALIGNED);
 | 
| +      next_position = position();
 | 
| +    }
 | 
| +    if (source_position <= next_position &&
 | 
| +        next_position - source_position < distance) {
 | 
| +      closest_break = break_index();
 | 
| +      distance = next_position - source_position;
 | 
| +      // Check whether we can't get any closer.
 | 
| +      if (distance == 0) break;
 | 
| +    }
 | 
| +    Next();
 | 
| +  }
 | 
| +  return closest_break;
 | 
| +}
 | 
| +
 | 
| +CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info,
 | 
| +                                     BreakLocatorType type)
 | 
| +    : BreakIterator(debug_info, type),
 | 
| +      reloc_iterator_(debug_info->DebugCode(), GetModeMask(type)),
 | 
|        source_position_iterator_(
 | 
| -          debug_info->abstract_code()->GetCode()->source_position_table()) {
 | 
| +          debug_info->DebugCode()->source_position_table()) {
 | 
|    // There is at least one break location.
 | 
|    DCHECK(!Done());
 | 
|    Next();
 | 
|  }
 | 
|  
 | 
| -int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
 | 
| +int CodeBreakIterator::GetModeMask(BreakLocatorType type) {
 | 
|    int mask = 0;
 | 
|    mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
 | 
|    mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
 | 
| @@ -125,7 +196,7 @@ int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
 | 
|    return mask;
 | 
|  }
 | 
|  
 | 
| -void BreakLocation::CodeIterator::Next() {
 | 
| +void CodeBreakIterator::Next() {
 | 
|    DisallowHeapAllocation no_gc;
 | 
|    DCHECK(!Done());
 | 
|  
 | 
| @@ -151,40 +222,71 @@ void BreakLocation::CodeIterator::Next() {
 | 
|    break_index_++;
 | 
|  }
 | 
|  
 | 
| -BreakLocation BreakLocation::CodeIterator::GetBreakLocation() {
 | 
| -  DebugBreakType type;
 | 
| +DebugBreakType CodeBreakIterator::GetDebugBreakType() {
 | 
|    if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
 | 
| -    type = DEBUG_BREAK_SLOT_AT_RETURN;
 | 
| +    return DEBUG_BREAK_SLOT_AT_RETURN;
 | 
|    } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
 | 
| -    type = DEBUG_BREAK_SLOT_AT_CALL;
 | 
| +    return DEBUG_BREAK_SLOT_AT_CALL;
 | 
|    } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
 | 
| -    type = isolate()->is_tail_call_elimination_enabled()
 | 
| +    return isolate()->is_tail_call_elimination_enabled()
 | 
|                 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
 | 
|                 : DEBUG_BREAK_SLOT_AT_CALL;
 | 
|    } else if (RelocInfo::IsDebuggerStatement(rmode())) {
 | 
| -    type = DEBUGGER_STATEMENT;
 | 
| +    return DEBUGGER_STATEMENT;
 | 
|    } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
 | 
| -    type = DEBUG_BREAK_SLOT;
 | 
| +    return DEBUG_BREAK_SLOT;
 | 
|    } else {
 | 
| -    type = NOT_DEBUG_BREAK;
 | 
| +    return NOT_DEBUG_BREAK;
 | 
|    }
 | 
| -  return BreakLocation(debug_info_, type, code_offset(), position(),
 | 
| -                       statement_position());
 | 
|  }
 | 
|  
 | 
| -BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
 | 
| +void CodeBreakIterator::SkipToPosition(int position,
 | 
| +                                       BreakPositionAlignment alignment) {
 | 
| +  CodeBreakIterator it(debug_info_, break_locator_type_);
 | 
| +  SkipTo(it.BreakIndexFromPosition(position, alignment));
 | 
| +}
 | 
| +
 | 
| +void CodeBreakIterator::SetDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  Builtins* builtins = isolate()->builtins();
 | 
| +  Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN
 | 
| +                            ? builtins->Return_DebugBreak()
 | 
| +                            : builtins->Slot_DebugBreak();
 | 
| +  DebugCodegen::PatchDebugBreakSlot(isolate(), rinfo()->pc(), target);
 | 
| +}
 | 
| +
 | 
| +void CodeBreakIterator::ClearDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  DebugCodegen::ClearDebugBreakSlot(isolate(), rinfo()->pc());
 | 
| +}
 | 
| +
 | 
| +bool CodeBreakIterator::IsDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return false;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc());
 | 
| +}
 | 
| +
 | 
| +BreakLocation CodeBreakIterator::GetBreakLocation() {
 | 
| +  Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode()));
 | 
| +  return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
 | 
| +}
 | 
| +
 | 
| +BytecodeArrayBreakIterator::BytecodeArrayBreakIterator(
 | 
|      Handle<DebugInfo> debug_info, BreakLocatorType type)
 | 
| -    : Iterator(debug_info),
 | 
| -      source_position_iterator_(debug_info->abstract_code()
 | 
| -                                    ->GetBytecodeArray()
 | 
| -                                    ->source_position_table()),
 | 
| -      break_locator_type_(type) {
 | 
| +    : BreakIterator(debug_info, type),
 | 
| +      source_position_iterator_(
 | 
| +          debug_info->DebugBytecodeArray()->source_position_table()) {
 | 
|    // There is at least one break location.
 | 
|    DCHECK(!Done());
 | 
|    Next();
 | 
|  }
 | 
|  
 | 
| -void BreakLocation::BytecodeArrayIterator::Next() {
 | 
| +void BytecodeArrayBreakIterator::Next() {
 | 
|    DisallowHeapAllocation no_gc;
 | 
|    DCHECK(!Done());
 | 
|    bool first = break_index_ == -1;
 | 
| @@ -199,7 +301,7 @@ void BreakLocation::BytecodeArrayIterator::Next() {
 | 
|      DCHECK(position_ >= 0);
 | 
|      DCHECK(statement_position_ >= 0);
 | 
|  
 | 
| -    enum DebugBreakType type = GetDebugBreakType();
 | 
| +    DebugBreakType type = GetDebugBreakType();
 | 
|      if (type == NOT_DEBUG_BREAK) continue;
 | 
|  
 | 
|      if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
 | 
| @@ -211,9 +313,8 @@ void BreakLocation::BytecodeArrayIterator::Next() {
 | 
|    break_index_++;
 | 
|  }
 | 
|  
 | 
| -BreakLocation::DebugBreakType
 | 
| -BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
 | 
| -  BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
 | 
| +DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() {
 | 
| +  BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
 | 
|    interpreter::Bytecode bytecode =
 | 
|        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
 | 
|  
 | 
| @@ -234,215 +335,51 @@ BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
 | 
| -  return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(),
 | 
| -                       position(), statement_position());
 | 
| -}
 | 
| -
 | 
| -// Find the break point at the supplied address, or the closest one before
 | 
| -// the address.
 | 
| -BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
 | 
| -                                            int offset) {
 | 
| -  std::unique_ptr<Iterator> it(GetIterator(debug_info));
 | 
| -  it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
 | 
| -  return it->GetBreakLocation();
 | 
| -}
 | 
| -
 | 
| -BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
 | 
| -                                       JavaScriptFrame* frame) {
 | 
| -  int code_offset = FrameSummary::GetFirst(frame).code_offset();
 | 
| -  int call_offset =
 | 
| -      CallOffsetFromCodeOffset(code_offset, frame->is_interpreted());
 | 
| -  return FromCodeOffset(debug_info, call_offset);
 | 
| -}
 | 
| -
 | 
| -void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info,
 | 
| -                                            int statement_position,
 | 
| -                                            List<BreakLocation>* result_out) {
 | 
| -  for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done();
 | 
| -       it->Next()) {
 | 
| -    if (it->statement_position() == statement_position) {
 | 
| -      result_out->Add(it->GetBreakLocation());
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
 | 
| -                                            int offset) {
 | 
| -  // Run through all break points to locate the one closest to the address.
 | 
| -  int closest_break = 0;
 | 
| -  int distance = kMaxInt;
 | 
| -  DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
 | 
| -  for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done();
 | 
| -       it->Next()) {
 | 
| -    // Check if this break point is closer that what was previously found.
 | 
| -    if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
 | 
| -      closest_break = it->break_index();
 | 
| -      distance = offset - it->code_offset();
 | 
| -      // Check whether we can't get any closer.
 | 
| -      if (distance == 0) break;
 | 
| -    }
 | 
| -  }
 | 
| -  return closest_break;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
 | 
| -                                          int position,
 | 
| -                                          BreakPositionAlignment alignment) {
 | 
| -  // Run through all break points to locate the one closest to the source
 | 
| -  // position.
 | 
| -  int distance = kMaxInt;
 | 
| -  std::unique_ptr<Iterator> it(GetIterator(debug_info));
 | 
| -  BreakLocation closest_break = it->GetBreakLocation();
 | 
| -  while (!it->Done()) {
 | 
| -    int next_position;
 | 
| -    if (alignment == STATEMENT_ALIGNED) {
 | 
| -      next_position = it->statement_position();
 | 
| -    } else {
 | 
| -      DCHECK(alignment == BREAK_POSITION_ALIGNED);
 | 
| -      next_position = it->position();
 | 
| -    }
 | 
| -    if (position <= next_position && next_position - position < distance) {
 | 
| -      closest_break = it->GetBreakLocation();
 | 
| -      distance = next_position - position;
 | 
| -      // Check whether we can't get any closer.
 | 
| -      if (distance == 0) break;
 | 
| -    }
 | 
| -    it->Next();
 | 
| -  }
 | 
| -  return closest_break;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
 | 
| -  // If there is not already a real break point here patch code with debug
 | 
| -  // break.
 | 
| -  if (!HasBreakPoint()) SetDebugBreak();
 | 
| -  DCHECK(IsDebugBreak() || IsDebuggerStatement());
 | 
| -  // Set the break point information.
 | 
| -  DebugInfo::SetBreakPoint(debug_info_, position_, statement_position_,
 | 
| -                           break_point_object);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
 | 
| -  // Clear the break point information.
 | 
| -  DebugInfo::ClearBreakPoint(debug_info_, position_, break_point_object);
 | 
| -  // If there are no more break points here remove the debug break.
 | 
| -  if (!HasBreakPoint()) {
 | 
| -    ClearDebugBreak();
 | 
| -    DCHECK(!IsDebugBreak());
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::SetOneShot() {
 | 
| -  // Debugger statement always calls debugger. No need to modify it.
 | 
| -  if (IsDebuggerStatement()) return;
 | 
| -
 | 
| -  // Patch code with debug break.
 | 
| -  SetDebugBreak();
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::ClearOneShot() {
 | 
| -  // Debugger statement always calls debugger. No need to modify it.
 | 
| -  if (IsDebuggerStatement()) return;
 | 
| -
 | 
| -  // If there is a real break point here no more to do.
 | 
| -  if (HasBreakPoint()) {
 | 
| -    DCHECK(IsDebugBreak());
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
| -  // Patch code removing debug break.
 | 
| -  ClearDebugBreak();
 | 
| -  DCHECK(!IsDebugBreak());
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::SetDebugBreak() {
 | 
| -  // Debugger statement always calls debugger. No need to modify it.
 | 
| -  if (IsDebuggerStatement()) return;
 | 
| -
 | 
| -  // If there is already a break point here just return. This might happen if
 | 
| -  // the same code is flooded with break points twice. Flooding the same
 | 
| -  // function twice might happen when stepping in a function with an exception
 | 
| -  // handler as the handler and the function is the same.
 | 
| -  if (IsDebugBreak()) return;
 | 
| -
 | 
| -  DCHECK(IsDebugBreakSlot());
 | 
| -  if (abstract_code()->IsCode()) {
 | 
| -    Code* code = abstract_code()->GetCode();
 | 
| -    DCHECK(code->kind() == Code::FUNCTION);
 | 
| -    Builtins* builtins = isolate()->builtins();
 | 
| -    Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
 | 
| -                                     : builtins->Slot_DebugBreak();
 | 
| -    Address pc = code->instruction_start() + code_offset();
 | 
| -    DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
 | 
| -  } else {
 | 
| -    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
 | 
| -    interpreter::Bytecode bytecode =
 | 
| -        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
 | 
| -    interpreter::Bytecode debugbreak =
 | 
| -        interpreter::Bytecodes::GetDebugBreak(bytecode);
 | 
| -    bytecode_array->set(code_offset(),
 | 
| -                        interpreter::Bytecodes::ToByte(debugbreak));
 | 
| -  }
 | 
| -  DCHECK(IsDebugBreak());
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void BreakLocation::ClearDebugBreak() {
 | 
| -  // Debugger statement always calls debugger. No need to modify it.
 | 
| -  if (IsDebuggerStatement()) return;
 | 
| -
 | 
| -  DCHECK(IsDebugBreakSlot());
 | 
| -  if (abstract_code()->IsCode()) {
 | 
| -    Code* code = abstract_code()->GetCode();
 | 
| -    DCHECK(code->kind() == Code::FUNCTION);
 | 
| -    Address pc = code->instruction_start() + code_offset();
 | 
| -    DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
 | 
| -  } else {
 | 
| -    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
 | 
| -    BytecodeArray* original = debug_info_->original_bytecode_array();
 | 
| -    bytecode_array->set(code_offset(), original->get(code_offset()));
 | 
| -  }
 | 
| -  DCHECK(!IsDebugBreak());
 | 
| +void BytecodeArrayBreakIterator::SkipToPosition(
 | 
| +    int position, BreakPositionAlignment alignment) {
 | 
| +  BytecodeArrayBreakIterator it(debug_info_, break_locator_type_);
 | 
| +  SkipTo(it.BreakIndexFromPosition(position, alignment));
 | 
|  }
 | 
|  
 | 
| -
 | 
| -bool BreakLocation::IsDebugBreak() const {
 | 
| -  if (IsDebuggerStatement()) return false;
 | 
| -  DCHECK(IsDebugBreakSlot());
 | 
| -  if (abstract_code()->IsCode()) {
 | 
| -    Code* code = abstract_code()->GetCode();
 | 
| -    DCHECK(code->kind() == Code::FUNCTION);
 | 
| -    Address pc = code->instruction_start() + code_offset();
 | 
| -    return DebugCodegen::DebugBreakSlotIsPatched(pc);
 | 
| -  } else {
 | 
| -    BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
 | 
| -    interpreter::Bytecode bytecode =
 | 
| -        interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
 | 
| -    return interpreter::Bytecodes::IsDebugBreak(bytecode);
 | 
| -  }
 | 
| +void BytecodeArrayBreakIterator::SetDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
 | 
| +  interpreter::Bytecode bytecode =
 | 
| +      interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
 | 
| +  if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
 | 
| +  interpreter::Bytecode debugbreak =
 | 
| +      interpreter::Bytecodes::GetDebugBreak(bytecode);
 | 
| +  bytecode_array->set(code_offset(),
 | 
| +                      interpreter::Bytecodes::ToByte(debugbreak));
 | 
| +}
 | 
| +
 | 
| +void BytecodeArrayBreakIterator::ClearDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
 | 
| +  BytecodeArray* original = debug_info_->OriginalBytecodeArray();
 | 
| +  bytecode_array->set(code_offset(), original->get(code_offset()));
 | 
| +}
 | 
| +
 | 
| +bool BytecodeArrayBreakIterator::IsDebugBreak() {
 | 
| +  DebugBreakType debug_break_type = GetDebugBreakType();
 | 
| +  if (debug_break_type == DEBUGGER_STATEMENT) return false;
 | 
| +  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
 | 
| +  BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
 | 
| +  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(position_);
 | 
| +BreakLocation BytecodeArrayBreakIterator::GetBreakLocation() {
 | 
| +  Handle<AbstractCode> code(
 | 
| +      AbstractCode::cast(debug_info_->DebugBytecodeArray()));
 | 
| +  return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
 | 
|  }
 | 
|  
 | 
| -bool BreakLocation::HasBreakPoint() const {
 | 
| -  // First check whether there is a break point with the same source position.
 | 
| -  if (!debug_info_->HasBreakPoint(position_)) return false;
 | 
| -  // Then check whether a break point at that source position would have
 | 
| -  // the same code offset. Otherwise it's just a break location that we can
 | 
| -  // step to, but not actually a location where we can put a break point.
 | 
| -  BreakLocation break_point_location = BreakLocation::FromPosition(
 | 
| -      debug_info_, position_, BREAK_POSITION_ALIGNED);
 | 
| -  return break_point_location.code_offset() == code_offset_;
 | 
| -}
 | 
|  
 | 
|  void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
 | 
|    uint32_t mask = 1 << feature;
 | 
| @@ -582,7 +519,7 @@ void Debug::Break(JavaScriptFrame* frame) {
 | 
|    BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
 | 
|  
 | 
|    // Find actual break points, if any, and trigger debug break event.
 | 
| -  Handle<Object> break_points_hit = CheckBreakPoints(&location);
 | 
| +  Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location);
 | 
|    if (!break_points_hit->IsUndefined(isolate_)) {
 | 
|      // Clear all current stepping setup.
 | 
|      ClearStepping();
 | 
| @@ -618,7 +555,7 @@ void Debug::Break(JavaScriptFrame* frame) {
 | 
|        step_break = step_break || location.IsReturn() ||
 | 
|                     (current_fp != last_fp) ||
 | 
|                     (thread_local_.last_statement_position_ !=
 | 
| -                    location.abstract_code()->SourceStatementPosition(offset));
 | 
| +                    summary.abstract_code()->SourceStatementPosition(offset));
 | 
|        break;
 | 
|      }
 | 
|      case StepFrame:
 | 
| @@ -641,15 +578,17 @@ void Debug::Break(JavaScriptFrame* frame) {
 | 
|  
 | 
|  // 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,
 | 
| +Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
 | 
| +                                       BreakLocation* location,
 | 
|                                         bool* has_break_points) {
 | 
|    Factory* factory = isolate_->factory();
 | 
|    bool has_break_points_to_check =
 | 
| -      break_points_active_ && location->HasBreakPoint();
 | 
| +      break_points_active_ && location->HasBreakPoint(debug_info);
 | 
|    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();
 | 
| +  Handle<Object> break_point_objects =
 | 
| +      debug_info->GetBreakPointObjects(location->position());
 | 
|    // Count the number of break points hit. If there are multiple break points
 | 
|    // they are in a FixedArray.
 | 
|    Handle<FixedArray> break_points_hit;
 | 
| @@ -692,15 +631,13 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
 | 
|    // 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);
 | 
| +  BreakLocation::AllAtCurrentStatement(debug_info, frame, &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);
 | 
| +        CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
 | 
|      has_break_points_at_all |= has_break_points;
 | 
|      if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
 | 
|    }
 | 
| @@ -762,15 +699,17 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
 | 
|    DCHECK(*source_position >= 0);
 | 
|  
 | 
|    // Find the break point and change it.
 | 
| -  BreakLocation location = BreakLocation::FromPosition(
 | 
| -      debug_info, *source_position, STATEMENT_ALIGNED);
 | 
| -  *source_position = location.statement_position();
 | 
| -  location.SetBreakPoint(break_point_object);
 | 
| +  *source_position =
 | 
| +      FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED);
 | 
| +  DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
 | 
| +  // At least one active break point now.
 | 
| +  DCHECK(debug_info->GetBreakPointCount() > 0);
 | 
|  
 | 
| -  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
 | 
| +  ClearBreakPoints(debug_info);
 | 
| +  ApplyBreakPoints(debug_info);
 | 
|  
 | 
| -  // At least one active break point now.
 | 
| -  return debug_info->GetBreakPointCount() > 0;
 | 
| +  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
 | 
| +  return true;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -805,64 +744,104 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
 | 
|    Handle<DebugInfo> debug_info(shared->GetDebugInfo());
 | 
|  
 | 
|    // Find the break point and change it.
 | 
| -  BreakLocation location =
 | 
| -      BreakLocation::FromPosition(debug_info, *source_position, alignment);
 | 
| -  location.SetBreakPoint(break_point_object);
 | 
| +  *source_position =
 | 
| +      FindBreakablePosition(debug_info, *source_position, alignment);
 | 
| +  DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
 | 
| +  // At least one active break point now.
 | 
| +  DCHECK(debug_info->GetBreakPointCount() > 0);
 | 
| +
 | 
| +  ClearBreakPoints(debug_info);
 | 
| +  ApplyBreakPoints(debug_info);
 | 
|  
 | 
|    feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
 | 
| +  return true;
 | 
| +}
 | 
|  
 | 
| -  *source_position = (alignment == STATEMENT_ALIGNED)
 | 
| -                         ? location.statement_position()
 | 
| -                         : location.position();
 | 
| +int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
 | 
| +                                 int source_position,
 | 
| +                                 BreakPositionAlignment alignment) {
 | 
| +  int statement_position;
 | 
| +  int position;
 | 
| +  if (debug_info->HasDebugCode()) {
 | 
| +    CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +    it.SkipToPosition(source_position, alignment);
 | 
| +    statement_position = it.statement_position();
 | 
| +    position = it.position();
 | 
| +  } else {
 | 
| +    DCHECK(debug_info->HasDebugBytecodeArray());
 | 
| +    BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +    it.SkipToPosition(source_position, alignment);
 | 
| +    statement_position = it.statement_position();
 | 
| +    position = it.position();
 | 
| +  }
 | 
| +  return alignment == STATEMENT_ALIGNED ? statement_position : position;
 | 
| +}
 | 
|  
 | 
| -  // At least one active break point now.
 | 
| -  DCHECK(debug_info->GetBreakPointCount() > 0);
 | 
| -  return true;
 | 
| +void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
 | 
| +  DisallowHeapAllocation no_gc;
 | 
| +  if (debug_info->break_points()->IsUndefined(isolate_)) return;
 | 
| +  FixedArray* break_points = debug_info->break_points();
 | 
| +  for (int i = 0; i < break_points->length(); i++) {
 | 
| +    if (break_points->get(i)->IsUndefined(isolate_)) continue;
 | 
| +    BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
 | 
| +    if (info->GetBreakPointCount() == 0) continue;
 | 
| +    if (debug_info->HasDebugCode()) {
 | 
| +      CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +      it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
 | 
| +      it.SetDebugBreak();
 | 
| +    }
 | 
| +    if (debug_info->HasDebugBytecodeArray()) {
 | 
| +      BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +      it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
 | 
| +      it.SetDebugBreak();
 | 
| +    }
 | 
| +  }
 | 
|  }
 | 
|  
 | 
| +void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
 | 
| +  DisallowHeapAllocation no_gc;
 | 
| +  if (debug_info->HasDebugCode()) {
 | 
| +    for (CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done();
 | 
| +         it.Next()) {
 | 
| +      it.ClearDebugBreak();
 | 
| +    }
 | 
| +  }
 | 
| +  if (debug_info->HasDebugBytecodeArray()) {
 | 
| +    for (BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +         !it.Done(); it.Next()) {
 | 
| +      it.ClearDebugBreak();
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
|  
 | 
|  void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
 | 
|    HandleScope scope(isolate_);
 | 
|  
 | 
| -  DebugInfoListNode* node = debug_info_list_;
 | 
| -  while (node != NULL) {
 | 
| +  for (DebugInfoListNode* node = debug_info_list_; node != NULL;
 | 
| +       node = node->next()) {
 | 
|      Handle<Object> result =
 | 
|          DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
 | 
| -    if (!result->IsUndefined(isolate_)) {
 | 
| -      // Get information in the break point.
 | 
| -      Handle<BreakPointInfo> break_point_info =
 | 
| -          Handle<BreakPointInfo>::cast(result);
 | 
| -      Handle<DebugInfo> debug_info = node->debug_info();
 | 
| -
 | 
| -      BreakLocation location = BreakLocation::FromPosition(
 | 
| -          debug_info, break_point_info->source_position(),
 | 
| -          BREAK_POSITION_ALIGNED);
 | 
| -      location.ClearBreakPoint(break_point_object);
 | 
| -
 | 
| -      // If there are no more break points left remove the debug info for this
 | 
| -      // function.
 | 
| +    if (result->IsUndefined(isolate_)) continue;
 | 
| +    Handle<DebugInfo> debug_info = node->debug_info();
 | 
| +    if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
 | 
| +      ClearBreakPoints(debug_info);
 | 
|        if (debug_info->GetBreakPointCount() == 0) {
 | 
|          RemoveDebugInfoAndClearFromShared(debug_info);
 | 
| +      } else {
 | 
| +        ApplyBreakPoints(debug_info);
 | 
|        }
 | 
| -
 | 
|        return;
 | 
|      }
 | 
| -    node = node->next();
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -
 | 
|  // Clear out all the debug break code. This is ONLY supposed to be used when
 | 
|  // shutting down the debugger as it will leave the break point information in
 | 
|  // DebugInfo even though the code is patched back to the non break point state.
 | 
|  void Debug::ClearAllBreakPoints() {
 | 
|    for (DebugInfoListNode* node = debug_info_list_; node != NULL;
 | 
|         node = node->next()) {
 | 
| -    for (std::unique_ptr<BreakLocation::Iterator> it(
 | 
| -             BreakLocation::GetIterator(node->debug_info()));
 | 
| -         !it->Done(); it->Next()) {
 | 
| -      it->GetBreakLocation().ClearDebugBreak();
 | 
| -    }
 | 
| +    ClearBreakPoints(node->debug_info());
 | 
|    }
 | 
|    // Remove all debug info.
 | 
|    while (debug_info_list_ != NULL) {
 | 
| @@ -870,7 +849,6 @@ void Debug::ClearAllBreakPoints() {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -
 | 
|  void Debug::FloodWithOneShot(Handle<JSFunction> function,
 | 
|                               BreakLocatorType type) {
 | 
|    // Debug utility functions are not subject to debugging.
 | 
| @@ -892,14 +870,19 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function,
 | 
|  
 | 
|    // Flood the function with break points.
 | 
|    Handle<DebugInfo> debug_info(shared->GetDebugInfo());
 | 
| -  for (std::unique_ptr<BreakLocation::Iterator> it(
 | 
| -           BreakLocation::GetIterator(debug_info, type));
 | 
| -       !it->Done(); it->Next()) {
 | 
| -    it->GetBreakLocation().SetOneShot();
 | 
| +  if (debug_info->HasDebugCode()) {
 | 
| +    for (CodeBreakIterator it(debug_info, type); !it.Done(); it.Next()) {
 | 
| +      it.SetDebugBreak();
 | 
| +    }
 | 
| +  }
 | 
| +  if (debug_info->HasDebugBytecodeArray()) {
 | 
| +    for (BytecodeArrayBreakIterator it(debug_info, type); !it.Done();
 | 
| +         it.Next()) {
 | 
| +      it.SetDebugBreak();
 | 
| +    }
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -
 | 
|  void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
 | 
|    if (type == BreakUncaughtException) {
 | 
|      break_on_uncaught_exception_ = enable;
 | 
| @@ -1014,15 +997,7 @@ void Debug::PrepareStep(StepAction step_action) {
 | 
|    }
 | 
|  
 | 
|    Handle<DebugInfo> debug_info(shared->GetDebugInfo());
 | 
| -  // Refresh frame summary if the code has been recompiled for debugging.
 | 
| -  if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
 | 
| -    summary = FrameSummary::GetFirst(frame);
 | 
| -  }
 | 
| -
 | 
| -  int call_offset =
 | 
| -      CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
 | 
| -  BreakLocation location =
 | 
| -      BreakLocation::FromCodeOffset(debug_info, call_offset);
 | 
| +  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
 | 
|  
 | 
|    // Any step at a return is a step-out.
 | 
|    if (location.IsReturn()) step_action = StepOut;
 | 
| @@ -1030,8 +1005,7 @@ void Debug::PrepareStep(StepAction step_action) {
 | 
|    if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
 | 
|  
 | 
|    thread_local_.last_statement_position_ =
 | 
| -      debug_info->abstract_code()->SourceStatementPosition(
 | 
| -          summary.code_offset());
 | 
| +      summary.abstract_code()->SourceStatementPosition(summary.code_offset());
 | 
|    thread_local_.last_fp_ = frame->UnpaddedFP();
 | 
|    // No longer perform the current async step.
 | 
|    clear_suspended_generator();
 | 
| @@ -1076,7 +1050,6 @@ void Debug::PrepareStep(StepAction step_action) {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -
 | 
|  // Simple function for returning the source positions for active break points.
 | 
|  Handle<Object> Debug::GetSourceBreakLocations(
 | 
|      Handle<SharedFunctionInfo> shared,
 | 
| @@ -1100,10 +1073,18 @@ Handle<Object> Debug::GetSourceBreakLocations(
 | 
|        if (break_points == 0) continue;
 | 
|        Smi* position = NULL;
 | 
|        if (position_alignment == STATEMENT_ALIGNED) {
 | 
| -        BreakLocation break_point_location = BreakLocation::FromPosition(
 | 
| -            debug_info, break_point_info->source_position(),
 | 
| -            BREAK_POSITION_ALIGNED);
 | 
| -        position = Smi::FromInt(break_point_location.statement_position());
 | 
| +        if (debug_info->HasDebugCode()) {
 | 
| +          CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +          it.SkipToPosition(break_point_info->source_position(),
 | 
| +                            BREAK_POSITION_ALIGNED);
 | 
| +          position = Smi::FromInt(it.statement_position());
 | 
| +        } else {
 | 
| +          DCHECK(debug_info->HasDebugBytecodeArray());
 | 
| +          BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
 | 
| +          it.SkipToPosition(break_point_info->source_position(),
 | 
| +                            BREAK_POSITION_ALIGNED);
 | 
| +          position = Smi::FromInt(it.statement_position());
 | 
| +        }
 | 
|        } else {
 | 
|          DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment);
 | 
|          position = Smi::FromInt(break_point_info->source_position());
 | 
| @@ -1114,7 +1095,6 @@ Handle<Object> Debug::GetSourceBreakLocations(
 | 
|    return locations;
 | 
|  }
 | 
|  
 | 
| -
 | 
|  void Debug::ClearStepping() {
 | 
|    // Clear the various stepping setup.
 | 
|    ClearOneShot();
 | 
| @@ -1135,11 +1115,9 @@ void Debug::ClearOneShot() {
 | 
|    // removed from the list.
 | 
|    for (DebugInfoListNode* node = debug_info_list_; node != NULL;
 | 
|         node = node->next()) {
 | 
| -    for (std::unique_ptr<BreakLocation::Iterator> it(
 | 
| -             BreakLocation::GetIterator(node->debug_info()));
 | 
| -         !it->Done(); it->Next()) {
 | 
| -      it->GetBreakLocation().ClearOneShot();
 | 
| -    }
 | 
| +    Handle<DebugInfo> debug_info = node->debug_info();
 | 
| +    ClearBreakPoints(debug_info);
 | 
| +    ApplyBreakPoints(debug_info);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -1243,7 +1221,7 @@ class RedirectActiveFunctions : public ThreadVisitor {
 | 
|          InterpretedFrame* interpreted_frame =
 | 
|              reinterpret_cast<InterpretedFrame*>(frame);
 | 
|          BytecodeArray* debug_copy =
 | 
| -            shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray();
 | 
| +            shared_->GetDebugInfo()->DebugBytecodeArray();
 | 
|          interpreted_frame->PatchBytecodeArray(debug_copy);
 | 
|          continue;
 | 
|        }
 | 
| @@ -1596,10 +1574,8 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
 | 
|    if (!shared->HasDebugInfo()) return false;
 | 
|  
 | 
|    DCHECK(!frame->is_optimized());
 | 
| -  int code_offset = FrameSummary::GetFirst(frame).code_offset();
 | 
|    Handle<DebugInfo> debug_info(shared->GetDebugInfo());
 | 
| -  BreakLocation location =
 | 
| -      BreakLocation::FromCodeOffset(debug_info, code_offset);
 | 
| +  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
 | 
|    return location.IsReturn() || location.IsTailCall();
 | 
|  }
 | 
|  
 | 
| @@ -2430,6 +2406,16 @@ v8::Local<v8::String> MessageImpl::GetJSON() const {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +namespace {
 | 
| +v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
 | 
| +  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
 | 
| +  // Isolate::context() may have been NULL when "script collected" event
 | 
| +  // occured.
 | 
| +  if (context.is_null()) return v8::Local<v8::Context>();
 | 
| +  Handle<Context> native_context(context->native_context());
 | 
| +  return v8::Utils::ToLocal(native_context);
 | 
| +}
 | 
| +}  // anonymous namespace
 | 
|  
 | 
|  v8::Local<v8::Context> MessageImpl::GetEventContext() const {
 | 
|    Isolate* isolate = event_data_->GetIsolate();
 | 
| 
 |