| 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 |