| 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 <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 in_debug_event_listener_(false), | 52 in_debug_event_listener_(false), |
| 53 break_on_exception_(false), | 53 break_on_exception_(false), |
| 54 break_on_uncaught_exception_(false), | 54 break_on_uncaught_exception_(false), |
| 55 side_effect_check_failed_(false), | 55 side_effect_check_failed_(false), |
| 56 debug_info_list_(NULL), | 56 debug_info_list_(NULL), |
| 57 feature_tracker_(isolate), | 57 feature_tracker_(isolate), |
| 58 isolate_(isolate) { | 58 isolate_(isolate) { |
| 59 ThreadInit(); | 59 ThreadInit(); |
| 60 } | 60 } |
| 61 | 61 |
| 62 BreakLocation BreakLocation::FromFrame(StandardFrame* frame) { | 62 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| 63 // TODO(clemensh): Handle Wasm frames. | 63 JavaScriptFrame* frame) { |
| 64 DCHECK(!frame->is_wasm()); | 64 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); |
| 65 | |
| 66 auto summary = FrameSummary::GetFirst(frame).AsJavaScript(); | |
| 67 int offset = summary.code_offset(); | 65 int offset = summary.code_offset(); |
| 68 Handle<AbstractCode> abstract_code = summary.abstract_code(); | 66 Handle<AbstractCode> abstract_code = summary.abstract_code(); |
| 69 if (abstract_code->IsCode()) offset = offset - 1; | 67 if (abstract_code->IsCode()) offset = offset - 1; |
| 70 Handle<DebugInfo> debug_info(summary.function()->shared()->GetDebugInfo()); | |
| 71 auto it = BreakIterator::GetIterator(debug_info, abstract_code); | 68 auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
| 72 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); | 69 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); |
| 73 return it->GetBreakLocation(); | 70 return it->GetBreakLocation(); |
| 74 } | 71 } |
| 75 | 72 |
| 76 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, | 73 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, |
| 77 JavaScriptFrame* frame, | 74 JavaScriptFrame* frame, |
| 78 List<BreakLocation>* result_out) { | 75 List<BreakLocation>* result_out) { |
| 79 auto summary = FrameSummary::GetFirst(frame).AsJavaScript(); | 76 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); |
| 80 int offset = summary.code_offset(); | 77 int offset = summary.code_offset(); |
| 81 Handle<AbstractCode> abstract_code = summary.abstract_code(); | 78 Handle<AbstractCode> abstract_code = summary.abstract_code(); |
| 82 if (abstract_code->IsCode()) offset = offset - 1; | 79 if (abstract_code->IsCode()) offset = offset - 1; |
| 83 int statement_position; | 80 int statement_position; |
| 84 { | 81 { |
| 85 auto it = BreakIterator::GetIterator(debug_info, abstract_code); | 82 auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
| 86 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); | 83 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); |
| 87 statement_position = it->statement_position(); | 84 statement_position = it->statement_position(); |
| 88 } | 85 } |
| 89 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code); | 86 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 DebugScope debug_scope(this); | 511 DebugScope debug_scope(this); |
| 515 if (debug_scope.failed()) return; | 512 if (debug_scope.failed()) return; |
| 516 | 513 |
| 517 // Postpone interrupt during breakpoint processing. | 514 // Postpone interrupt during breakpoint processing. |
| 518 PostponeInterruptsScope postpone(isolate_); | 515 PostponeInterruptsScope postpone(isolate_); |
| 519 | 516 |
| 520 // Return if we fail to retrieve debug info. | 517 // Return if we fail to retrieve debug info. |
| 521 Handle<JSFunction> function(frame->function()); | 518 Handle<JSFunction> function(frame->function()); |
| 522 Handle<SharedFunctionInfo> shared(function->shared()); | 519 Handle<SharedFunctionInfo> shared(function->shared()); |
| 523 if (!EnsureDebugInfo(shared, function)) return; | 520 if (!EnsureDebugInfo(shared, function)) return; |
| 521 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); |
| 524 | 522 |
| 525 BreakLocation location = BreakLocation::FromFrame(frame); | 523 // Find the break location where execution has stopped. |
| 524 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
| 526 | 525 |
| 527 // Find actual break points, if any, and trigger debug break event. | 526 // Find actual break points, if any, and trigger debug break event. |
| 528 MaybeHandle<FixedArray> break_points_hit; | 527 MaybeHandle<FixedArray> break_points_hit = |
| 529 if (break_points_active()) { | 528 CheckBreakPoints(debug_info, &location); |
| 530 // Get the debug info, which must exist if we reach here. | |
| 531 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); | |
| 532 | |
| 533 break_points_hit = CheckBreakPoints(debug_info, &location); | |
| 534 } | |
| 535 | |
| 536 if (!break_points_hit.is_null()) { | 529 if (!break_points_hit.is_null()) { |
| 537 // Clear all current stepping setup. | 530 // Clear all current stepping setup. |
| 538 ClearStepping(); | 531 ClearStepping(); |
| 539 // Notify the debug event listeners. | 532 // Notify the debug event listeners. |
| 540 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements( | 533 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements( |
| 541 break_points_hit.ToHandleChecked()); | 534 break_points_hit.ToHandleChecked()); |
| 542 OnDebugBreak(jsarr, false); | 535 OnDebugBreak(jsarr, false); |
| 543 return; | 536 return; |
| 544 } | 537 } |
| 545 | 538 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 558 if (current_fp < target_fp) return; | 551 if (current_fp < target_fp) return; |
| 559 step_break = true; | 552 step_break = true; |
| 560 break; | 553 break; |
| 561 case StepNext: | 554 case StepNext: |
| 562 // Step next should not break in a deeper frame. | 555 // Step next should not break in a deeper frame. |
| 563 if (current_fp < target_fp) return; | 556 if (current_fp < target_fp) return; |
| 564 // For step-next, a tail call is like a return and should break. | 557 // For step-next, a tail call is like a return and should break. |
| 565 step_break = location.IsTailCall(); | 558 step_break = location.IsTailCall(); |
| 566 // Fall through. | 559 // Fall through. |
| 567 case StepIn: { | 560 case StepIn: { |
| 568 FrameSummary summary = FrameSummary::GetFirst(frame); | 561 FrameSummary summary = FrameSummary::GetTop(frame); |
| 569 step_break = step_break || location.IsReturn() || current_fp != last_fp || | 562 step_break = step_break || location.IsReturn() || current_fp != last_fp || |
| 570 thread_local_.last_statement_position_ != | 563 thread_local_.last_statement_position_ != |
| 571 summary.SourceStatementPosition(); | 564 summary.SourceStatementPosition(); |
| 572 break; | 565 break; |
| 573 } | 566 } |
| 574 case StepFrame: | 567 case StepFrame: |
| 575 step_break = current_fp != last_fp; | 568 step_break = current_fp != last_fp; |
| 576 break; | 569 break; |
| 577 } | 570 } |
| 578 | 571 |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 // Step out: Find the calling JavaScript frame and flood it with | 1000 // Step out: Find the calling JavaScript frame and flood it with |
| 1008 // breakpoints. | 1001 // breakpoints. |
| 1009 frames_it.Advance(); | 1002 frames_it.Advance(); |
| 1010 // Fill the function to return to with one-shot break points. | 1003 // Fill the function to return to with one-shot break points. |
| 1011 JSFunction* function = frames_it.frame()->function(); | 1004 JSFunction* function = frames_it.frame()->function(); |
| 1012 FloodWithOneShot(Handle<JSFunction>(function)); | 1005 FloodWithOneShot(Handle<JSFunction>(function)); |
| 1013 return; | 1006 return; |
| 1014 } | 1007 } |
| 1015 | 1008 |
| 1016 // Get the debug info (create it if it does not exist). | 1009 // Get the debug info (create it if it does not exist). |
| 1017 auto summary = FrameSummary::GetFirst(frame).AsJavaScript(); | 1010 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); |
| 1018 Handle<JSFunction> function(summary.function()); | 1011 Handle<JSFunction> function(summary.function()); |
| 1019 Handle<SharedFunctionInfo> shared(function->shared()); | 1012 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1020 if (!EnsureDebugInfo(shared, function)) { | 1013 if (!EnsureDebugInfo(shared, function)) { |
| 1021 // Return if ensuring debug info failed. | 1014 // Return if ensuring debug info failed. |
| 1022 return; | 1015 return; |
| 1023 } | 1016 } |
| 1024 | 1017 |
| 1025 BreakLocation location = BreakLocation::FromFrame(frame); | 1018 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1019 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
| 1026 | 1020 |
| 1027 // Any step at a return is a step-out. | 1021 // Any step at a return is a step-out. |
| 1028 if (location.IsReturn()) step_action = StepOut; | 1022 if (location.IsReturn()) step_action = StepOut; |
| 1029 // A step-next at a tail call is a step-out. | 1023 // A step-next at a tail call is a step-out. |
| 1030 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; | 1024 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; |
| 1031 | 1025 |
| 1032 thread_local_.last_statement_position_ = | 1026 thread_local_.last_statement_position_ = |
| 1033 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); | 1027 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); |
| 1034 thread_local_.last_fp_ = frame->UnpaddedFP(); | 1028 thread_local_.last_fp_ = frame->UnpaddedFP(); |
| 1035 // No longer perform the current async step. | 1029 // No longer perform the current async step. |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 after_break_target_ = NULL; | 1576 after_break_target_ = NULL; |
| 1583 if (!LiveEdit::SetAfterBreakTarget(this)) { | 1577 if (!LiveEdit::SetAfterBreakTarget(this)) { |
| 1584 // Continue just after the slot. | 1578 // Continue just after the slot. |
| 1585 after_break_target_ = frame->pc(); | 1579 after_break_target_ = frame->pc(); |
| 1586 } | 1580 } |
| 1587 } | 1581 } |
| 1588 | 1582 |
| 1589 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1583 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
| 1590 HandleScope scope(isolate_); | 1584 HandleScope scope(isolate_); |
| 1591 | 1585 |
| 1586 // Get the executing function in which the debug break occurred. |
| 1587 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
| 1588 |
| 1592 // With no debug info there are no break points, so we can't be at a return. | 1589 // With no debug info there are no break points, so we can't be at a return. |
| 1593 if (!frame->function()->shared()->HasDebugInfo()) return false; | 1590 if (!shared->HasDebugInfo()) return false; |
| 1594 | 1591 |
| 1595 DCHECK(!frame->is_optimized()); | 1592 DCHECK(!frame->is_optimized()); |
| 1596 BreakLocation location = BreakLocation::FromFrame(frame); | 1593 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1594 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
| 1597 return location.IsReturn() || location.IsTailCall(); | 1595 return location.IsReturn() || location.IsTailCall(); |
| 1598 } | 1596 } |
| 1599 | 1597 |
| 1600 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1598 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
| 1601 LiveEditFrameDropMode mode) { | 1599 LiveEditFrameDropMode mode) { |
| 1602 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) { | 1600 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) { |
| 1603 thread_local_.frame_drop_mode_ = mode; | 1601 thread_local_.frame_drop_mode_ = mode; |
| 1604 } | 1602 } |
| 1605 thread_local_.break_frame_id_ = new_break_frame_id; | 1603 thread_local_.break_frame_id_ = new_break_frame_id; |
| 1606 } | 1604 } |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2280 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | 2278 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
| 2281 } | 2279 } |
| 2282 | 2280 |
| 2283 #ifdef DEBUG | 2281 #ifdef DEBUG |
| 2284 void Debug::PrintBreakLocation() { | 2282 void Debug::PrintBreakLocation() { |
| 2285 if (!FLAG_print_break_location) return; | 2283 if (!FLAG_print_break_location) return; |
| 2286 HandleScope scope(isolate_); | 2284 HandleScope scope(isolate_); |
| 2287 JavaScriptFrameIterator iterator(isolate_); | 2285 JavaScriptFrameIterator iterator(isolate_); |
| 2288 if (iterator.done()) return; | 2286 if (iterator.done()) return; |
| 2289 JavaScriptFrame* frame = iterator.frame(); | 2287 JavaScriptFrame* frame = iterator.frame(); |
| 2290 FrameSummary summary = FrameSummary::GetFirst(frame); | 2288 FrameSummary summary = FrameSummary::GetTop(frame); |
| 2291 int source_position = summary.SourcePosition(); | 2289 int source_position = summary.SourcePosition(); |
| 2292 Handle<Object> script_obj = summary.script(); | 2290 Handle<Object> script_obj = summary.script(); |
| 2293 PrintF("[debug] break in function '"); | 2291 PrintF("[debug] break in function '"); |
| 2294 summary.FunctionName()->PrintOn(stdout); | 2292 summary.FunctionName()->PrintOn(stdout); |
| 2295 PrintF("'.\n"); | 2293 PrintF("'.\n"); |
| 2296 if (script_obj->IsScript()) { | 2294 if (script_obj->IsScript()) { |
| 2297 Handle<Script> script = Handle<Script>::cast(script_obj); | 2295 Handle<Script> script = Handle<Script>::cast(script_obj); |
| 2298 Handle<String> source(String::cast(script->source())); | 2296 Handle<String> source(String::cast(script->source())); |
| 2299 Script::InitLineEnds(script); | 2297 Script::InitLineEnds(script); |
| 2300 int line = | 2298 int line = |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2645 logger_->DebugEvent("Put", message.text()); | 2643 logger_->DebugEvent("Put", message.text()); |
| 2646 } | 2644 } |
| 2647 | 2645 |
| 2648 void LockingCommandMessageQueue::Clear() { | 2646 void LockingCommandMessageQueue::Clear() { |
| 2649 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2647 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2650 queue_.Clear(); | 2648 queue_.Clear(); |
| 2651 } | 2649 } |
| 2652 | 2650 |
| 2653 } // namespace internal | 2651 } // namespace internal |
| 2654 } // namespace v8 | 2652 } // namespace v8 |
| OLD | NEW |