Index: src/debug/debug.cc |
diff --git a/src/debug/debug.cc b/src/debug/debug.cc |
index 84ccd5981a0fa32a77eb97a492bb95a494b9dedb..13700ff0d420b09328bef971f01e3967645e4866 100644 |
--- a/src/debug/debug.cc |
+++ b/src/debug/debug.cc |
@@ -58,27 +58,41 @@ static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { |
return v8::Utils::ToLocal(native_context); |
} |
-BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, |
- int position, int statement_position) |
+BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, |
+ int code_offset, int position, |
+ int statement_position) |
: debug_info_(debug_info), |
- code_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), |
- rmode_(rinfo->rmode()), |
- data_(rinfo->data()), |
+ code_offset_(code_offset), |
+ type_(type), |
position_(position), |
statement_position_(statement_position) {} |
+BreakLocation::Iterator* BreakLocation::GetIterator( |
+ Handle<DebugInfo> debug_info, BreakLocatorType type) { |
+ if (debug_info->shared()->HasBytecodeArray()) { |
+ UNIMPLEMENTED(); |
+ return nullptr; |
+ } |
+ return new CodeIterator(debug_info, type); |
+} |
+ |
BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, |
BreakLocatorType type) |
: debug_info_(debug_info), |
- reloc_iterator_(debug_info->code(), GetModeMask(type)), |
break_index_(-1), |
position_(1), |
statement_position_(1) { |
- if (!Done()) Next(); |
} |
+BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, |
+ BreakLocatorType type) |
+ : Iterator(debug_info, type), |
+ reloc_iterator_(debug_info->abstract_code()->GetCode(), |
+ GetModeMask(type)) { |
+ if (!Done()) Next(); |
+} |
-int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) { |
+int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { |
int mask = 0; |
mask |= RelocInfo::ModeMask(RelocInfo::POSITION); |
mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); |
@@ -91,8 +105,7 @@ int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) { |
return mask; |
} |
- |
-void BreakLocation::Iterator::Next() { |
+void BreakLocation::CodeIterator::Next() { |
DisallowHeapAllocation no_gc; |
DCHECK(!Done()); |
@@ -139,14 +152,30 @@ void BreakLocation::Iterator::Next() { |
break_index_++; |
} |
+BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { |
+ DebugBreakType type; |
+ if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { |
+ type = DEBUG_BREAK_SLOT_AT_RETURN; |
+ } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { |
+ type = DEBUG_BREAK_SLOT_AT_CALL; |
+ } else if (RelocInfo::IsDebuggerStatement(rmode())) { |
+ type = DEBUGGER_STATEMENT; |
+ } else if (RelocInfo::IsDebugBreakSlot(rmode())) { |
+ type = DEBUG_BREAK_SLOT; |
+ } else { |
+ type = NOT_DEBUG_BREAK; |
+ } |
+ return BreakLocation(debug_info_, type, code_offset(), position(), |
+ statement_position()); |
+} |
// Find the break point at the supplied address, or the closest one before |
// the address. |
BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
int offset) { |
- Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
- it.SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
- return it.GetBreakLocation(); |
+ base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
+ it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
+ return it->GetBreakLocation(); |
} |
// Move GetFirstFrameSummary Definition to here as FromFrame use it. |
@@ -170,12 +199,12 @@ BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
void BreakLocation::FromCodeOffsetSameStatement( |
Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) { |
int break_index = BreakIndexFromCodeOffset(debug_info, offset); |
- Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
- 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(); |
+ base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
+ 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(); |
} |
} |
@@ -183,9 +212,10 @@ void BreakLocation::FromCodeOffsetSameStatement( |
void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
int statement_position, |
List<BreakLocation>* result_out) { |
- for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
- if (it.statement_position() == statement_position) { |
- result_out->Add(it.GetBreakLocation()); |
+ for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
+ it->Next()) { |
+ if (it->statement_position() == statement_position) { |
+ result_out->Add(it->GetBreakLocation()); |
} |
} |
} |
@@ -195,14 +225,13 @@ int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
// Run through all break points to locate the one closest to the address. |
int closest_break = 0; |
int distance = kMaxInt; |
- Code* code = debug_info->code(); |
- DCHECK(0 <= offset && offset < code->instruction_size()); |
- Address pc = code->instruction_start() + offset; |
- for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
+ DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size()); |
+ for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
+ it->Next()) { |
// Check if this break point is closer that what was previously found. |
- if (it.pc() <= pc && pc - it.pc() < distance) { |
- closest_break = it.break_index(); |
- distance = static_cast<int>(pc - it.pc()); |
+ if (it->code_offset() <= offset && offset - it->code_offset() < distance) { |
+ closest_break = it->break_index(); |
+ distance = offset - it->code_offset(); |
// Check whether we can't get any closer. |
if (distance == 0) break; |
} |
@@ -216,28 +245,26 @@ BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, |
BreakPositionAlignment alignment) { |
// Run through all break points to locate the one closest to the source |
// position. |
- int closest_break = 0; |
int distance = kMaxInt; |
- |
- for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
+ base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
+ BreakLocation closest_break = it->GetBreakLocation(); |
+ while (!it->Done()) { |
int next_position; |
if (alignment == STATEMENT_ALIGNED) { |
- next_position = it.statement_position(); |
+ next_position = it->statement_position(); |
} else { |
DCHECK(alignment == BREAK_POSITION_ALIGNED); |
- next_position = it.position(); |
+ next_position = it->position(); |
} |
if (position <= next_position && next_position - position < distance) { |
- closest_break = it.break_index(); |
+ closest_break = it->GetBreakLocation(); |
distance = next_position - position; |
// Check whether we can't get any closer. |
if (distance == 0) break; |
} |
+ it->Next(); |
} |
- |
- Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
- it.SkipTo(closest_break); |
- return it.GetBreakLocation(); |
+ return closest_break; |
} |
@@ -305,12 +332,18 @@ void BreakLocation::SetDebugBreak() { |
if (IsDebugBreak()) return; |
DCHECK(IsDebugBreakSlot()); |
- Isolate* isolate = debug_info_->GetIsolate(); |
- Builtins* builtins = isolate->builtins(); |
- Handle<Code> target = |
- IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak(); |
- DebugCodegen::PatchDebugBreakSlot(isolate, pc(), target); |
- DCHECK(IsDebugBreak()); |
+ if (abstract_code()->IsCode()) { |
+ Code* code = abstract_code()->GetCode(); |
+ DCHECK(code->kind() == Code::FUNCTION); |
+ Builtins* builtins = isolate()->builtins(); |
+ Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() |
+ : builtins->Slot_DebugBreak(); |
+ Address pc = code->instruction_start() + code_offset(); |
+ DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); |
+ DCHECK(IsDebugBreak()); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
} |
@@ -319,15 +352,30 @@ void BreakLocation::ClearDebugBreak() { |
if (IsDebuggerStatement()) return; |
DCHECK(IsDebugBreakSlot()); |
- DebugCodegen::ClearDebugBreakSlot(debug_info_->GetIsolate(), pc()); |
- DCHECK(!IsDebugBreak()); |
+ if (abstract_code()->IsCode()) { |
+ Code* code = abstract_code()->GetCode(); |
+ DCHECK(code->kind() == Code::FUNCTION); |
+ Address pc = code->instruction_start() + code_offset(); |
+ DebugCodegen::ClearDebugBreakSlot(isolate(), pc); |
+ DCHECK(!IsDebugBreak()); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
} |
bool BreakLocation::IsDebugBreak() const { |
if (IsDebuggerStatement()) return false; |
DCHECK(IsDebugBreakSlot()); |
- return rinfo().IsPatchedDebugBreakSlotSequence(); |
+ if (abstract_code()->IsCode()) { |
+ Code* code = abstract_code()->GetCode(); |
+ DCHECK(code->kind() == Code::FUNCTION); |
+ Address pc = code->instruction_start() + code_offset(); |
+ return DebugCodegen::DebugBreakSlotIsPatched(pc); |
+ } else { |
+ UNIMPLEMENTED(); |
+ return false; |
+ } |
} |
@@ -335,7 +383,6 @@ Handle<Object> BreakLocation::BreakPointObjects() const { |
return debug_info_->GetBreakPointObjects(code_offset_); |
} |
- |
void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { |
uint32_t mask = 1 << feature; |
// Only count one sample per feature and isolate. |
@@ -500,11 +547,11 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
if (current_fp < target_fp) return; |
// Fall through. |
case StepIn: { |
- int offset = |
- static_cast<int>(frame->pc() - location.code()->instruction_start()); |
+ FrameSummary summary = GetFirstFrameSummary(frame); |
+ int offset = summary.code_offset(); |
step_break = location.IsReturn() || (current_fp != last_fp) || |
(thread_local_.last_statement_position_ != |
- location.code()->SourceStatementPosition(offset)); |
+ location.abstract_code()->SourceStatementPosition(offset)); |
break; |
} |
case StepFrame: |
@@ -744,9 +791,10 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
void Debug::ClearAllBreakPoints() { |
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(); |
+ for (base::SmartPointer<BreakLocation::Iterator> it( |
+ BreakLocation::GetIterator(node->debug_info())); |
+ !it->Done(); it->Next()) { |
+ it->GetBreakLocation().ClearDebugBreak(); |
} |
} |
// Remove all debug info. |
@@ -777,8 +825,10 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function, |
// Flood the function with break points. |
Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
- for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { |
- it.GetBreakLocation().SetOneShot(); |
+ for (base::SmartPointer<BreakLocation::Iterator> it( |
+ BreakLocation::GetIterator(debug_info, type)); |
+ !it->Done(); it->Next()) { |
+ it->GetBreakLocation().SetOneShot(); |
} |
} |
@@ -898,7 +948,8 @@ void Debug::PrepareStep(StepAction step_action) { |
if (location.IsReturn()) step_action = StepOut; |
thread_local_.last_statement_position_ = |
- debug_info->code()->SourceStatementPosition(summary.code_offset()); |
+ debug_info->abstract_code()->SourceStatementPosition( |
+ summary.code_offset()); |
thread_local_.last_fp_ = frame->UnpaddedFP(); |
switch (step_action) { |
@@ -1005,9 +1056,10 @@ void Debug::ClearOneShot() { |
// removed from the list. |
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(); |
+ for (base::SmartPointer<BreakLocation::Iterator> it( |
+ BreakLocation::GetIterator(node->debug_info())); |
+ !it->Done(); it->Next()) { |
+ it->GetBreakLocation().ClearOneShot(); |
} |
} |
} |
@@ -1438,21 +1490,14 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
// With no debug info there are no break points, so we can't be at a return. |
if (!shared->HasDebugInfo()) return false; |
+ |
+ DCHECK(!frame->is_optimized()); |
+ FrameSummary summary = GetFirstFrameSummary(frame); |
+ |
Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
- Handle<Code> code(debug_info->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 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(*code, mask); !it.done(); it.next()) { |
- if (it.rinfo()->pc() == slot_pc) return true; |
- } |
- return false; |
+ BreakLocation location = |
+ BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); |
+ return location.IsReturn(); |
} |