Index: src/debug.cc |
diff --git a/src/debug.cc b/src/debug.cc |
index ea402ffa3d8c44865b509c7a2b60dbcf1c887593..0cd20ad5b134c9a3c2db796efebeb45d9fd23e7d 100644 |
--- a/src/debug.cc |
+++ b/src/debug.cc |
@@ -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; |
} |