Index: src/debug.cc |
=================================================================== |
--- src/debug.cc (revision 4816) |
+++ src/debug.cc (working copy) |
@@ -129,10 +129,14 @@ |
ASSERT(statement_position_ >= 0); |
} |
- // Check for breakable code target. Look in the original code as setting |
- // break points can cause the code targets in the running (debugged) code to |
- // be of a different kind than in the original code. |
- if (RelocInfo::IsCodeTarget(rmode())) { |
+ if (IsDebugBreakSlot()) { |
+ // There is always a possible break point at a debug break slot. |
+ break_point_++; |
+ return; |
+ } else if (RelocInfo::IsCodeTarget(rmode())) { |
+ // Check for breakable code target. Look in the original code as setting |
+ // break points can cause the code targets in the running (debugged) code |
+ // to be of a different kind than in the original code. |
Address target = original_rinfo()->target_address(); |
Code* code = Code::GetCodeFromTargetAddress(target); |
if ((code->is_inline_cache_stub() && |
@@ -329,6 +333,9 @@ |
if (RelocInfo::IsJSReturn(rmode())) { |
// Patch the frame exit code with a break point. |
SetDebugBreakAtReturn(); |
+ } else if (IsDebugBreakSlot()) { |
+ // Patch the code in the break slot. |
+ SetDebugBreakAtSlot(); |
} else { |
// Patch the IC call. |
SetDebugBreakAtIC(); |
@@ -346,6 +353,9 @@ |
if (RelocInfo::IsJSReturn(rmode())) { |
// Restore the frame exit code. |
ClearDebugBreakAtReturn(); |
+ } else if (IsDebugBreakSlot()) { |
+ // Restore the code in the break slot. |
+ ClearDebugBreakAtSlot(); |
} else { |
// Patch the IC call. |
ClearDebugBreakAtIC(); |
@@ -417,6 +427,8 @@ |
bool BreakLocationIterator::IsDebugBreak() { |
if (RelocInfo::IsJSReturn(rmode())) { |
return IsDebugBreakAtReturn(); |
+ } else if (IsDebugBreakSlot()) { |
+ return IsDebugBreakAtSlot(); |
} else { |
return Debug::IsDebugBreak(rinfo()->target_address()); |
} |
@@ -478,6 +490,11 @@ |
} |
+bool BreakLocationIterator::IsDebugBreakSlot() { |
+ return RelocInfo::DEBUG_BREAK_SLOT == rmode(); |
+} |
+ |
+ |
Object* BreakLocationIterator::BreakPointObjects() { |
return debug_info_->GetBreakPointObjects(code_position()); |
} |
@@ -573,6 +590,7 @@ |
Handle<Context> Debug::debug_context_ = Handle<Context>(); |
Code* Debug::debug_break_return_ = NULL; |
+Code* Debug::debug_break_slot_ = NULL; |
void ScriptCache::Add(Handle<Script> script) { |
@@ -656,6 +674,10 @@ |
debug_break_return_ = |
Builtins::builtin(Builtins::Return_DebugBreak); |
ASSERT(debug_break_return_->IsCode()); |
+ // Get code to handle debug break in debug break slots. |
+ debug_break_slot_ = |
+ Builtins::builtin(Builtins::Slot_DebugBreak); |
+ ASSERT(debug_break_slot_->IsCode()); |
} |
} |
@@ -824,6 +846,7 @@ |
void Debug::Iterate(ObjectVisitor* v) { |
v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_))); |
+ v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_slot_))); |
} |
@@ -1631,16 +1654,21 @@ |
// break point is still active after processing the break point. |
Address addr = frame->pc() - Assembler::kCallTargetAddressOffset; |
- // Check if the location is at JS exit. |
+ // Check if the location is at JS exit or debug break slot. |
bool at_js_return = false; |
bool break_at_js_return_active = false; |
+ bool at_debug_break_slot = false; |
RelocIterator it(debug_info->code()); |
- while (!it.done()) { |
+ while (!it.done() && !at_js_return && !at_debug_break_slot) { |
if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { |
at_js_return = (it.rinfo()->pc() == |
addr - Assembler::kPatchReturnSequenceAddressOffset); |
break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence(); |
} |
+ if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) { |
+ at_debug_break_slot = (it.rinfo()->pc() == |
+ addr - Assembler::kPatchDebugBreakSlotAddressOffset); |
+ } |
it.next(); |
} |
@@ -1657,25 +1685,30 @@ |
// Move back to where the call instruction sequence started. |
thread_local_.after_break_target_ = |
addr - Assembler::kPatchReturnSequenceAddressOffset; |
- } else { |
- // Check if there still is a debug break call at the target address. If the |
- // break point has been removed it will have disappeared. If it have |
- // disappeared don't try to look in the original code as the running code |
- // will have the right address. This takes care of the case where the last |
- // break point is removed from the function and therefore no "original code" |
- // is available. If the debug break call is still there find the address in |
- // the original code. |
- if (IsDebugBreak(Assembler::target_address_at(addr))) { |
- // If the break point is still there find the call address which was |
- // overwritten in the original code by the call to DebugBreakXXX. |
+ } else if (at_debug_break_slot) { |
+ // Address of where the debug break slot starts. |
+ addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; |
- // Find the corresponding address in the original code. |
- addr += original_code->instruction_start() - code->instruction_start(); |
- } |
+ // Continue just after the slot. |
+ thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength; |
+ } else if (IsDebugBreak(Assembler::target_address_at(addr))) { |
+ // We now know that there is still a debug break call at the target address, |
+ // so the break point is still there and the original code will hold the |
+ // address to jump to in order to complete the call which is replaced by a |
+ // call to DebugBreakXXX. |
+ // Find the corresponding address in the original code. |
+ addr += original_code->instruction_start() - code->instruction_start(); |
+ |
// Install jump to the call address in the original code. This will be the |
// call which was overwritten by the call to DebugBreakXXX. |
thread_local_.after_break_target_ = Assembler::target_address_at(addr); |
+ } else { |
+ // There is no longer a break point present. Don't try to look in the |
+ // original code as the running code will have the right address. This takes |
+ // care of the case where the last break point is removed from the function |
+ // and therefore no "original code" is available. |
+ thread_local_.after_break_target_ = Assembler::target_address_at(addr); |
} |
} |