Refactor BreakLocationIterator.
authoryangguo <yangguo@chromium.org>
Wed, 4 Mar 2015 13:15:07 +0000 (05:15 -0800)
committerCommit bot <commit-bot@chromium.org>
Wed, 4 Mar 2015 13:15:34 +0000 (13:15 +0000)
We now have BreakLocation::Iterator to iterate via RelocIterator, and
create a BreakLocation when we are done iterating. The reloc info is
stored in BreakLocation in a GC-safe way and instantiated on demand.

R=ulan@chromium.org
BUG=v8:3924
LOG=N

Review URL: https://codereview.chromium.org/967323002

Cr-Commit-Position: refs/heads/master@{#26983}

34 files changed:
src/arm/assembler-arm.cc
src/arm/assembler-arm.h
src/arm/debug-arm.cc
src/arm64/assembler-arm64-inl.h
src/arm64/assembler-arm64.cc
src/arm64/assembler-arm64.h
src/arm64/debug-arm64.cc
src/arm64/full-codegen-arm64.cc
src/assembler.h
src/debug.cc
src/debug.h
src/ia32/assembler-ia32.cc
src/ia32/debug-ia32.cc
src/mips/assembler-mips-inl.h
src/mips/assembler-mips.cc
src/mips/assembler-mips.h
src/mips/debug-mips.cc
src/mips64/assembler-mips64-inl.h
src/mips64/assembler-mips64.cc
src/mips64/assembler-mips64.h
src/mips64/debug-mips64.cc
src/objects.cc
src/objects.h
src/ppc/assembler-ppc-inl.h
src/ppc/assembler-ppc.cc
src/ppc/assembler-ppc.h
src/ppc/debug-ppc.cc
src/runtime/runtime-debug.cc
src/x64/assembler-x64.cc
src/x64/debug-x64.cc
src/x87/assembler-x87.cc
src/x87/debug-x87.cc
test/cctest/test-debug.cc
test/cctest/test-func-name-inference.cc

index bbc766bed3d743bf77f2d9baa1c5487a07ed0d52..b1e664ac26542f91dacc4da12f6121ab4285aaf2 100644 (file)
@@ -246,27 +246,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  Instr* pc = reinterpret_cast<Instr*>(pc_);
-  Instr* instr = reinterpret_cast<Instr*>(instructions);
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc + i) = *(instr + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  // Patch the code at the current address with a call to the target.
-  UNIMPLEMENTED();
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand
 // See assembler-arm-inl.h for inlined constructors
index 721b0bce41ffe647b011d8c0a0a0ffbe9fb77944..fc143e17414e1b497e81c0029a9fda6fca3e4219 100644 (file)
@@ -824,6 +824,8 @@ class Assembler : public AssemblerBase {
   static const int kPcLoadDelta = 8;
 
   static const int kJSReturnSequenceInstructions = 4;
+  static const int kJSReturnSequenceLength =
+      kJSReturnSequenceInstructions * kInstrSize;
   static const int kDebugBreakSlotInstructions = 3;
   static const int kDebugBreakSlotLength =
       kDebugBreakSlotInstructions * kInstrSize;
index c9100576d2f61813654edfb34f3b91f0d50c42c7..d9c25c6588c6a64cec29709d9443cf6541d4b39f 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtReturn() {
+void BreakLocation::SetDebugBreakAtReturn() {
   // Patch the code changing the return from JS function sequence from
   //   mov sp, fp
   //   ldmia sp!, {fp, lr}
@@ -28,7 +23,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
   //   blx ip
   //   <debug break return code entry point address>
   //   bkpt 0
-  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
+  CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions);
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
   patcher.Emit(
@@ -37,29 +32,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 }
 
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceInstructions);
-}
-
-
-// A debug break in the frame exit code is identified by the JS frame exit code
-// having been patched with a call instruction.
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   // Patch the code changing the debug break slot code from
   //   mov r2, r2
@@ -69,7 +42,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   //   ldr ip, [pc, #0]
   //   blx ip
   //   <debug break slot code entry point address>
-  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+  CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions);
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
   patcher.Emit(
@@ -77,13 +50,6 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kDebugBreakSlotInstructions);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 
index 4547efef0c66677109d364cbd4dd3be3c8bd4e9f..b13635f28e3bdfff294f5abffe88ee0718141b7d 100644 (file)
@@ -838,7 +838,7 @@ bool RelocInfo::IsPatchedReturnSequence() {
   // The sequence must be:
   //   ldr ip0, [pc, #offset]
   //   blr ip0
-  // See arm64/debug-arm64.cc BreakLocationIterator::SetDebugBreakAtReturn().
+  // See arm64/debug-arm64.cc BreakLocation::SetDebugBreakAtReturn().
   Instruction* i1 = reinterpret_cast<Instruction*>(pc_);
   Instruction* i2 = i1->following();
   return i1->IsLdrLiteralX() && (i1->Rt() == ip0.code()) &&
index bba78c89e47441f0f901b2e55729bf13b5b26556..93d1d25a6c7747628d51c0c4466432ad9e749fd8 100644 (file)
@@ -188,26 +188,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  Instr* pc = reinterpret_cast<Instr*>(pc_);
-  Instr* instr = reinterpret_cast<Instr*>(instructions);
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc + i) = *(instr + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count * kInstructionSize);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  UNIMPLEMENTED();
-}
-
-
 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
                                               Register reg3, Register reg4) {
   CPURegList regs(reg1, reg2, reg3, reg4);
index 16d027065f94a75c3418aeb6fa87448c3eee2bc6..23662ad7a0f276d6d0cb2f6c9847a3a75646f2cb 100644 (file)
@@ -952,7 +952,9 @@ class Assembler : public AssemblerBase {
 
   // Number of instructions generated for the return sequence in
   // FullCodeGenerator::EmitReturnSequence.
-  static const int kJSRetSequenceInstructions = 7;
+  static const int kJSReturnSequenceInstructions = 7;
+  static const int kJSReturnSequenceLength =
+      kJSReturnSequenceInstructions * kInstructionSize;
   // Distance between start of patched return sequence and the emitted address
   // to jump to.
   static const int kPatchReturnSequenceAddressOffset =  0;
@@ -960,7 +962,7 @@ class Assembler : public AssemblerBase {
 
   // Number of instructions necessary to be able to later patch it to a call.
   // See DebugCodegen::GenerateSlot() and
-  // BreakLocationIterator::SetDebugBreakAtSlot().
+  // BreakLocation::SetDebugBreakAtSlot().
   static const int kDebugBreakSlotInstructions = 4;
   static const int kDebugBreakSlotLength =
     kDebugBreakSlotInstructions * kInstructionSize;
index dae5a28434a898ac3bd801150d457604dd0b7552..56e3c031ed23a15e95e5d8d3a3de500c0345e8f7 100644 (file)
@@ -15,12 +15,8 @@ namespace internal {
 
 #define __ ACCESS_MASM(masm)
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
 
-void BreakLocationIterator::SetDebugBreakAtReturn() {
+void BreakLocation::SetDebugBreakAtReturn() {
   // Patch the code emitted by FullCodeGenerator::EmitReturnSequence, changing
   // the return from JS function sequence from
   //   mov sp, fp
@@ -39,8 +35,8 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 
   // The patching code must not overflow the space occupied by the return
   // sequence.
-  STATIC_ASSERT(Assembler::kJSRetSequenceInstructions >= 5);
-  PatchingAssembler patcher(reinterpret_cast<Instruction*>(rinfo()->pc()), 5);
+  STATIC_ASSERT(Assembler::kJSReturnSequenceInstructions >= 5);
+  PatchingAssembler patcher(reinterpret_cast<Instruction*>(pc()), 5);
   byte* entry =
       debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry();
 
@@ -59,27 +55,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  // Reset the code emitted by EmitReturnSequence to its original state.
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSRetSequenceInstructions);
-}
-
-
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   // Patch the code emitted by DebugCodegen::GenerateSlots, changing the debug
   // break slot code from
   //   mov x0, x0    @ nop DEBUG_BREAK_NOP
@@ -99,7 +75,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   // The patching code must not overflow the space occupied by the return
   // sequence.
   STATIC_ASSERT(Assembler::kDebugBreakSlotInstructions >= 4);
-  PatchingAssembler patcher(reinterpret_cast<Instruction*>(rinfo()->pc()), 4);
+  PatchingAssembler patcher(reinterpret_cast<Instruction*>(pc()), 4);
   byte* entry =
       debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry();
 
@@ -117,13 +93,6 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kDebugBreakSlotInstructions);
-}
-
-
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
                                           RegList object_regs,
                                           RegList non_object_regs,
index e168028b488feb5b4f7f59642cbe9beff52c366f..97bfb80ae0d4e7566ab8818bac276caba8747465 100644 (file)
@@ -456,10 +456,10 @@ void FullCodeGenerator::EmitReturnSequence() {
 
     // Make sure that the constant pool is not emitted inside of the return
     // sequence. This sequence can get patched when the debugger is used. See
-    // debug-arm64.cc:BreakLocationIterator::SetDebugBreakAtReturn().
+    // debug-arm64.cc:BreakLocation::SetDebugBreakAtReturn().
     {
       InstructionAccurateScope scope(masm_,
-                                     Assembler::kJSRetSequenceInstructions);
+                                     Assembler::kJSReturnSequenceInstructions);
       CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
       __ RecordJSReturn();
       // This code is generated using Assembler methods rather than Macro
index eb00f8a7e640c619f7ddc04885201ead18a1f5ac..9e6311dafd049e69c0e79ac867ecbf438241ebb5 100644 (file)
@@ -476,6 +476,9 @@ class RelocInfo {
   static inline bool IsDebugBreakSlot(Mode mode) {
     return mode == DEBUG_BREAK_SLOT;
   }
+  static inline bool IsDebuggerStatement(Mode mode) {
+    return mode == DEBUG_BREAK;
+  }
   static inline bool IsNone(Mode mode) {
     return mode == NONE32 || mode == NONE64;
   }
@@ -595,9 +598,6 @@ class RelocInfo {
   template<typename StaticVisitor> inline void Visit(Heap* heap);
   inline void Visit(Isolate* isolate, ObjectVisitor* v);
 
-  // Patch the code with some other code.
-  void PatchCode(byte* instructions, int instruction_count);
-
   // Patch the code with a call.
   void PatchCodeWithCall(Address target, int guard_bytes);
 
index ea402ffa3d8c44865b509c7a2b60dbcf1c887593..0cd20ad5b134c9a3c2db796efebeb45d9fd23e7d 100644 (file)
@@ -60,47 +60,29 @@ static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
 }
 
 
-BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
-                                             BreakLocatorType type) {
-  debug_info_ = debug_info;
-  type_ = type;
-  reloc_iterator_ = NULL;
-  reloc_iterator_original_ = NULL;
-  Reset();  // Initialize the rest of the member variables.
-}
-
-
-BreakLocationIterator::~BreakLocationIterator() {
-  DCHECK(reloc_iterator_ != NULL);
-  DCHECK(reloc_iterator_original_ != NULL);
-  delete reloc_iterator_;
-  delete reloc_iterator_original_;
-}
-
-
-// Check whether a code stub with the specified major key is a possible break
-// point location when looking for source break locations.
-static bool IsSourceBreakStub(Code* code) {
-  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
-  return major_key == CodeStub::CallFunction;
-}
-
-
-// Check whether a code stub with the specified major key is a possible break
-// location.
-static bool IsBreakStub(Code* code) {
-  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
-  return major_key == CodeStub::CallFunction;
+BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
+                                  BreakLocatorType type)
+    : debug_info_(debug_info),
+      type_(type),
+      reloc_iterator_(debug_info->code(),
+                      ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
+      reloc_iterator_original_(
+          debug_info->original_code(),
+          ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
+      break_index_(-1),
+      position_(1),
+      statement_position_(1) {
+  Next();
 }
 
 
-void BreakLocationIterator::Next() {
+void BreakLocation::Iterator::Next() {
   DisallowHeapAllocation no_gc;
   DCHECK(!RinfoDone());
 
   // Iterate through reloc info for code and original code stopping at each
   // breakable code target.
-  bool first = break_point_ == -1;
+  bool first = break_index_ == -1;
   while (!RinfoDone()) {
     if (!first) RinfoNext();
     first = false;
@@ -115,8 +97,8 @@ void BreakLocationIterator::Next() {
       }
       // Always update the position as we don't want that to be before the
       // statement position.
-      position_ = static_cast<int>(
-          rinfo()->data() - debug_info_->shared()->start_position());
+      position_ = static_cast<int>(rinfo()->data() -
+                                   debug_info_->shared()->start_position());
       DCHECK(position_ >= 0);
       DCHECK(statement_position_ >= 0);
     }
@@ -131,7 +113,7 @@ void BreakLocationIterator::Next() {
         position_ = 0;
       }
       statement_position_ = position_;
-      break_point_++;
+      break_index_++;
       return;
     }
 
@@ -143,7 +125,7 @@ void BreakLocationIterator::Next() {
       Code* code = Code::GetCodeFromTargetAddress(target);
 
       if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
-        break_point_++;
+        break_index_++;
         return;
       }
 
@@ -152,144 +134,117 @@ void BreakLocationIterator::Next() {
 
       if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
            !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
-        break_point_++;
+        break_index_++;
         return;
       }
       if (code->kind() == Code::STUB) {
-        if (IsDebuggerStatement()) {
-          break_point_++;
+        if (RelocInfo::IsDebuggerStatement(rmode())) {
+          break_index_++;
+          return;
+        } else if (CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
+          break_index_++;
           return;
-        } else if (type_ == ALL_BREAK_LOCATIONS) {
-          if (IsBreakStub(code)) {
-            break_point_++;
-            return;
-          }
-        } else {
-          DCHECK(type_ == SOURCE_BREAK_LOCATIONS);
-          if (IsSourceBreakStub(code)) {
-            break_point_++;
-            return;
-          }
         }
       }
     }
 
-    if (IsDebugBreakSlot() && type_ != CALLS_AND_RETURNS) {
+    if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
       // There is always a possible break point at a debug break slot.
-      break_point_++;
+      break_index_++;
       return;
     }
   }
 }
 
 
-void BreakLocationIterator::Next(int count) {
-  while (count > 0) {
-    Next();
-    count--;
-  }
+// Find the break point at the supplied address, or the closest one before
+// the address.
+BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
+                                         BreakLocatorType type, Address pc) {
+  Iterator it(debug_info, type);
+  it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
+  return it.GetBreakLocation();
 }
 
 
 // Find the break point at the supplied address, or the closest one before
 // the address.
-void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
+void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
+                                             BreakLocatorType type, Address pc,
+                                             List<BreakLocation>* result_out) {
+  int break_index = BreakIndexFromAddress(debug_info, type, pc);
+  Iterator it(debug_info, type);
+  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,
+                                         BreakLocatorType type, Address pc) {
   // Run through all break points to locate the one closest to the address.
-  int closest_break_point = 0;
+  int closest_break = 0;
   int distance = kMaxInt;
-  while (!Done()) {
+  for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
     // Check if this break point is closer that what was previously found.
-    if (this->pc() <= pc && pc - this->pc() < distance) {
-      closest_break_point = break_point();
-      distance = static_cast<int>(pc - this->pc());
+    if (it.pc() <= pc && pc - it.pc() < distance) {
+      closest_break = it.break_index();
+      distance = static_cast<int>(pc - it.pc());
       // Check whether we can't get any closer.
       if (distance == 0) break;
     }
-    Next();
   }
-
-  // Move to the break point found.
-  Reset();
-  Next(closest_break_point);
+  return closest_break;
 }
 
 
-// Find the break point closest to the supplied source position.
-void BreakLocationIterator::FindBreakLocationFromPosition(int position,
-    BreakPositionAlignment alignment) {
+BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
+                                          BreakLocatorType type, int position,
+                                          BreakPositionAlignment alignment) {
   // Run through all break points to locate the one closest to the source
   // position.
-  int closest_break_point = 0;
+  int closest_break = 0;
   int distance = kMaxInt;
 
-  while (!Done()) {
+  for (Iterator it(debug_info, type); !it.Done(); it.Next()) {
     int next_position;
-    switch (alignment) {
-    case STATEMENT_ALIGNED:
-      next_position = this->statement_position();
-      break;
-    case BREAK_POSITION_ALIGNED:
-      next_position = this->position();
-      break;
-    default:
-      UNREACHABLE();
-      next_position = this->statement_position();
+    if (alignment == STATEMENT_ALIGNED) {
+      next_position = it.statement_position();
+    } else {
+      DCHECK(alignment == BREAK_POSITION_ALIGNED);
+      next_position = it.position();
     }
-    // Check if this break point is closer that what was previously found.
     if (position <= next_position && next_position - position < distance) {
-      closest_break_point = break_point();
+      closest_break = it.break_index();
       distance = next_position - position;
       // Check whether we can't get any closer.
       if (distance == 0) break;
     }
-    Next();
   }
 
-  // Move to the break point found.
-  Reset();
-  Next(closest_break_point);
+  Iterator it(debug_info, type);
+  it.SkipTo(closest_break);
+  return it.GetBreakLocation();
 }
 
 
-void BreakLocationIterator::Reset() {
-  // Create relocation iterators for the two code objects.
-  if (reloc_iterator_ != NULL) delete reloc_iterator_;
-  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
-  reloc_iterator_ = new RelocIterator(
-      debug_info_->code(),
-      ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
-  reloc_iterator_original_ = new RelocIterator(
-      debug_info_->original_code(),
-      ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
-
-  // Position at the first break point.
-  break_point_ = -1;
-  position_ = 1;
-  statement_position_ = 1;
-  Next();
-}
-
-
-bool BreakLocationIterator::Done() const {
-  return RinfoDone();
-}
-
-
-void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
+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_, code_position(),
-                           position(), statement_position(),
-                           break_point_object);
+  DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_,
+                           statement_position_, break_point_object);
 }
 
 
-void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
+void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
   // Clear the break point information.
-  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
+  DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object);
   // If there are no more break points here remove the debug break.
   if (!HasBreakPoint()) {
     ClearDebugBreak();
@@ -298,7 +253,7 @@ void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
 }
 
 
-void BreakLocationIterator::SetOneShot() {
+void BreakLocation::SetOneShot() {
   // Debugger statement always calls debugger. No need to modify it.
   if (IsDebuggerStatement()) return;
 
@@ -313,7 +268,7 @@ void BreakLocationIterator::SetOneShot() {
 }
 
 
-void BreakLocationIterator::ClearOneShot() {
+void BreakLocation::ClearOneShot() {
   // Debugger statement always calls debugger. No need to modify it.
   if (IsDebuggerStatement()) return;
 
@@ -329,7 +284,7 @@ void BreakLocationIterator::ClearOneShot() {
 }
 
 
-void BreakLocationIterator::SetDebugBreak() {
+void BreakLocation::SetDebugBreak() {
   // Debugger statement always calls debugger. No need to modify it.
   if (IsDebuggerStatement()) return;
 
@@ -339,7 +294,7 @@ void BreakLocationIterator::SetDebugBreak() {
   // handler as the handler and the function is the same.
   if (IsDebugBreak()) return;
 
-  if (RelocInfo::IsJSReturn(rmode())) {
+  if (IsExit()) {
     // Patch the frame exit code with a break point.
     SetDebugBreakAtReturn();
   } else if (IsDebugBreakSlot()) {
@@ -353,59 +308,48 @@ void BreakLocationIterator::SetDebugBreak() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreak() {
+void BreakLocation::ClearDebugBreak() {
   // Debugger statement always calls debugger. No need to modify it.
   if (IsDebuggerStatement()) return;
 
-  if (RelocInfo::IsJSReturn(rmode())) {
-    // Restore the frame exit code.
-    ClearDebugBreakAtReturn();
+  if (IsExit()) {
+    // Restore the frame exit code with a break point.
+    RestoreFromOriginal(Assembler::kJSReturnSequenceLength);
   } else if (IsDebugBreakSlot()) {
     // Restore the code in the break slot.
-    ClearDebugBreakAtSlot();
+    RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
   } else {
-    // Patch the IC call.
-    ClearDebugBreakAtIC();
+    // Restore the IC call.
+    rinfo().set_target_address(original_rinfo().target_address());
   }
   DCHECK(!IsDebugBreak());
 }
 
 
-bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
-  if (RelocInfo::IsConstructCall(original_rmode())) {
-    return true;
-  } else if (RelocInfo::IsCodeTarget(rmode())) {
+void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
+  memcpy(pc(), original_pc(), length_in_bytes);
+  CpuFeatures::FlushICache(pc(), length_in_bytes);
+}
+
+
+bool BreakLocation::IsStepInLocation() const {
+  if (IsConstructCall()) return true;
+  if (RelocInfo::IsCodeTarget(rmode())) {
     HandleScope scope(debug_info_->GetIsolate());
-    Address target = original_rinfo()->target_address();
-    Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
-    if (target_code->kind() == Code::STUB) {
-      return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
-    }
+    Handle<Code> target_code = CodeTarget();
     return target_code->is_call_stub();
   }
   return false;
 }
 
 
-// Check whether the break point is at a position which will exit the function.
-bool BreakLocationIterator::IsExit() const {
-  return (RelocInfo::IsJSReturn(rmode()));
-}
-
-
-bool BreakLocationIterator::HasBreakPoint() {
-  return debug_info_->HasBreakPoint(code_position());
-}
-
-
-// Check whether there is a debug break at the current position.
-bool BreakLocationIterator::IsDebugBreak() {
-  if (RelocInfo::IsJSReturn(rmode())) {
-    return IsDebugBreakAtReturn();
+bool BreakLocation::IsDebugBreak() const {
+  if (IsExit()) {
+    return rinfo().IsPatchedReturnSequence();
   } else if (IsDebugBreakSlot()) {
-    return IsDebugBreakAtSlot();
+    return rinfo().IsPatchedDebugBreakSlotSequence();
   } else {
-    return Debug::IsDebugBreak(rinfo()->target_address());
+    return Debug::IsDebugBreak(rinfo().target_address());
   }
 }
 
@@ -457,70 +401,53 @@ static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
 }
 
 
-void BreakLocationIterator::SetDebugBreakAtIC() {
+void BreakLocation::SetDebugBreakAtIC() {
   // Patch the original code with the current address as the current address
   // might have changed by the inline caching since the code was copied.
-  original_rinfo()->set_target_address(rinfo()->target_address());
+  original_rinfo().set_target_address(rinfo().target_address());
 
-  RelocInfo::Mode mode = rmode();
-  if (RelocInfo::IsCodeTarget(mode)) {
-    Address target = rinfo()->target_address();
-    Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
+  if (RelocInfo::IsCodeTarget(rmode_)) {
+    Handle<Code> target_code = CodeTarget();
 
     // Patch the code to invoke the builtin debug break function matching the
     // calling convention used by the call site.
-    Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
-    rinfo()->set_target_address(dbgbrk_code->entry());
+    Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_);
+    rinfo().set_target_address(debug_break_code->entry());
   }
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtIC() {
-  // Patch the code to the original invoke.
-  rinfo()->set_target_address(original_rinfo()->target_address());
+Handle<Object> BreakLocation::BreakPointObjects() const {
+  return debug_info_->GetBreakPointObjects(pc_offset_);
 }
 
 
-bool BreakLocationIterator::IsDebuggerStatement() {
-  return RelocInfo::DEBUG_BREAK == rmode();
+Handle<Code> BreakLocation::CodeTarget() const {
+  DCHECK(IsCodeTarget());
+  Address target = rinfo().target_address();
+  return Handle<Code>(Code::GetCodeFromTargetAddress(target));
 }
 
 
-bool BreakLocationIterator::IsDebugBreakSlot() {
-  return RelocInfo::DEBUG_BREAK_SLOT == rmode();
+Handle<Code> BreakLocation::OriginalCodeTarget() const {
+  DCHECK(IsCodeTarget());
+  Address target = original_rinfo().target_address();
+  return Handle<Code>(Code::GetCodeFromTargetAddress(target));
 }
 
 
-Object* BreakLocationIterator::BreakPointObjects() {
-  return debug_info_->GetBreakPointObjects(code_position());
+bool BreakLocation::Iterator::RinfoDone() const {
+  DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
+  return reloc_iterator_.done();
 }
 
 
-// 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 BreakLocationIterator::ClearAllDebugBreak() {
-  while (!Done()) {
-    ClearDebugBreak();
-    Next();
-  }
-}
-
-
-bool BreakLocationIterator::RinfoDone() const {
-  DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
-  return reloc_iterator_->done();
-}
-
-
-void BreakLocationIterator::RinfoNext() {
-  reloc_iterator_->next();
-  reloc_iterator_original_->next();
+void BreakLocation::Iterator::RinfoNext() {
+  reloc_iterator_.next();
+  reloc_iterator_original_.next();
 #ifdef DEBUG
-  DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
-  if (!reloc_iterator_->done()) {
-    DCHECK(rmode() == original_rmode());
-  }
+  DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
+  DCHECK(reloc_iterator_.done() || rmode() == original_rmode());
 #endif
 }
 
@@ -854,14 +781,14 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) {
   Handle<DebugInfo> debug_info = GetDebugInfo(shared);
 
   // Find the break point where execution has stopped.
-  BreakLocationIterator break_location_iterator(debug_info,
-                                                ALL_BREAK_LOCATIONS);
-  // pc points to the instruction after the current one, possibly a break
+  // PC points to the instruction after the current one, possibly a break
   // location as well. So the "- 1" to exclude it from the search.
-  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
+  Address call_pc = frame->pc() - 1;
+  BreakLocation break_location =
+      BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
 
   // Check whether step next reached a new statement.
-  if (!StepNextContinue(&break_location_iterator, frame)) {
+  if (!StepNextContinue(&break_location, frame)) {
     // Decrease steps left if performing multiple steps.
     if (thread_local_.step_count_ > 0) {
       thread_local_.step_count_--;
@@ -871,9 +798,8 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) {
   // If there is one or more real break points check whether any of these are
   // triggered.
   Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
-  if (break_location_iterator.HasBreakPoint()) {
-    Handle<Object> break_point_objects =
-        Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
+  if (break_location.HasBreakPoint()) {
+    Handle<Object> break_point_objects = break_location.BreakPointObjects();
     break_points_hit = CheckBreakPoints(break_point_objects);
   }
 
@@ -1058,11 +984,10 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
   DCHECK(*source_position >= 0);
 
   // Find the break point and change it.
-  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
-  it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
-  it.SetBreakPoint(break_point_object);
-
-  *source_position = it.statement_position();
+  BreakLocation location = BreakLocation::FromPosition(
+      debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
+  *source_position = location.statement_position();
+  location.SetBreakPoint(break_point_object);
 
   // At least one active break point now.
   return debug_info->GetBreakPointCount() > 0;
@@ -1078,11 +1003,12 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
   PrepareForBreakPoints();
 
   // Obtain shared function info for the function.
-  Object* result = FindSharedFunctionInfoInScript(script, *source_position);
+  Handle<Object> result =
+      FindSharedFunctionInfoInScript(script, *source_position);
   if (result->IsUndefined()) return false;
 
   // Make sure the function has set up the debug info.
-  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
+  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
   if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
     // Return if retrieving debug info failed.
     return false;
@@ -1102,12 +1028,12 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
   DCHECK(position >= 0);
 
   // Find the break point and change it.
-  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
-  it.FindBreakLocationFromPosition(position, alignment);
-  it.SetBreakPoint(break_point_object);
+  BreakLocation location = BreakLocation::FromPosition(
+      debug_info, SOURCE_BREAK_LOCATIONS, position, alignment);
+  location.SetBreakPoint(break_point_object);
 
-  position = (alignment == STATEMENT_ALIGNED) ? it.statement_position()
-                                              : it.position();
+  position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
+                                              : location.position();
 
   *source_position = position + shared->start_position();
 
@@ -1122,18 +1048,21 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
 
   DebugInfoListNode* node = debug_info_list_;
   while (node != NULL) {
-    Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
-                                                   break_point_object);
+    Handle<Object> result =
+        DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
     if (!result->IsUndefined()) {
       // Get information in the break point.
-      BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
+      Handle<BreakPointInfo> break_point_info =
+          Handle<BreakPointInfo>::cast(result);
       Handle<DebugInfo> debug_info = node->debug_info();
 
       // Find the break point and clear it.
-      BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
-      it.FindBreakLocationFromAddress(debug_info->code()->entry() +
-          break_point_info->code_position()->value());
-      it.ClearBreakPoint(break_point_object);
+      Address pc = debug_info->code()->entry() +
+                   break_point_info->code_position()->value();
+
+      BreakLocation location =
+          BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc);
+      location.ClearBreakPoint(break_point_object);
 
       // If there are no more break points left remove the debug info for this
       // function.
@@ -1148,15 +1077,17 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
 }
 
 
+// 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() {
-  DebugInfoListNode* node = debug_info_list_;
-  while (node != NULL) {
-    // Remove all debug break code.
-    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
-    it.ClearAllDebugBreak();
-    node = node->next();
+  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();
+    }
   }
-
   // Remove all debug info.
   while (debug_info_list_ != NULL) {
     RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
@@ -1179,10 +1110,9 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function,
   }
 
   // Flood the function with break points.
-  BreakLocationIterator it(GetDebugInfo(shared), type);
-  while (!it.Done()) {
-    it.SetOneShot();
-    it.Next();
+  for (BreakLocation::Iterator it(GetDebugInfo(shared), type); !it.Done();
+       it.Next()) {
+    it.GetBreakLocation().SetOneShot();
   }
 }
 
@@ -1341,64 +1271,49 @@ void Debug::PrepareStep(StepAction step_action,
   bool is_load_or_store = false;
   bool is_inline_cache_stub = false;
   bool is_at_restarted_function = false;
-  bool is_exit = false;
-  bool is_construct_call = false;
   Handle<Code> call_function_stub;
 
-  {
-    // Find the break location where execution has stopped.
-    DisallowHeapAllocation no_gc;
-    BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
-
-    // pc points to the instruction after the current one, possibly a break
-    // location as well. So the "- 1" to exclude it from the search.
-    it.FindBreakLocationFromAddress(frame->pc() - 1);
-
-    is_exit = it.IsExit();
-    is_construct_call = RelocInfo::IsConstructCall(it.rmode());
-
-    if (thread_local_.restarter_frame_function_pointer_ == NULL) {
-      if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
-        bool is_call_target = false;
-        Address target = it.rinfo()->target_address();
-        Code* code = Code::GetCodeFromTargetAddress(target);
-
-        is_call_target = code->is_call_stub();
-        is_inline_cache_stub = code->is_inline_cache_stub();
-        is_load_or_store = is_inline_cache_stub && !is_call_target;
-
-        // Check if target code is CallFunction stub.
-        Code* maybe_call_function_stub = code;
-        // If there is a breakpoint at this line look at the original code to
-        // check if it is a CallFunction stub.
-        if (it.IsDebugBreak()) {
-          Address original_target = it.original_rinfo()->target_address();
-          maybe_call_function_stub =
-              Code::GetCodeFromTargetAddress(original_target);
-        }
-        if ((maybe_call_function_stub->kind() == Code::STUB &&
-             CodeStub::GetMajorKey(maybe_call_function_stub) ==
-                 CodeStub::CallFunction) ||
-            maybe_call_function_stub->is_call_stub()) {
-          // Save reference to the code as we may need it to find out arguments
-          // count for 'step in' later.
-          call_function_stub = Handle<Code>(maybe_call_function_stub);
-        }
+  // 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, ALL_BREAK_LOCATIONS, call_pc);
+
+  if (thread_local_.restarter_frame_function_pointer_ == NULL) {
+    if (location.IsCodeTarget()) {
+      Handle<Code> target_code = location.CodeTarget();
+      is_inline_cache_stub = target_code->is_inline_cache_stub();
+      is_load_or_store = is_inline_cache_stub && !target_code->is_call_stub();
+
+      // Check if target code is CallFunction stub.
+      Handle<Code> maybe_call_function_stub = target_code;
+      // If there is a breakpoint at this line look at the original code to
+      // check if it is a CallFunction stub.
+      if (location.IsDebugBreak()) {
+        maybe_call_function_stub = location.OriginalCodeTarget();
+      }
+      if ((maybe_call_function_stub->kind() == Code::STUB &&
+           CodeStub::GetMajorKey(*maybe_call_function_stub) ==
+               CodeStub::CallFunction) ||
+          maybe_call_function_stub->is_call_stub()) {
+        // Save reference to the code as we may need it to find out arguments
+        // count for 'step in' later.
+        call_function_stub = maybe_call_function_stub;
       }
-    } else {
-      is_at_restarted_function = true;
     }
+  } else {
+    is_at_restarted_function = true;
   }
 
   // If this is the last break code target step out is the only possibility.
-  if (is_exit || step_action == StepOut) {
+  if (location.IsExit() || step_action == StepOut) {
     if (step_action == StepOut) {
       // Skip step_count frames starting with the current one.
       while (step_count-- > 0 && !frames_it.done()) {
         frames_it.Advance();
       }
     } else {
-      DCHECK(is_exit);
+      DCHECK(location.IsExit());
       frames_it.Advance();
     }
     // Skip builtin functions on the stack.
@@ -1415,7 +1330,7 @@ void Debug::PrepareStep(StepAction step_action,
       // Set target frame pointer.
       ActivateStepOut(frames_it.frame());
     }
-  } else if (!(is_inline_cache_stub || is_construct_call ||
+  } else if (!(is_inline_cache_stub || location.IsConstructCall() ||
                !call_function_stub.is_null() || is_at_restarted_function) ||
              step_action == StepNext || step_action == StepMin) {
     // Step next or step min.
@@ -1511,7 +1426,7 @@ void Debug::PrepareStep(StepAction step_action,
     // Step in through CallFunction stub should also be prepared by caller of
     // this function (Debug::PrepareStep) which should flood target function
     // with breakpoints.
-    DCHECK(is_construct_call || is_inline_cache_stub ||
+    DCHECK(location.IsConstructCall() || is_inline_cache_stub ||
            !call_function_stub.is_null() || is_at_restarted_function);
     ActivateStepIn(frame);
   }
@@ -1524,7 +1439,7 @@ void Debug::PrepareStep(StepAction step_action,
 // there will be several break points in the same statement when the code is
 // flooded with one-shot break points. This function helps to perform several
 // steps before reporting break back to the debugger.
-bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
+bool Debug::StepNextContinue(BreakLocation* break_location,
                              JavaScriptFrame* frame) {
   // StepNext and StepOut shouldn't bring us deeper in code, so last frame
   // shouldn't be a parent of current frame.
@@ -1543,11 +1458,11 @@ bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
   // statement is hit.
   if (step_action == StepNext || step_action == StepIn) {
     // Never continue if returning from function.
-    if (break_location_iterator->IsExit()) return false;
+    if (break_location->IsExit()) return false;
 
     // Continue if we are still on the same frame and in the same statement.
     int current_statement_position =
-        break_location_iterator->code()->SourceStatementPosition(frame->pc());
+        break_location->code()->SourceStatementPosition(frame->pc());
     return thread_local_.last_fp_ == frame->UnpaddedFP() &&
         thread_local_.last_statement_position_ == current_statement_position;
   }
@@ -1565,9 +1480,6 @@ bool Debug::IsDebugBreak(Address addr) {
 }
 
 
-
-
-
 // Simple function for returning the source positions for active break points.
 Handle<Object> Debug::GetSourceBreakLocations(
     Handle<SharedFunctionInfo> shared,
@@ -1655,15 +1567,12 @@ void Debug::ClearOneShot() {
   // The current implementation just runs through all the breakpoints. When the
   // last break point for a function is removed that function is automatically
   // removed from the list.
-
-  DebugInfoListNode* node = debug_info_list_;
-  while (node != NULL) {
-    BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
-    while (!it.Done()) {
-      it.ClearOneShot();
-      it.Next();
+  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();
     }
-    node = node->next();
   }
 }
 
@@ -2080,8 +1989,8 @@ void Debug::PrepareForBreakPoints() {
 }
 
 
-Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
-                                              int position) {
+Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
+                                                     int position) {
   // Iterate the heap looking for SharedFunctionInfo generated from the
   // script. The inner most SharedFunctionInfo containing the source position
   // for the requested break point is found.
@@ -2164,7 +2073,7 @@ Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
       }  // End for loop.
     }  // End no-allocation scope.
 
-    if (target.is_null()) return heap->undefined_value();
+    if (target.is_null()) return isolate_->factory()->undefined_value();
 
     // There will be at least one break point when we are done.
     has_break_points_ = true;
@@ -2180,11 +2089,11 @@ Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
       MaybeHandle<Code> maybe_result = target_function.is_null()
           ? Compiler::GetUnoptimizedCode(target)
           : Compiler::GetUnoptimizedCode(target_function);
-      if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
+      if (maybe_result.is_null()) return isolate_->factory()->undefined_value();
     }
   }  // End while loop.
 
-  return *target;
+  return target;
 }
 
 
index 3e2db60b8ea70e324884b085ef8068c374a38962..7209b53ad0027bdaa21a882f558bf24ffd6e2ef2 100644 (file)
@@ -66,83 +66,161 @@ enum BreakPositionAlignment {
 };
 
 
-// Class for iterating through the break points in a function and changing
-// them.
-class BreakLocationIterator {
+class BreakLocation {
  public:
-  explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
-                                 BreakLocatorType type);
-  virtual ~BreakLocationIterator();
-
-  void Next();
-  void Next(int count);
-  void FindBreakLocationFromAddress(Address pc);
-  void FindBreakLocationFromPosition(int position,
-      BreakPositionAlignment alignment);
-  void Reset();
-  bool Done() const;
+  // Find the break point at the supplied address, or the closest one before
+  // the address.
+  static BreakLocation FromAddress(Handle<DebugInfo> debug_info,
+                                   BreakLocatorType type, Address pc);
+
+  static void FromAddressSameStatement(Handle<DebugInfo> debug_info,
+                                       BreakLocatorType type, Address pc,
+                                       List<BreakLocation>* result_out);
+
+  static BreakLocation FromPosition(Handle<DebugInfo> debug_info,
+                                    BreakLocatorType type, int position,
+                                    BreakPositionAlignment alignment);
+
+  bool IsDebugBreak() const;
+  inline bool IsExit() const { return RelocInfo::IsJSReturn(rmode_); }
+  inline bool IsConstructCall() const {
+    return RelocInfo::IsConstructCall(rmode_);
+  }
+  inline bool IsCodeTarget() const { return RelocInfo::IsCodeTarget(rmode_); }
+
+  Handle<Code> CodeTarget() const;
+  Handle<Code> OriginalCodeTarget() const;
+
+  bool IsStepInLocation() const;
+  inline bool HasBreakPoint() const {
+    return debug_info_->HasBreakPoint(pc_offset_);
+  }
+
+  Handle<Object> BreakPointObjects() const;
+
   void SetBreakPoint(Handle<Object> break_point_object);
   void ClearBreakPoint(Handle<Object> break_point_object);
+
   void SetOneShot();
   void ClearOneShot();
-  bool IsStepInLocation(Isolate* isolate);
-  bool IsExit() const;
-  bool HasBreakPoint();
-  bool IsDebugBreak();
-  Object* BreakPointObjects();
-  void ClearAllDebugBreak();
-
 
-  inline int code_position() {
-    return static_cast<int>(pc() - debug_info_->code()->entry());
-  }
-  inline int break_point() { return break_point_; }
-  inline int position() { return position_; }
-  inline int statement_position() { return statement_position_; }
-  inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
-  inline Code* code() { return debug_info_->code(); }
-  inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
-  inline RelocInfo::Mode rmode() const {
-    return reloc_iterator_->rinfo()->rmode();
+  inline RelocInfo rinfo() const {
+    return RelocInfo(pc(), rmode(), data_, code());
   }
-  inline RelocInfo* original_rinfo() {
-    return reloc_iterator_original_->rinfo();
-  }
-  inline RelocInfo::Mode original_rmode() const {
-    return reloc_iterator_original_->rinfo()->rmode();
+
+  inline RelocInfo original_rinfo() const {
+    return RelocInfo(original_pc(), original_rmode(), original_data_,
+                     original_code());
   }
 
-  bool IsDebuggerStatement();
+  inline int position() const { return position_; }
+  inline int statement_position() const { return statement_position_; }
 
- protected:
-  bool RinfoDone() const;
-  void RinfoNext();
+  inline Address pc() const { return code()->entry() + pc_offset_; }
+  inline Address original_pc() const {
+    return original_code()->entry() + original_pc_offset_;
+  }
 
-  BreakLocatorType type_;
-  int break_point_;
-  int position_;
-  int statement_position_;
-  Handle<DebugInfo> debug_info_;
-  RelocIterator* reloc_iterator_;
-  RelocIterator* reloc_iterator_original_;
+  inline RelocInfo::Mode rmode() const { return rmode_; }
+  inline RelocInfo::Mode original_rmode() const { return original_rmode_; }
+
+  inline Code* code() const { return debug_info_->code(); }
+  inline Code* original_code() const { return debug_info_->original_code(); }
 
  private:
-  void SetDebugBreak();
-  void ClearDebugBreak();
+  BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
+                RelocInfo* original_rinfo, int position, int statement_position)
+      : debug_info_(debug_info),
+        pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())),
+        original_pc_offset_(static_cast<int>(
+            original_rinfo->pc() - debug_info->original_code()->entry())),
+        rmode_(rinfo->rmode()),
+        original_rmode_(original_rinfo->rmode()),
+        data_(rinfo->data()),
+        original_data_(original_rinfo->data()),
+        position_(position),
+        statement_position_(statement_position) {}
+
+  class Iterator {
+   public:
+    Iterator(Handle<DebugInfo> debug_info, BreakLocatorType type);
 
-  void SetDebugBreakAtIC();
-  void ClearDebugBreakAtIC();
+    BreakLocation GetBreakLocation() {
+      return BreakLocation(debug_info_, rinfo(), original_rinfo(), position(),
+                           statement_position());
+    }
 
-  bool IsDebugBreakAtReturn();
-  void SetDebugBreakAtReturn();
-  void ClearDebugBreakAtReturn();
+    inline bool Done() const { return RinfoDone(); }
+    void Next();
+
+    void SkipTo(int count) {
+      while (count-- > 0) Next();
+    }
+
+    inline RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
+    inline RelocInfo::Mode original_rmode() {
+      return reloc_iterator_.rinfo()->rmode();
+    }
 
-  bool IsDebugBreakSlot();
-  bool IsDebugBreakAtSlot();
+    inline RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
+    inline RelocInfo* original_rinfo() {
+      return reloc_iterator_original_.rinfo();
+    }
+
+    inline Address pc() { return rinfo()->pc(); }
+    inline Address original_pc() { return original_rinfo()->pc(); }
+
+    int break_index() const { return break_index_; }
+
+    inline int position() const { return position_; }
+    inline int statement_position() const { return statement_position_; }
+
+   private:
+    bool RinfoDone() const;
+    void RinfoNext();
+
+    Handle<DebugInfo> debug_info_;
+    BreakLocatorType type_;
+    RelocIterator reloc_iterator_;
+    RelocIterator reloc_iterator_original_;
+    int break_index_;
+    int position_;
+    int statement_position_;
+
+    DisallowHeapAllocation no_gc_;
+
+    DISALLOW_COPY_AND_ASSIGN(Iterator);
+  };
+
+  friend class Debug;
+
+  static int BreakIndexFromAddress(Handle<DebugInfo> debug_info,
+                                   BreakLocatorType type, Address pc);
+
+  void ClearDebugBreak();
+  void RestoreFromOriginal(int length_in_bytes);
+
+  void SetDebugBreak();
+  void SetDebugBreakAtReturn();
   void SetDebugBreakAtSlot();
-  void ClearDebugBreakAtSlot();
+  void SetDebugBreakAtIC();
 
-  DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
+  inline bool IsDebuggerStatement() const {
+    return RelocInfo::IsDebuggerStatement(rmode_);
+  }
+  inline bool IsDebugBreakSlot() const {
+    return RelocInfo::IsDebugBreakSlot(rmode_);
+  }
+
+  Handle<DebugInfo> debug_info_;
+  int pc_offset_;
+  int original_pc_offset_;
+  RelocInfo::Mode rmode_;
+  RelocInfo::Mode original_rmode_;
+  intptr_t data_;
+  intptr_t original_data_;
+  int position_;
+  int statement_position_;
 };
 
 
@@ -403,8 +481,7 @@ class Debug {
   void ClearStepping();
   void ClearStepOut();
   bool IsStepping() { return thread_local_.step_count_ > 0; }
-  bool StepNextContinue(BreakLocationIterator* break_location_iterator,
-                        JavaScriptFrame* frame);
+  bool StepNextContinue(BreakLocation* location, JavaScriptFrame* frame);
   bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
   void HandleStepIn(Handle<Object> function_obj, Handle<Object> holder,
                     Address fp, bool is_constructor);
@@ -422,13 +499,11 @@ class Debug {
   static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
 
   // This function is used in FunctionNameUsing* tests.
-  Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
+  Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
+                                                int position);
 
   // Returns true if the current stub call is patched to call the debugger.
   static bool IsDebugBreak(Address addr);
-  // Returns true if the current return statement has been patched to be
-  // a debugger breakpoint.
-  static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
 
   static Handle<Object> GetSourceBreakLocations(
       Handle<SharedFunctionInfo> shared,
index 511b1c868867d2a3a75955c42e060e8dcb903b62..4be27ceeabaaec16394ce63a4965e8ed0f563a42 100644 (file)
@@ -179,17 +179,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc_ + i) = *(instructions + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count);
-}
-
-
 // Patch the code at the current PC with a call to the target address.
 // Additional guard int3 instructions can be added if required.
 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
index 34b33b2c17f5ad194493ebbd323ce97315cdfbad..6d1c0f63840573d9c5b48b5c67e754c66961dc74 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
 
+// Patch the code at the current PC with a call to the target address.
+// Additional guard int3 instructions can be added if required.
+void PatchCodeWithCall(Address pc, Address target, int guard_bytes) {
+  // Call instruction takes up 5 bytes and int3 takes up one byte.
+  static const int kCallCodeSize = 5;
+  int code_size = kCallCodeSize + guard_bytes;
 
-// Patch the JS frame exit code with a debug break call. See
-// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-ia32.cc
-// for the precise return instructions sequence.
-void BreakLocationIterator::SetDebugBreakAtReturn() {
-  DCHECK(Assembler::kJSReturnSequenceLength >=
-         Assembler::kCallInstructionLength);
-  rinfo()->PatchCodeWithCall(
-      debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
-      Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
-}
+  // Create a code patcher.
+  CodePatcher patcher(pc, code_size);
 
+// Add a label for checking the size of the code used for returning.
+#ifdef DEBUG
+  Label check_codesize;
+  patcher.masm()->bind(&check_codesize);
+#endif
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceLength);
-}
+  // Patch the code.
+  patcher.masm()->call(target, RelocInfo::NONE32);
 
+  // Check that the size of the code generated is as expected.
+  DCHECK_EQ(kCallCodeSize,
+            patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 
-// A debug break in the frame exit code is identified by the JS frame exit code
-// having been patched with a call instruction.
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
+  // Add the requested number of int3 instructions after the call.
+  DCHECK_GE(guard_bytes, 0);
+  for (int i = 0; i < guard_bytes; i++) {
+    patcher.masm()->int3();
+  }
+
+  CpuFeatures::FlushICache(pc, code_size);
 }
 
 
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
+// Patch the JS frame exit code with a debug break call. See
+// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-ia32.cc
+// for the precise return instructions sequence.
+void BreakLocation::SetDebugBreakAtReturn() {
+  DCHECK(Assembler::kJSReturnSequenceLength >=
+         Assembler::kCallInstructionLength);
+  PatchCodeWithCall(
+      pc(), debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
+      Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
 
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   Isolate* isolate = debug_info_->GetIsolate();
-  rinfo()->PatchCodeWithCall(
-      isolate->builtins()->Slot_DebugBreak()->entry(),
+  PatchCodeWithCall(
+      pc(), isolate->builtins()->Slot_DebugBreak()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
index 1fdb3e97e5a18cd83f6548084c56bf28ceefabc9..3e98222fc6394cc8d4aeb2cf68b305fc69777fd6 100644 (file)
@@ -307,8 +307,8 @@ Address RelocInfo::call_address() {
   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   // The pc_ offset of 0 assumes mips patched return sequence per
-  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
-  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  // debug-mips.cc BreakLocation::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocation::SetDebugBreakAtSlot().
   return Assembler::target_address_at(pc_, host_);
 }
 
@@ -317,8 +317,8 @@ void RelocInfo::set_call_address(Address target) {
   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   // The pc_ offset of 0 assumes mips patched return sequence per
-  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
-  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  // debug-mips.cc BreakLocation::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocation::SetDebugBreakAtSlot().
   Assembler::set_target_address_at(pc_, host_, target);
   if (host() != NULL) {
     Object* target_code = Code::GetCodeFromTargetAddress(target);
index 13dd0cd2f9ec8a07ecb1bbbdb01d070a942566bf..e005f19712f74730c2489df2d741a810c8b920cc 100644 (file)
@@ -214,27 +214,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-// Patch the code at the current address with the supplied instructions.
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  Instr* pc = reinterpret_cast<Instr*>(pc_);
-  Instr* instr = reinterpret_cast<Instr*>(instructions);
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc + i) = *(instr + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  // Patch the code at the current address with a call to the target.
-  UNIMPLEMENTED_MIPS();
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand.
 // See assembler-mips-inl.h for inlined constructors.
index 296311273081329ac8401ce96b91b80f68e5bcae..8f2e9983d533f5b17729cc8249b64e54c1d6a8e3 100644 (file)
@@ -591,6 +591,8 @@ class Assembler : public AssemblerBase {
   // Number of instructions used for the JS return sequence. The constant is
   // used by the debugger to patch the JS return sequence.
   static const int kJSReturnSequenceInstructions = 7;
+  static const int kJSReturnSequenceLength =
+      kJSReturnSequenceInstructions * kInstrSize;
   static const int kDebugBreakSlotInstructions = 4;
   static const int kDebugBreakSlotLength =
       kDebugBreakSlotInstructions * kInstrSize;
index 5b3591c81b3326aca58ccc98525f20f708e59900..a14fac8d064ae5452dfe278ce0430b74b6076393 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtReturn() {
+void BreakLocation::SetDebugBreakAtReturn() {
   // Mips return sequence:
   // mov sp, fp
   // lw fp, sp(0)
@@ -31,7 +26,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 
   // Make sure this constant matches the number if instrucntions we emit.
   DCHECK(Assembler::kJSReturnSequenceInstructions == 7);
-  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
+  CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions);
   // li and Call pseudo-instructions emit two instructions each.
   patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int32_t>(
       debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry())));
@@ -45,29 +40,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 }
 
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceInstructions);
-}
-
-
-// A debug break in the exit code is identified by the JS frame exit code
-// having been patched with li/call psuedo-instrunction (liu/ori/jalr).
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   // Patch the code changing the debug break slot code from:
   //   nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
@@ -77,20 +50,13 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   // to a call to the debug break slot code.
   //   li t9, address   (lui t9 / ori t9 instruction pair)
   //   call t9          (jalr t9 / nop instruction pair)
-  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+  CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions);
   patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int32_t>(
       debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry())));
   patcher.masm()->Call(v8::internal::t9);
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kDebugBreakSlotInstructions);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 
index dede337e2a053d525958398e30cca16b0f1798a7..f1e3e587efb3b985d38f39c451b38883dac5527a 100644 (file)
@@ -301,8 +301,8 @@ Address RelocInfo::call_address() {
   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   // The pc_ offset of 0 assumes mips patched return sequence per
-  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
-  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  // debug-mips.cc BreakLocation::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocation::SetDebugBreakAtSlot().
   return Assembler::target_address_at(pc_, host_);
 }
 
@@ -311,8 +311,8 @@ void RelocInfo::set_call_address(Address target) {
   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   // The pc_ offset of 0 assumes mips patched return sequence per
-  // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or
-  // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  // debug-mips.cc BreakLocation::SetDebugBreakAtReturn(), or
+  // debug break slot per BreakLocation::SetDebugBreakAtSlot().
   Assembler::set_target_address_at(pc_, host_, target);
   if (host() != NULL) {
     Object* target_code = Code::GetCodeFromTargetAddress(target);
index 9fdcf759449fe1158db28097bbb495a8bd696713..8a20f26c19992b00dafd967850ca80437f300231 100644 (file)
@@ -191,27 +191,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-// Patch the code at the current address with the supplied instructions.
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  Instr* pc = reinterpret_cast<Instr*>(pc_);
-  Instr* instr = reinterpret_cast<Instr*>(instructions);
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc + i) = *(instr + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  // Patch the code at the current address with a call to the target.
-  UNIMPLEMENTED_MIPS();
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand.
 // See assembler-mips-inl.h for inlined constructors.
index 09f29c2e8131c829bef243301796ef7874eed226..fbcf59a98245ea61d67205abb445093fd92746c9 100644 (file)
@@ -585,6 +585,8 @@ class Assembler : public AssemblerBase {
   // Number of instructions used for the JS return sequence. The constant is
   // used by the debugger to patch the JS return sequence.
   static const int kJSReturnSequenceInstructions = 7;
+  static const int kJSReturnSequenceLength =
+      kJSReturnSequenceInstructions * kInstrSize;
   static const int kDebugBreakSlotInstructions = 6;
   static const int kDebugBreakSlotLength =
       kDebugBreakSlotInstructions * kInstrSize;
index 0bb0c4a802da07a9e413924291d16ce1b43a4cb0..8ef247d8c978adf72dae81a23b2e46215748c460 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtReturn() {
+void BreakLocation::SetDebugBreakAtReturn() {
   // Mips return sequence:
   // mov sp, fp
   // lw fp, sp(0)
@@ -31,7 +26,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 
   // Make sure this constant matches the number if instructions we emit.
   DCHECK(Assembler::kJSReturnSequenceInstructions == 7);
-  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
+  CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions);
   // li and Call pseudo-instructions emit 6 + 2 instructions.
   patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int64_t>(
       debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry())),
@@ -44,29 +39,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 }
 
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceInstructions);
-}
-
-
-// A debug break in the exit code is identified by the JS frame exit code
-// having been patched with li/call psuedo-instrunction (liu/ori/jalr).
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   // Patch the code changing the debug break slot code from:
   //   nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
@@ -78,7 +51,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   // to a call to the debug break slot code.
   //   li t9, address   (4-instruction sequence on mips64)
   //   call t9          (jalr t9 / nop instruction pair)
-  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+  CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions);
   patcher.masm()->li(v8::internal::t9,
       Operand(reinterpret_cast<int64_t>(
           debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry())),
@@ -87,13 +60,6 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kDebugBreakSlotInstructions);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 
index ff6b7a12a7d6777644f9dcc779f7a3d16d69021b..172cc2ae73888001e36d04d752ac0e898bad80e2 100644 (file)
@@ -16726,12 +16726,14 @@ void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
 
 
 // Get the break point objects for a code position.
-Object* DebugInfo::GetBreakPointObjects(int code_position) {
+Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
   Object* break_point_info = GetBreakPointInfo(code_position);
   if (break_point_info->IsUndefined()) {
-    return GetHeap()->undefined_value();
+    return GetIsolate()->factory()->undefined_value();
   }
-  return BreakPointInfo::cast(break_point_info)->break_point_objects();
+  return Handle<Object>(
+      BreakPointInfo::cast(break_point_info)->break_point_objects(),
+      GetIsolate());
 }
 
 
@@ -16750,22 +16752,22 @@ int DebugInfo::GetBreakPointCount() {
 }
 
 
-Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
-                                      Handle<Object> break_point_object) {
-  Heap* heap = debug_info->GetHeap();
-  if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
-  for (int i = 0; i < debug_info->break_points()->length(); i++) {
-    if (!debug_info->break_points()->get(i)->IsUndefined()) {
-      Handle<BreakPointInfo> break_point_info =
-          Handle<BreakPointInfo>(BreakPointInfo::cast(
-              debug_info->break_points()->get(i)));
-      if (BreakPointInfo::HasBreakPointObject(break_point_info,
-                                              break_point_object)) {
-        return *break_point_info;
+Handle<Object> DebugInfo::FindBreakPointInfo(
+    Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
+  Isolate* isolate = debug_info->GetIsolate();
+  if (!debug_info->break_points()->IsUndefined()) {
+    for (int i = 0; i < debug_info->break_points()->length(); i++) {
+      if (!debug_info->break_points()->get(i)->IsUndefined()) {
+        Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
+            BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
+        if (BreakPointInfo::HasBreakPointObject(break_point_info,
+                                                break_point_object)) {
+          return break_point_info;
+        }
       }
     }
   }
-  return heap->undefined_value();
+  return isolate->factory()->undefined_value();
 }
 
 
index b8b6874cfc0ceb0bc9a6118a6783177ae2bb2561..8ddcd8b04fc7a8d0cf4171f598cf2ba50ecfc65f 100644 (file)
@@ -10773,10 +10773,10 @@ class DebugInfo: public Struct {
                             int source_position, int statement_position,
                             Handle<Object> break_point_object);
   // Get the break point objects for a code position.
-  Object* GetBreakPointObjects(int code_position);
+  Handle<Object> GetBreakPointObjects(int code_position);
   // Find the break point info holding this break point object.
-  static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
-                                    Handle<Object> break_point_object);
+  static Handle<Object> FindBreakPointInfo(Handle<DebugInfo> debug_info,
+                                           Handle<Object> break_point_object);
   // Get the number of break points for this function.
   int GetBreakPointCount();
 
index 7ae89883400dad51b56bfdc14322bf1a610f8db0..ec8d61926f87c6ba46618d5f4c4be5a00052e656 100644 (file)
@@ -242,8 +242,8 @@ Address RelocInfo::call_address() {
   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
   // The pc_ offset of 0 assumes patched return sequence per
-  // BreakLocationIterator::SetDebugBreakAtReturn(), or debug break
-  // slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  // BreakLocation::SetDebugBreakAtReturn(), or debug break
+  // slot per BreakLocation::SetDebugBreakAtSlot().
   return Assembler::target_address_at(pc_, host_);
 }
 
@@ -285,7 +285,7 @@ void RelocInfo::WipeOut() {
 bool RelocInfo::IsPatchedReturnSequence() {
   //
   // The patched return sequence is defined by
-  // BreakLocationIterator::SetDebugBreakAtReturn()
+  // BreakLocation::SetDebugBreakAtReturn()
   // FIXED_SEQUENCE
 
   Instr instr0 = Assembler::instr_at(pc_);
index 021ae1d11165814b3abe7d27559e245dd048bba4..671133f998eb465d942a241b042559fe761a9cf5 100644 (file)
@@ -160,27 +160,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  Instr* pc = reinterpret_cast<Instr*>(pc_);
-  Instr* instr = reinterpret_cast<Instr*>(instructions);
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc + i) = *(instr + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  // Patch the code at the current address with a call to the target.
-  UNIMPLEMENTED();
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand
 // See assembler-ppc-inl.h for inlined constructors
index 982f126169461bb0356b9f0f806f12bbc938a561..27af916db4e59c9ce4acd8c078c5549d772cba5b 100644 (file)
@@ -659,9 +659,11 @@ class Assembler : public AssemblerBase {
   //   blrl
   static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
 
-  // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn()
+  // This is the length of the BreakLocation::SetDebugBreakAtReturn()
   // code patch FIXED_SEQUENCE
   static const int kJSReturnSequenceInstructions = kMovInstructions + 3;
+  static const int kJSReturnSequenceLength =
+      kJSReturnSequenceInstructions * kInstrSize;
 
   // This is the length of the code sequence from SetDebugBreakAtSlot()
   // FIXED_SEQUENCE
index f2c658ed697293b90b5f9f06b8c3262c9351b147..f59f6371de4f22d75dccc73ed25e1b2b6d814be5 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtReturn() {
+void BreakLocation::SetDebugBreakAtReturn() {
   // Patch the code changing the return from JS function sequence from
   //
   //   LeaveFrame
@@ -31,7 +26,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
   //   blrl
   //   bkpt
   //
-  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
+  CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions);
   Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm());
   patcher.masm()->mov(
       v8::internal::r0,
@@ -45,29 +40,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 }
 
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceInstructions);
-}
-
-
-// A debug break in the frame exit code is identified by the JS frame exit code
-// having been patched with a call instruction.
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
-}
-
-
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
-}
-
-
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   // Patch the code changing the debug break slot code from
   //
@@ -83,7 +56,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
   //   mtlr r0
   //   blrl
   //
-  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+  CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions);
   Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm());
   patcher.masm()->mov(
       v8::internal::r0,
@@ -94,13 +67,6 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kDebugBreakSlotInstructions);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 
index 9d69294fea88da0512ec20a7945e42796e7a762e..7c5546913756762c181d94dc9d85f2665948910a 100644 (file)
@@ -1164,18 +1164,19 @@ class ScopeIterator {
     if (!ignore_nested_scopes) {
       Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
 
-      // Find the break point where execution has stopped.
-      BreakLocationIterator break_location_iterator(debug_info,
-                                                    ALL_BREAK_LOCATIONS);
-      // pc points to the instruction after the current one, possibly a break
+      // PC points to the instruction after the current one, possibly a break
       // location as well. So the "- 1" to exclude it from the search.
-      break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
+      Address call_pc = frame->pc() - 1;
+
+      // Find the break point where execution has stopped.
+      BreakLocation location =
+          BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
 
       // Within the return sequence at the moment it is not possible to
       // get a source position which is consistent with the current scope chain.
       // Thus all nested with, catch and block contexts are skipped and we only
       // provide the function scope.
-      ignore_nested_scopes = break_location_iterator.IsExit();
+      ignore_nested_scopes = location.IsExit();
     }
 
     if (ignore_nested_scopes) {
@@ -1559,18 +1560,19 @@ RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
 
   Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
 
-  int len = 0;
-  Handle<JSArray> array(isolate->factory()->NewJSArray(10));
-  // Find the break point where execution has stopped.
-  BreakLocationIterator break_location_iterator(debug_info,
-                                                ALL_BREAK_LOCATIONS);
+  // Find range of break points starting from the break point where execution
+  // has stopped.
+  Address call_pc = frame->pc() - 1;
+  List<BreakLocation> locations;
+  BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS,
+                                          call_pc, &locations);
 
-  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
-  int current_statement_pos = break_location_iterator.statement_position();
+  Handle<JSArray> array = isolate->factory()->NewJSArray(locations.length());
 
-  while (!break_location_iterator.Done()) {
+  int index = 0;
+  for (BreakLocation location : locations) {
     bool accept;
-    if (break_location_iterator.pc() > frame->pc()) {
+    if (location.pc() > frame->pc()) {
       accept = true;
     } else {
       StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
@@ -1587,20 +1589,15 @@ RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
       }
     }
     if (accept) {
-      if (break_location_iterator.IsStepInLocation(isolate)) {
-        Smi* position_value = Smi::FromInt(break_location_iterator.position());
+      if (location.IsStepInLocation()) {
+        Smi* position_value = Smi::FromInt(location.position());
         RETURN_FAILURE_ON_EXCEPTION(
             isolate, JSObject::SetElement(
-                         array, len, Handle<Object>(position_value, isolate),
+                         array, index, Handle<Object>(position_value, isolate),
                          NONE, SLOPPY));
-        len++;
+        index++;
       }
     }
-    // Advance iterator.
-    break_location_iterator.Next();
-    if (current_statement_pos != break_location_iterator.statement_position()) {
-      break;
-    }
   }
   return *array;
 }
index 118018fd1960dfcdbcb4673d8da0cd03e0e0364a..697a6fa82252421f44f3ff10293337898c228076 100644 (file)
@@ -107,50 +107,6 @@ void CpuFeatures::PrintFeatures() {
 }
 
 
-// -----------------------------------------------------------------------------
-// Implementation of RelocInfo
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard int3 instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  int code_size = Assembler::kCallSequenceLength + guard_bytes;
-
-  // Create a code patcher.
-  CodePatcher patcher(pc_, code_size);
-
-  // Add a label for checking the size of the code used for returning.
-#ifdef DEBUG
-  Label check_codesize;
-  patcher.masm()->bind(&check_codesize);
-#endif
-
-  // Patch the code.
-  patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(target),
-                       Assembler::RelocInfoNone());
-  patcher.masm()->call(kScratchRegister);
-
-  // Check that the size of the code generated is as expected.
-  DCHECK_EQ(Assembler::kCallSequenceLength,
-            patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
-
-  // Add the requested number of int3 instructions after the call.
-  for (int i = 0; i < guard_bytes; i++) {
-    patcher.masm()->int3();
-  }
-}
-
-
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc_ + i) = *(instructions + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count);
-}
-
-
 // -----------------------------------------------------------------------------
 // Register constants.
 
index c8f9456f75638501c74ba0d70b0ab62a25290cd9..ee2b5c526a449d74ed1fb30a9333aedfde2ab55d 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn()  {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
+// Patch the code at the current PC with a call to the target address.
+// Additional guard int3 instructions can be added if required.
+void PatchCodeWithCall(Address pc, Address target, int guard_bytes) {
+  int code_size = Assembler::kCallSequenceLength + guard_bytes;
 
+  // Create a code patcher.
+  CodePatcher patcher(pc, code_size);
 
-// Patch the JS frame exit code with a debug break call. See
-// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc
-// for the precise return instructions sequence.
-void BreakLocationIterator::SetDebugBreakAtReturn()  {
-  DCHECK(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength);
-  rinfo()->PatchCodeWithCall(
-      debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
-      Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength);
-}
+// Add a label for checking the size of the code used for returning.
+#ifdef DEBUG
+  Label check_codesize;
+  patcher.masm()->bind(&check_codesize);
+#endif
 
+  // Patch the code.
+  patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(target),
+                       Assembler::RelocInfoNone());
+  patcher.masm()->call(kScratchRegister);
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceLength);
-}
+  // Check that the size of the code generated is as expected.
+  DCHECK_EQ(Assembler::kCallSequenceLength,
+            patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 
+  // Add the requested number of int3 instructions after the call.
+  for (int i = 0; i < guard_bytes; i++) {
+    patcher.masm()->int3();
+  }
 
-// A debug break in the frame exit code is identified by the JS frame exit code
-// having been patched with a call instruction.
-bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
+  CpuFeatures::FlushICache(pc, code_size);
 }
 
 
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
+// Patch the JS frame exit code with a debug break call. See
+// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc
+// for the precise return instructions sequence.
+void BreakLocation::SetDebugBreakAtReturn() {
+  DCHECK(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength);
+  PatchCodeWithCall(
+      pc(), debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
+      Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength);
 }
 
 
-void BreakLocationIterator::SetDebugBreakAtSlot() {
+void BreakLocation::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCodeWithCall(
-      debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(),
+  PatchCodeWithCall(
+      pc(), debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength);
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 
index f2db021b69dba779676100807790a57f15003880..0d0a49435840d99422bf5d1aacd3b4d753a66500 100644 (file)
@@ -102,48 +102,6 @@ bool RelocInfo::IsInConstantPool() {
 }
 
 
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
-  // Patch the code at the current address with the supplied instructions.
-  for (int i = 0; i < instruction_count; i++) {
-    *(pc_ + i) = *(instructions + i);
-  }
-
-  // Indicate that code has changed.
-  CpuFeatures::FlushICache(pc_, instruction_count);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard int3 instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
-  // Call instruction takes up 5 bytes and int3 takes up one byte.
-  static const int kCallCodeSize = 5;
-  int code_size = kCallCodeSize + guard_bytes;
-
-  // Create a code patcher.
-  CodePatcher patcher(pc_, code_size);
-
-  // Add a label for checking the size of the code used for returning.
-#ifdef DEBUG
-  Label check_codesize;
-  patcher.masm()->bind(&check_codesize);
-#endif
-
-  // Patch the code.
-  patcher.masm()->call(target, RelocInfo::NONE32);
-
-  // Check that the size of the code generated is as expected.
-  DCHECK_EQ(kCallCodeSize,
-            patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
-
-  // Add the requested number of int3 instructions after the call.
-  DCHECK_GE(guard_bytes, 0);
-  for (int i = 0; i < guard_bytes; i++) {
-    patcher.masm()->int3();
-  }
-}
-
-
 // -----------------------------------------------------------------------------
 // Implementation of Operand
 
index cdbcbad966254ee8625889a53280f10616769b1c..8da8c2f063b7ae2731998c668da7b9ee12da0592 100644 (file)
 namespace v8 {
 namespace internal {
 
-bool BreakLocationIterator::IsDebugBreakAtReturn() {
-  return Debug::IsDebugBreakAtReturn(rinfo());
-}
+// Patch the code at the current PC with a call to the target address.
+// Additional guard int3 instructions can be added if required.
+void RelocInfo::PatchCodeWithCall(Address pc, Address target, int guard_bytes) {
+  // Call instruction takes up 5 bytes and int3 takes up one byte.
+  static const int kCallCodeSize = 5;
+  int code_size = kCallCodeSize + guard_bytes;
 
+  // Create a code patcher.
+  CodePatcher patcher(pc, code_size);
 
-// Patch the JS frame exit code with a debug break call. See
-// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x87.cc
-// for the precise return instructions sequence.
-void BreakLocationIterator::SetDebugBreakAtReturn() {
-  DCHECK(Assembler::kJSReturnSequenceLength >=
-         Assembler::kCallInstructionLength);
-  rinfo()->PatchCodeWithCall(
-      debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
-      Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
-}
+// Add a label for checking the size of the code used for returning.
+#ifdef DEBUG
+  Label check_codesize;
+  patcher.masm()->bind(&check_codesize);
+#endif
 
+  // Patch the code.
+  patcher.masm()->call(target, RelocInfo::NONE32);
 
-// Restore the JS frame exit code.
-void BreakLocationIterator::ClearDebugBreakAtReturn() {
-  rinfo()->PatchCode(original_rinfo()->pc(),
-                     Assembler::kJSReturnSequenceLength);
-}
+  // Check that the size of the code generated is as expected.
+  DCHECK_EQ(kCallCodeSize,
+            patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
 
+  // Add the requested number of int3 instructions after the call.
+  DCHECK_GE(guard_bytes, 0);
+  for (int i = 0; i < guard_bytes; i++) {
+    patcher.masm()->int3();
+  }
 
-// A debug break in the frame exit code is identified by the JS frame exit code
-// having been patched with a call instruction.
-bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
-  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
-  return rinfo->IsPatchedReturnSequence();
+  CpuFeatures::FlushICache(pc, code_size);
 }
 
 
-bool BreakLocationIterator::IsDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  // Check whether the debug break slot instructions have been patched.
-  return rinfo()->IsPatchedDebugBreakSlotSequence();
+// Patch the JS frame exit code with a debug break call. See
+// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x87.cc
+// for the precise return instructions sequence.
+void BreakLocation::SetDebugBreakAtReturn() {
+  DCHECK(Assembler::kJSReturnSequenceLength >=
+         Assembler::kCallInstructionLength);
+  PatchCodeWithCall(
+      pc(), debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(),
+      Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
 }
 
 
 void BreakLocationIterator::SetDebugBreakAtSlot() {
   DCHECK(IsDebugBreakSlot());
   Isolate* isolate = debug_info_->GetIsolate();
-  rinfo()->PatchCodeWithCall(
-      isolate->builtins()->Slot_DebugBreak()->entry(),
+  rinfo().PatchCodeWithCall(
+      pc(), isolate->builtins()->Slot_DebugBreak()->entry(),
       Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
 }
 
 
-void BreakLocationIterator::ClearDebugBreakAtSlot() {
-  DCHECK(IsDebugBreakSlot());
-  rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
-}
-
-
 #define __ ACCESS_MASM(masm)
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
index a4a993ad30c1cd8ea5b75c0e2b062fb0cb651eb1..2bbadc3ec5e27db2864b4be5f0888ac386233a50 100644 (file)
@@ -416,7 +416,7 @@ void CheckDebuggerUnloaded(bool check_functions) {
           if (RelocInfo::IsCodeTarget(rmode)) {
             CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
           } else if (RelocInfo::IsJSReturn(rmode)) {
-            CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
+            CHECK(!it.rinfo()->IsPatchedReturnSequence());
           }
         }
       }
@@ -437,47 +437,36 @@ static void CheckDebuggerUnloaded(bool check_functions = false) {
 }
 
 
-// Inherit from BreakLocationIterator to get access to protected parts for
-// testing.
-class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
- public:
-  explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
-    : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
-  v8::internal::RelocIterator* it() { return reloc_iterator_; }
-  v8::internal::RelocIterator* it_original() {
-    return reloc_iterator_original_;
-  }
-};
-
-
 // Compile a function, set a break point and check that the call at the break
 // location in the code is the expected debug_break function.
 void CheckDebugBreakFunction(DebugLocalContext* env,
                              const char* source, const char* name,
                              int position, v8::internal::RelocInfo::Mode mode,
                              Code* debug_break) {
-  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
+  i::Debug* debug = CcTest::i_isolate()->debug();
 
   // Create function and set the break point.
-  Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
-      *CompileFunction(env, source, name));
+  Handle<i::JSFunction> fun =
+      v8::Utils::OpenHandle(*CompileFunction(env, source, name));
   int bp = SetBreakPoint(fun, position);
 
   // Check that the debug break function is as expected.
-  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
+  Handle<i::SharedFunctionInfo> shared(fun->shared());
   CHECK(Debug::HasDebugInfo(shared));
-  TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
-  it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
-  v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
-  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
-    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
+  i::BreakLocation location = i::BreakLocation::FromPosition(
+      Debug::GetDebugInfo(shared), i::SOURCE_BREAK_LOCATIONS, position,
+      i::STATEMENT_ALIGNED);
+  i::RelocInfo::Mode actual_mode = location.rmode();
+  if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
+    actual_mode = i::RelocInfo::CODE_TARGET;
   }
   CHECK_EQ(mode, actual_mode);
-  if (mode != v8::internal::RelocInfo::JS_RETURN) {
-    CHECK_EQ(debug_break,
-        Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
+  if (mode != i::RelocInfo::JS_RETURN) {
+    CHECK_EQ(debug_break, *location.CodeTarget());
   } else {
-    CHECK(Debug::IsDebugBreakAtReturn(it1.it()->rinfo()));
+    i::RelocInfo rinfo = location.rinfo();
+    CHECK(i::RelocInfo::IsJSReturn(rinfo.rmode()));
+    CHECK(rinfo.IsPatchedReturnSequence());
   }
 
   // Clear the break point and check that the debug break function is no longer
@@ -485,15 +474,17 @@ void CheckDebugBreakFunction(DebugLocalContext* env,
   ClearBreakPoint(bp);
   CHECK(!debug->HasDebugInfo(shared));
   CHECK(debug->EnsureDebugInfo(shared, fun));
-  TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
-  it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
-  actual_mode = it2.it()->rinfo()->rmode();
-  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
-    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
+  location = i::BreakLocation::FromPosition(Debug::GetDebugInfo(shared),
+                                            i::SOURCE_BREAK_LOCATIONS, position,
+                                            i::STATEMENT_ALIGNED);
+  actual_mode = location.rmode();
+  if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
+    actual_mode = i::RelocInfo::CODE_TARGET;
   }
   CHECK_EQ(mode, actual_mode);
-  if (mode == v8::internal::RelocInfo::JS_RETURN) {
-    CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo()));
+  if (mode == i::RelocInfo::JS_RETURN) {
+    i::RelocInfo rinfo = location.rinfo();
+    CHECK(!rinfo.IsPatchedReturnSequence());
   }
 }
 
index 24f9c73532fee85aca402c808732841f0528b78b..ae8e77d745b14f07b30028fb49d352f336c4aa4e 100644 (file)
@@ -81,11 +81,9 @@ static void CheckFunctionName(v8::Handle<v8::Script> script,
 
   // Obtain SharedFunctionInfo for the function.
   isolate->debug()->PrepareForBreakPoints();
-  Object* shared_func_info_ptr =
-      isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos);
-  CHECK(shared_func_info_ptr != CcTest::heap()->undefined_value());
-  Handle<SharedFunctionInfo> shared_func_info(
-      SharedFunctionInfo::cast(shared_func_info_ptr));
+  Handle<SharedFunctionInfo> shared_func_info =
+      Handle<SharedFunctionInfo>::cast(
+          isolate->debug()->FindSharedFunctionInfoInScript(i_script, func_pos));
 
   // Verify inferred function name.
   SmartArrayPointer<char> inferred_name =