Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: src/debug.cc

Issue 1234833003: Debugger: use debug break slots to break at function exit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix for arm Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index c8240e084fe85126357aeed1863a829337536eba..cdd2b8c7b949115816cbc91bc0395a74610a4efd 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -59,16 +59,11 @@ static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
- RelocInfo* original_rinfo, int position,
- int statement_position)
+ 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) {}
@@ -77,11 +72,10 @@ BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
BreakLocatorType type)
: debug_info_(debug_info),
reloc_iterator_(debug_info->code(), GetModeMask(type)),
- reloc_iterator_original_(debug_info->original_code(), GetModeMask(type)),
break_index_(-1),
position_(1),
statement_position_(1) {
- if (!RinfoDone()) Next();
+ if (!Done()) Next();
}
@@ -89,7 +83,7 @@ int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
int mask = 0;
mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
- mask |= RelocInfo::ModeMask(RelocInfo::JS_RETURN);
+ mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CONSTRUCT_CALL);
if (type == ALL_BREAK_LOCATIONS) {
@@ -102,15 +96,15 @@ int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) {
void BreakLocation::Iterator::Next() {
DisallowHeapAllocation no_gc;
- DCHECK(!RinfoDone());
+ DCHECK(!Done());
// Iterate through reloc info for code and original code stopping at each
// breakable code target.
bool first = break_index_ == -1;
- while (!RinfoDone()) {
- if (!first) RinfoNext();
+ while (!Done()) {
+ if (!first) reloc_iterator_.next();
first = false;
- if (RinfoDone()) return;
+ if (Done()) return;
// Whenever a statement position or (plain) position is passed update the
// current value of these.
@@ -128,7 +122,10 @@ void BreakLocation::Iterator::Next() {
continue;
}
- if (RelocInfo::IsJSReturn(rmode())) {
+ DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
+ RelocInfo::IsDebuggerStatement(rmode()));
+
+ if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
// Set the positions to the end of the function.
if (debug_info_->shared()->HasSourceCode()) {
position_ = debug_info_->shared()->end_position() -
@@ -137,11 +134,8 @@ void BreakLocation::Iterator::Next() {
position_ = 0;
}
statement_position_ = position_;
- break;
}
- DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
- RelocInfo::IsDebuggerStatement(rmode()));
break;
}
break_index_++;
@@ -152,6 +146,7 @@ void BreakLocation::Iterator::Next() {
// the address.
BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
BreakLocatorType type, Address pc) {
+ DCHECK(debug_info->code()->has_debug_break_slots());
Iterator it(debug_info, type);
it.SkipTo(BreakIndexFromAddress(debug_info, type, pc));
return it.GetBreakLocation();
@@ -163,6 +158,7 @@ BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info,
void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info,
BreakLocatorType type, Address pc,
List<BreakLocation>* result_out) {
+ DCHECK(debug_info->code()->has_debug_break_slots());
int break_index = BreakIndexFromAddress(debug_info, type, pc);
Iterator it(debug_info, type);
it.SkipTo(break_index);
@@ -195,6 +191,7 @@ int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info,
BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
BreakLocatorType type, int position,
BreakPositionAlignment alignment) {
+ DCHECK(debug_info->code()->has_debug_break_slots());
// Run through all break points to locate the one closest to the source
// position.
int closest_break = 0;
@@ -286,13 +283,11 @@ void BreakLocation::SetDebugBreak() {
// handler as the handler and the function is the same.
if (IsDebugBreak()) return;
- if (IsExit()) {
- // Patch the frame exit code with a break point.
- SetDebugBreakAtReturn();
- } else if (IsDebugBreakSlot()) {
- // Patch the code in the break slot.
- SetDebugBreakAtSlot();
- }
+ DCHECK(IsDebugBreakSlot());
+ Builtins* builtins = debug_info_->GetIsolate()->builtins();
+ Handle<Code> target =
+ IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak();
+ DebugCodegen::PatchDebugBreakSlot(pc(), target);
DCHECK(IsDebugBreak());
}
@@ -301,32 +296,19 @@ void BreakLocation::ClearDebugBreak() {
// Debugger statement always calls debugger. No need to modify it.
if (IsDebuggerStatement()) return;
- if (IsExit()) {
- // Restore the frame exit code with a break point.
- RestoreFromOriginal(Assembler::kJSReturnSequenceLength);
- } else if (IsDebugBreakSlot()) {
- // Restore the code in the break slot.
- RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
- }
+ DCHECK(IsDebugBreakSlot());
+ DebugCodegen::ClearDebugBreakSlot(pc());
DCHECK(!IsDebugBreak());
}
-void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
- memcpy(pc(), original_pc(), length_in_bytes);
- CpuFeatures::FlushICache(pc(), length_in_bytes);
-}
-
-
bool BreakLocation::IsStepInLocation() const {
return IsConstructCall() || IsCall();
}
bool BreakLocation::IsDebugBreak() const {
- if (IsExit()) {
- return rinfo().IsPatchedReturnSequence();
- } else if (IsDebugBreakSlot()) {
+ if (IsDebugBreakSlot()) {
return rinfo().IsPatchedDebugBreakSlotSequence();
}
return false;
@@ -338,22 +320,6 @@ Handle<Object> BreakLocation::BreakPointObjects() const {
}
-bool BreakLocation::Iterator::RinfoDone() const {
- DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
- return reloc_iterator_.done();
-}
-
-
-void BreakLocation::Iterator::RinfoNext() {
- reloc_iterator_.next();
- reloc_iterator_original_.next();
-#ifdef DEBUG
- DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
- DCHECK(reloc_iterator_.done() || rmode() == original_rinfo()->rmode());
-#endif
-}
-
-
// Threading support.
void Debug::ThreadInit() {
thread_local_.break_count_ = 0;
@@ -1150,14 +1116,14 @@ void Debug::PrepareStep(StepAction step_action,
}
// If this is the last break code target step out is the only possibility.
- if (location.IsExit() || step_action == StepOut) {
+ if (location.IsReturn() || 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(location.IsExit());
+ DCHECK(location.IsReturn());
frames_it.Advance();
}
// Skip native and extension functions on the stack.
@@ -1263,7 +1229,7 @@ bool Debug::StepNextContinue(BreakLocation* break_location,
// statement is hit.
if (step_action == StepNext || step_action == StepIn) {
// Never continue if returning from function.
- if (break_location->IsExit()) return false;
+ if (break_location->IsReturn()) return false;
// Continue if we are still on the same frame and in the same statement.
int current_statement_position =
@@ -2015,67 +1981,8 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
- HandleScope scope(isolate_);
- PrepareForBreakPoints();
-
- // Get the executing function in which the debug break occurred.
- Handle<JSFunction> function(JSFunction::cast(frame->function()));
- Handle<SharedFunctionInfo> shared(function->shared());
- if (!EnsureDebugInfo(shared, function)) {
- // Return if we failed to retrieve the debug info.
- return;
- }
- Handle<DebugInfo> debug_info = GetDebugInfo(shared);
- Handle<Code> code(debug_info->code());
- Handle<Code> original_code(debug_info->original_code());
-#ifdef DEBUG
- // Get the code which is actually executing.
- Handle<Code> frame_code(frame->LookupCode());
- DCHECK(frame_code.is_identical_to(code));
-#endif
-
- // Find the call address in the running code. This address holds the call to
- // either a DebugBreakXXX or to the debug break return entry code if the
- // break point is still active after processing the break point.
- Address addr = Assembler::break_address_from_return_address(frame->pc());
-
- // 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() && !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();
- }
-
- // Handle the jump to continue execution after break point depending on the
- // break location.
- if (at_js_return) {
- // If the break point at return is still active jump to the corresponding
- // place in the original code. If not the break point was removed during
- // break point processing.
- if (break_at_js_return_active) {
- addr += original_code->instruction_start() - code->instruction_start();
- }
-
- // Move back to where the call instruction sequence started.
- after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
- } else if (at_debug_break_slot) {
- // Address of where the debug break slot starts.
- addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
-
- // Continue just after the slot.
- after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
- }
+ // Continue just after the slot.
+ after_break_target_ = frame->pc();
}
@@ -2085,9 +1992,7 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
// If there are no break points this cannot be break at return, as
// the debugger statement and stack guard debug break cannot be at
// return.
- if (!has_break_points_) {
- return false;
- }
+ if (!has_break_points_) return false;
PrepareForBreakPoints();
@@ -2106,17 +2011,11 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
DCHECK(frame_code.is_identical_to(code));
#endif
- // Find the call address in the running code.
- Address addr = Assembler::break_address_from_return_address(frame->pc());
-
- // Check if the location is at JS return.
- RelocIterator it(debug_info->code());
- while (!it.done()) {
- if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
- return (it.rinfo()->pc() ==
- addr - Assembler::kPatchReturnSequenceAddressOffset);
- }
- it.next();
+ // Find the reloc info matching the start of the debug break slot.
+ Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength;
+ int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
+ for (RelocIterator it(debug_info->code(), mask); !it.done(); it.next()) {
+ if (it.rinfo()->pc() == slot_pc) return true;
}
return false;
}
@@ -3177,23 +3076,5 @@ void LockingCommandMessageQueue::Clear() {
queue_.Clear();
}
-
-void DebugCodegen::RecordRelocInfo(MacroAssembler* masm,
- DebugCodegen::SlotLocation location,
- int call_argc) {
- switch (location) {
- case PLAIN_DEBUG_BREAK:
- masm->RecordDebugBreakSlot();
- return;
- case DEBUG_BREAK_AT_CALL:
- DCHECK_LE(0, call_argc);
- masm->RecordDebugBreakSlotForCall(call_argc);
- return;
- case DEBUG_BREAK_AT_CONSTRUCT_CALL:
- masm->RecordDebugBreakSlotForConstructCall();
- return;
- }
-}
-
} // namespace internal
} // namespace v8
« no previous file with comments | « src/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698