OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/debug/debug.h" | 5 #include "src/debug/debug.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 DCHECK(!Done()); | 101 DCHECK(!Done()); |
102 Next(); | 102 Next(); |
103 } | 103 } |
104 | 104 |
105 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { | 105 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { |
106 int mask = 0; | 106 int mask = 0; |
107 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); | 107 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); |
108 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); | 108 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); |
109 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 109 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); |
110 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); | 110 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); |
| 111 if (isolate()->is_tail_call_elimination_enabled()) { |
| 112 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL); |
| 113 } |
111 if (type == ALL_BREAK_LOCATIONS) { | 114 if (type == ALL_BREAK_LOCATIONS) { |
112 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); | 115 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); |
113 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); | 116 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); |
114 } | 117 } |
115 return mask; | 118 return mask; |
116 } | 119 } |
117 | 120 |
118 void BreakLocation::CodeIterator::Next() { | 121 void BreakLocation::CodeIterator::Next() { |
119 DisallowHeapAllocation no_gc; | 122 DisallowHeapAllocation no_gc; |
120 DCHECK(!Done()); | 123 DCHECK(!Done()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 } | 157 } |
155 break_index_++; | 158 break_index_++; |
156 } | 159 } |
157 | 160 |
158 BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { | 161 BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { |
159 DebugBreakType type; | 162 DebugBreakType type; |
160 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { | 163 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { |
161 type = DEBUG_BREAK_SLOT_AT_RETURN; | 164 type = DEBUG_BREAK_SLOT_AT_RETURN; |
162 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { | 165 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { |
163 type = DEBUG_BREAK_SLOT_AT_CALL; | 166 type = DEBUG_BREAK_SLOT_AT_CALL; |
| 167 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) { |
| 168 type = isolate()->is_tail_call_elimination_enabled() |
| 169 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL |
| 170 : DEBUG_BREAK_SLOT_AT_CALL; |
164 } else if (RelocInfo::IsDebuggerStatement(rmode())) { | 171 } else if (RelocInfo::IsDebuggerStatement(rmode())) { |
165 type = DEBUGGER_STATEMENT; | 172 type = DEBUGGER_STATEMENT; |
166 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { | 173 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { |
167 type = DEBUG_BREAK_SLOT; | 174 type = DEBUG_BREAK_SLOT; |
168 } else { | 175 } else { |
169 type = NOT_DEBUG_BREAK; | 176 type = NOT_DEBUG_BREAK; |
170 } | 177 } |
171 return BreakLocation(debug_info_, type, code_offset(), position(), | 178 return BreakLocation(debug_info_, type, code_offset(), position(), |
172 statement_position()); | 179 statement_position()); |
173 } | 180 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 BreakLocation::DebugBreakType | 226 BreakLocation::DebugBreakType |
220 BreakLocation::BytecodeArrayIterator::GetDebugBreakType() { | 227 BreakLocation::BytecodeArrayIterator::GetDebugBreakType() { |
221 BytecodeArray* bytecode_array = debug_info_->original_bytecode_array(); | 228 BytecodeArray* bytecode_array = debug_info_->original_bytecode_array(); |
222 interpreter::Bytecode bytecode = | 229 interpreter::Bytecode bytecode = |
223 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | 230 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
224 | 231 |
225 if (bytecode == interpreter::Bytecode::kDebugger) { | 232 if (bytecode == interpreter::Bytecode::kDebugger) { |
226 return DEBUGGER_STATEMENT; | 233 return DEBUGGER_STATEMENT; |
227 } else if (bytecode == interpreter::Bytecode::kReturn) { | 234 } else if (bytecode == interpreter::Bytecode::kReturn) { |
228 return DEBUG_BREAK_SLOT_AT_RETURN; | 235 return DEBUG_BREAK_SLOT_AT_RETURN; |
| 236 } else if (bytecode == interpreter::Bytecode::kTailCall) { |
| 237 return isolate()->is_tail_call_elimination_enabled() |
| 238 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL |
| 239 : DEBUG_BREAK_SLOT_AT_CALL; |
229 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) { | 240 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) { |
230 return DEBUG_BREAK_SLOT_AT_CALL; | 241 return DEBUG_BREAK_SLOT_AT_CALL; |
231 } else if (source_position_iterator_.is_statement()) { | 242 } else if (source_position_iterator_.is_statement()) { |
232 return DEBUG_BREAK_SLOT; | 243 return DEBUG_BREAK_SLOT; |
233 } else { | 244 } else { |
234 return NOT_DEBUG_BREAK; | 245 return NOT_DEBUG_BREAK; |
235 } | 246 } |
236 } | 247 } |
237 | 248 |
238 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { | 249 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 OnDebugBreak(break_points_hit, false); | 608 OnDebugBreak(break_points_hit, false); |
598 return; | 609 return; |
599 } | 610 } |
600 | 611 |
601 // No break point. Check for stepping. | 612 // No break point. Check for stepping. |
602 StepAction step_action = last_step_action(); | 613 StepAction step_action = last_step_action(); |
603 Address current_fp = frame->UnpaddedFP(); | 614 Address current_fp = frame->UnpaddedFP(); |
604 Address target_fp = thread_local_.target_fp_; | 615 Address target_fp = thread_local_.target_fp_; |
605 Address last_fp = thread_local_.last_fp_; | 616 Address last_fp = thread_local_.last_fp_; |
606 | 617 |
607 bool step_break = true; | 618 bool step_break = false; |
608 switch (step_action) { | 619 switch (step_action) { |
609 case StepNone: | 620 case StepNone: |
610 return; | 621 return; |
611 case StepOut: | 622 case StepOut: |
612 // Step out has not reached the target frame yet. | 623 // Step out has not reached the target frame yet. |
613 if (current_fp < target_fp) return; | 624 if (current_fp < target_fp) return; |
| 625 step_break = true; |
614 break; | 626 break; |
615 case StepNext: | 627 case StepNext: |
616 // Step next should not break in a deeper frame. | 628 // Step next should not break in a deeper frame. |
617 if (current_fp < target_fp) return; | 629 if (current_fp < target_fp) return; |
| 630 // For step-next, a tail call is like a return and should break. |
| 631 step_break = location.IsTailCall(); |
618 // Fall through. | 632 // Fall through. |
619 case StepIn: { | 633 case StepIn: { |
620 FrameSummary summary = GetFirstFrameSummary(frame); | 634 FrameSummary summary = GetFirstFrameSummary(frame); |
621 int offset = summary.code_offset(); | 635 int offset = summary.code_offset(); |
622 step_break = location.IsReturn() || (current_fp != last_fp) || | 636 step_break = step_break || location.IsReturn() || |
| 637 (current_fp != last_fp) || |
623 (thread_local_.last_statement_position_ != | 638 (thread_local_.last_statement_position_ != |
624 location.abstract_code()->SourceStatementPosition(offset)); | 639 location.abstract_code()->SourceStatementPosition(offset)); |
625 break; | 640 break; |
626 } | 641 } |
627 case StepFrame: | 642 case StepFrame: |
628 step_break = current_fp != last_fp; | 643 step_break = current_fp != last_fp; |
629 break; | 644 break; |
630 } | 645 } |
631 | 646 |
632 // Clear all current stepping setup. | 647 // Clear all current stepping setup. |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 // Refresh frame summary if the code has been recompiled for debugging. | 1023 // Refresh frame summary if the code has been recompiled for debugging. |
1009 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { | 1024 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
1010 summary = GetFirstFrameSummary(frame); | 1025 summary = GetFirstFrameSummary(frame); |
1011 } | 1026 } |
1012 | 1027 |
1013 int call_offset = | 1028 int call_offset = |
1014 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 1029 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); |
1015 BreakLocation location = | 1030 BreakLocation location = |
1016 BreakLocation::FromCodeOffset(debug_info, call_offset); | 1031 BreakLocation::FromCodeOffset(debug_info, call_offset); |
1017 | 1032 |
1018 // At a return statement we will step out either way. | 1033 // Any step at a return is a step-out. |
1019 if (location.IsReturn()) step_action = StepOut; | 1034 if (location.IsReturn()) step_action = StepOut; |
| 1035 // A step-next at a tail call is a step-out. |
| 1036 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; |
1020 | 1037 |
1021 thread_local_.last_statement_position_ = | 1038 thread_local_.last_statement_position_ = |
1022 debug_info->abstract_code()->SourceStatementPosition( | 1039 debug_info->abstract_code()->SourceStatementPosition( |
1023 summary.code_offset()); | 1040 summary.code_offset()); |
1024 thread_local_.last_fp_ = frame->UnpaddedFP(); | 1041 thread_local_.last_fp_ = frame->UnpaddedFP(); |
1025 | 1042 |
1026 switch (step_action) { | 1043 switch (step_action) { |
1027 case StepNone: | 1044 case StepNone: |
1028 UNREACHABLE(); | 1045 UNREACHABLE(); |
1029 break; | 1046 break; |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1585 | 1602 |
1586 // With no debug info there are no break points, so we can't be at a return. | 1603 // With no debug info there are no break points, so we can't be at a return. |
1587 if (!shared->HasDebugInfo()) return false; | 1604 if (!shared->HasDebugInfo()) return false; |
1588 | 1605 |
1589 DCHECK(!frame->is_optimized()); | 1606 DCHECK(!frame->is_optimized()); |
1590 FrameSummary summary = GetFirstFrameSummary(frame); | 1607 FrameSummary summary = GetFirstFrameSummary(frame); |
1591 | 1608 |
1592 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1609 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1593 BreakLocation location = | 1610 BreakLocation location = |
1594 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1611 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); |
1595 return location.IsReturn(); | 1612 return location.IsReturn() || location.IsTailCall(); |
1596 } | 1613 } |
1597 | 1614 |
1598 | 1615 |
1599 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1616 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
1600 LiveEdit::FrameDropMode mode) { | 1617 LiveEdit::FrameDropMode mode) { |
1601 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1618 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
1602 thread_local_.frame_drop_mode_ = mode; | 1619 thread_local_.frame_drop_mode_ = mode; |
1603 } | 1620 } |
1604 thread_local_.break_frame_id_ = new_break_frame_id; | 1621 thread_local_.break_frame_id_ = new_break_frame_id; |
1605 } | 1622 } |
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2607 } | 2624 } |
2608 | 2625 |
2609 | 2626 |
2610 void LockingCommandMessageQueue::Clear() { | 2627 void LockingCommandMessageQueue::Clear() { |
2611 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2628 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2612 queue_.Clear(); | 2629 queue_.Clear(); |
2613 } | 2630 } |
2614 | 2631 |
2615 } // namespace internal | 2632 } // namespace internal |
2616 } // namespace v8 | 2633 } // namespace v8 |
OLD | NEW |