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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 DebugScope debug_scope(this); | 504 DebugScope debug_scope(this); |
505 if (debug_scope.failed()) return; | 505 if (debug_scope.failed()) return; |
506 | 506 |
507 // Postpone interrupt during breakpoint processing. | 507 // Postpone interrupt during breakpoint processing. |
508 PostponeInterruptsScope postpone(isolate_); | 508 PostponeInterruptsScope postpone(isolate_); |
509 DisableBreak no_recursive_break(this); | 509 DisableBreak no_recursive_break(this); |
510 | 510 |
511 // Return if we fail to retrieve debug info. | 511 // Return if we fail to retrieve debug info. |
512 Handle<JSFunction> function(frame->function()); | 512 Handle<JSFunction> function(frame->function()); |
513 Handle<SharedFunctionInfo> shared(function->shared()); | 513 Handle<SharedFunctionInfo> shared(function->shared()); |
514 if (!EnsureDebugInfo(shared)) return; | 514 if (!EnsureBreakInfo(shared)) return; |
515 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); | 515 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); |
516 | 516 |
517 // Find the break location where execution has stopped. | 517 // Find the break location where execution has stopped. |
518 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 518 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
519 | 519 |
520 // Find actual break points, if any, and trigger debug break event. | 520 // Find actual break points, if any, and trigger debug break event. |
521 MaybeHandle<FixedArray> break_points_hit = | 521 MaybeHandle<FixedArray> break_points_hit = |
522 CheckBreakPoints(debug_info, &location); | 522 CheckBreakPoints(debug_info, &location); |
523 if (!break_points_hit.is_null()) { | 523 if (!break_points_hit.is_null()) { |
524 // Clear all current stepping setup. | 524 // Clear all current stepping setup. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
605 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { | 605 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { |
606 HandleScope scope(isolate_); | 606 HandleScope scope(isolate_); |
607 // A break location is considered muted if break locations on the current | 607 // A break location is considered muted if break locations on the current |
608 // statement have at least one break point, and all of these break points | 608 // statement have at least one break point, and all of these break points |
609 // evaluate to false. Aside from not triggering a debug break event at the | 609 // evaluate to false. Aside from not triggering a debug break event at the |
610 // break location, we also do not trigger one for debugger statements, nor | 610 // break location, we also do not trigger one for debugger statements, nor |
611 // an exception event on exception at this location. | 611 // an exception event on exception at this location. |
612 FrameSummary summary = FrameSummary::GetTop(frame); | 612 FrameSummary summary = FrameSummary::GetTop(frame); |
613 DCHECK(!summary.IsWasm()); | 613 DCHECK(!summary.IsWasm()); |
614 Handle<JSFunction> function = summary.AsJavaScript().function(); | 614 Handle<JSFunction> function = summary.AsJavaScript().function(); |
615 if (!function->shared()->HasDebugInfo()) return false; | 615 if (!function->shared()->HasBreakInfo()) return false; |
616 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); | 616 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); |
617 // Enter the debugger. | 617 // Enter the debugger. |
618 DebugScope debug_scope(this); | 618 DebugScope debug_scope(this); |
619 if (debug_scope.failed()) return false; | 619 if (debug_scope.failed()) return false; |
620 List<BreakLocation> break_locations; | 620 List<BreakLocation> break_locations; |
621 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); | 621 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); |
622 bool has_break_points_at_all = false; | 622 bool has_break_points_at_all = false; |
623 for (int i = 0; i < break_locations.length(); i++) { | 623 for (int i = 0; i < break_locations.length(); i++) { |
624 bool has_break_points; | 624 bool has_break_points; |
625 MaybeHandle<FixedArray> check_result = | 625 MaybeHandle<FixedArray> check_result = |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
671 } | 671 } |
672 | 672 |
673 | 673 |
674 bool Debug::SetBreakPoint(Handle<JSFunction> function, | 674 bool Debug::SetBreakPoint(Handle<JSFunction> function, |
675 Handle<Object> break_point_object, | 675 Handle<Object> break_point_object, |
676 int* source_position) { | 676 int* source_position) { |
677 HandleScope scope(isolate_); | 677 HandleScope scope(isolate_); |
678 | 678 |
679 // Make sure the function is compiled and has set up the debug info. | 679 // Make sure the function is compiled and has set up the debug info. |
680 Handle<SharedFunctionInfo> shared(function->shared()); | 680 Handle<SharedFunctionInfo> shared(function->shared()); |
681 if (!EnsureDebugInfo(shared)) return true; | 681 if (!EnsureBreakInfo(shared)) return true; |
682 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 682 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
683 // Source positions starts with zero. | 683 // Source positions starts with zero. |
684 DCHECK(*source_position >= 0); | 684 DCHECK(*source_position >= 0); |
685 | 685 |
686 // Find the break point and change it. | 686 // Find the break point and change it. |
687 *source_position = | 687 *source_position = |
688 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED); | 688 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED); |
689 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); | 689 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); |
690 // At least one active break point now. | 690 // At least one active break point now. |
691 DCHECK(debug_info->GetBreakPointCount() > 0); | 691 DCHECK(debug_info->GetBreakPointCount() > 0); |
(...skipping 19 matching lines...) Expand all Loading... | |
711 | 711 |
712 HandleScope scope(isolate_); | 712 HandleScope scope(isolate_); |
713 | 713 |
714 // Obtain shared function info for the function. | 714 // Obtain shared function info for the function. |
715 Handle<Object> result = | 715 Handle<Object> result = |
716 FindSharedFunctionInfoInScript(script, *source_position); | 716 FindSharedFunctionInfoInScript(script, *source_position); |
717 if (result->IsUndefined(isolate_)) return false; | 717 if (result->IsUndefined(isolate_)) return false; |
718 | 718 |
719 // Make sure the function has set up the debug info. | 719 // Make sure the function has set up the debug info. |
720 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 720 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); |
721 if (!EnsureDebugInfo(shared)) return false; | 721 if (!EnsureBreakInfo(shared)) return false; |
722 | 722 |
723 // Find position within function. The script position might be before the | 723 // Find position within function. The script position might be before the |
724 // source position of the first function. | 724 // source position of the first function. |
725 if (shared->start_position() > *source_position) { | 725 if (shared->start_position() > *source_position) { |
726 *source_position = shared->start_position(); | 726 *source_position = shared->start_position(); |
727 } | 727 } |
728 | 728 |
729 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 729 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
730 | 730 |
731 // Find the break point and change it. | 731 // Find the break point and change it. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
802 | 802 |
803 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 803 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
804 node = node->next()) { | 804 node = node->next()) { |
805 Handle<Object> result = | 805 Handle<Object> result = |
806 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); | 806 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); |
807 if (result->IsUndefined(isolate_)) continue; | 807 if (result->IsUndefined(isolate_)) continue; |
808 Handle<DebugInfo> debug_info = node->debug_info(); | 808 Handle<DebugInfo> debug_info = node->debug_info(); |
809 if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) { | 809 if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) { |
810 ClearBreakPoints(debug_info); | 810 ClearBreakPoints(debug_info); |
811 if (debug_info->GetBreakPointCount() == 0) { | 811 if (debug_info->GetBreakPointCount() == 0) { |
812 RemoveDebugInfoAndClearFromShared(debug_info); | 812 RemoveBreakInfoAndMaybeFree(debug_info); |
813 } else { | 813 } else { |
814 ApplyBreakPoints(debug_info); | 814 ApplyBreakPoints(debug_info); |
815 } | 815 } |
816 return; | 816 return; |
817 } | 817 } |
818 } | 818 } |
819 } | 819 } |
820 | 820 |
821 // Clear out all the debug break code. This is ONLY supposed to be used when | 821 // Clear out all the debug break code. |
822 // shutting down the debugger as it will leave the break point information in | |
823 // DebugInfo even though the code is patched back to the non break point state. | |
824 void Debug::ClearAllBreakPoints() { | 822 void Debug::ClearAllBreakPoints() { |
825 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 823 DebugInfoListNode* curr = debug_info_list_; |
Michael Starzinger
2017/05/31 13:14:58
nit: s/curr/current/
jgruber
2017/05/31 13:46:45
Done.
| |
826 node = node->next()) { | 824 while (curr != nullptr) { |
827 ClearBreakPoints(node->debug_info()); | 825 DebugInfoListNode* next = curr->next(); |
828 } | 826 Handle<DebugInfo> debug_info = curr->debug_info(); |
829 // Remove all debug info. | 827 ClearBreakPoints(debug_info); |
830 while (debug_info_list_ != NULL) { | 828 RemoveBreakInfoAndMaybeFree(debug_info); |
Michael Starzinger
2017/05/31 13:14:57
question: This seems like it could have quadratic
jgruber
2017/05/31 13:46:45
Changed this slightly to avoid the linked-list sea
| |
831 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 829 curr = next; |
832 } | 830 } |
833 } | 831 } |
834 | 832 |
835 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared, | 833 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared, |
836 bool returns_only) { | 834 bool returns_only) { |
837 if (IsBlackboxed(shared)) return; | 835 if (IsBlackboxed(shared)) return; |
838 // Make sure the function is compiled and has set up the debug info. | 836 // Make sure the function is compiled and has set up the debug info. |
839 if (!EnsureDebugInfo(shared)) return; | 837 if (!EnsureBreakInfo(shared)) return; |
840 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 838 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
841 // Flood the function with break points. | 839 // Flood the function with break points. |
842 if (debug_info->HasDebugCode()) { | 840 if (debug_info->HasDebugCode()) { |
843 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) { | 841 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) { |
844 if (returns_only && !it.GetBreakLocation().IsReturn()) continue; | 842 if (returns_only && !it.GetBreakLocation().IsReturn()) continue; |
845 it.SetDebugBreak(); | 843 it.SetDebugBreak(); |
846 } | 844 } |
847 } | 845 } |
848 if (debug_info->HasDebugBytecodeArray()) { | 846 if (debug_info->HasDebugBytecodeArray()) { |
849 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) { | 847 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) { |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1024 return; | 1022 return; |
1025 } | 1023 } |
1026 | 1024 |
1027 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 1025 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); |
1028 DCHECK(js_frame->function()->IsJSFunction()); | 1026 DCHECK(js_frame->function()->IsJSFunction()); |
1029 | 1027 |
1030 // Get the debug info (create it if it does not exist). | 1028 // Get the debug info (create it if it does not exist). |
1031 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); | 1029 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); |
1032 Handle<JSFunction> function(summary.function()); | 1030 Handle<JSFunction> function(summary.function()); |
1033 Handle<SharedFunctionInfo> shared(function->shared()); | 1031 Handle<SharedFunctionInfo> shared(function->shared()); |
1034 if (!EnsureDebugInfo(shared)) return; | 1032 if (!EnsureBreakInfo(shared)) return; |
1035 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1033 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1036 | 1034 |
1037 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame); | 1035 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame); |
1038 | 1036 |
1039 // Any step at a return is a step-out and we need to schedule DebugOnFunction | 1037 // Any step at a return is a step-out and we need to schedule DebugOnFunction |
1040 // call callback. | 1038 // call callback. |
1041 if (location.IsReturn()) { | 1039 if (location.IsReturn()) { |
1042 // On StepOut we'll ignore our further calls to current function in | 1040 // On StepOut we'll ignore our further calls to current function in |
1043 // PrepareStepIn callback. | 1041 // PrepareStepIn callback. |
1044 if (last_step_action() == StepOut) { | 1042 if (last_step_action() == StepOut) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1114 FloodWithOneShot(shared); | 1112 FloodWithOneShot(shared); |
1115 break; | 1113 break; |
1116 } | 1114 } |
1117 } | 1115 } |
1118 | 1116 |
1119 // Simple function for returning the source positions for active break points. | 1117 // Simple function for returning the source positions for active break points. |
1120 Handle<Object> Debug::GetSourceBreakLocations( | 1118 Handle<Object> Debug::GetSourceBreakLocations( |
1121 Handle<SharedFunctionInfo> shared, | 1119 Handle<SharedFunctionInfo> shared, |
1122 BreakPositionAlignment position_alignment) { | 1120 BreakPositionAlignment position_alignment) { |
1123 Isolate* isolate = shared->GetIsolate(); | 1121 Isolate* isolate = shared->GetIsolate(); |
1124 if (!shared->HasDebugInfo()) { | 1122 if (!shared->HasBreakInfo()) { |
1125 return isolate->factory()->undefined_value(); | 1123 return isolate->factory()->undefined_value(); |
1126 } | 1124 } |
1127 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1125 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1128 if (debug_info->GetBreakPointCount() == 0) { | 1126 if (debug_info->GetBreakPointCount() == 0) { |
1129 return isolate->factory()->undefined_value(); | 1127 return isolate->factory()->undefined_value(); |
1130 } | 1128 } |
1131 Handle<FixedArray> locations = | 1129 Handle<FixedArray> locations = |
1132 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); | 1130 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); |
1133 int count = 0; | 1131 int count = 0; |
1134 for (int i = 0; i < debug_info->break_points()->length(); ++i) { | 1132 for (int i = 0; i < debug_info->break_points()->length(); ++i) { |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1392 int end_position, bool restrict_to_function, | 1390 int end_position, bool restrict_to_function, |
1393 std::vector<BreakLocation>* locations) { | 1391 std::vector<BreakLocation>* locations) { |
1394 if (restrict_to_function) { | 1392 if (restrict_to_function) { |
1395 Handle<Object> result = | 1393 Handle<Object> result = |
1396 FindSharedFunctionInfoInScript(script, start_position); | 1394 FindSharedFunctionInfoInScript(script, start_position); |
1397 if (result->IsUndefined(isolate_)) return false; | 1395 if (result->IsUndefined(isolate_)) return false; |
1398 | 1396 |
1399 // Make sure the function has set up the debug info. | 1397 // Make sure the function has set up the debug info. |
1400 Handle<SharedFunctionInfo> shared = | 1398 Handle<SharedFunctionInfo> shared = |
1401 Handle<SharedFunctionInfo>::cast(result); | 1399 Handle<SharedFunctionInfo>::cast(result); |
1402 if (!EnsureDebugInfo(shared)) return false; | 1400 if (!EnsureBreakInfo(shared)) return false; |
1403 | 1401 |
1404 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1402 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1405 FindBreakablePositions(debug_info, start_position, end_position, locations); | 1403 FindBreakablePositions(debug_info, start_position, end_position, locations); |
1406 return true; | 1404 return true; |
1407 } | 1405 } |
1408 | 1406 |
1409 while (true) { | 1407 while (true) { |
1410 HandleScope scope(isolate_); | 1408 HandleScope scope(isolate_); |
1411 List<Handle<SharedFunctionInfo>> candidates; | 1409 List<Handle<SharedFunctionInfo>> candidates; |
1412 SharedFunctionInfo::ScriptIterator iterator(script); | 1410 SharedFunctionInfo::ScriptIterator iterator(script); |
(...skipping 12 matching lines...) Expand all Loading... | |
1425 for (int i = 0; i < candidates.length(); ++i) { | 1423 for (int i = 0; i < candidates.length(); ++i) { |
1426 // Code that cannot be compiled lazily are internal and not debuggable. | 1424 // Code that cannot be compiled lazily are internal and not debuggable. |
1427 DCHECK(candidates[i]->allows_lazy_compilation()); | 1425 DCHECK(candidates[i]->allows_lazy_compilation()); |
1428 if (!candidates[i]->HasDebugCode()) { | 1426 if (!candidates[i]->HasDebugCode()) { |
1429 if (!Compiler::CompileDebugCode(candidates[i])) { | 1427 if (!Compiler::CompileDebugCode(candidates[i])) { |
1430 return false; | 1428 return false; |
1431 } else { | 1429 } else { |
1432 was_compiled = true; | 1430 was_compiled = true; |
1433 } | 1431 } |
1434 } | 1432 } |
1435 if (!EnsureDebugInfo(candidates[i])) return false; | 1433 if (!EnsureBreakInfo(candidates[i])) return false; |
1436 } | 1434 } |
1437 if (was_compiled) continue; | 1435 if (was_compiled) continue; |
1438 | 1436 |
1439 for (int i = 0; i < candidates.length(); ++i) { | 1437 for (int i = 0; i < candidates.length(); ++i) { |
1440 CHECK(candidates[i]->HasDebugInfo()); | 1438 CHECK(candidates[i]->HasBreakInfo()); |
1441 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo()); | 1439 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo()); |
1442 FindBreakablePositions(debug_info, start_position, end_position, | 1440 FindBreakablePositions(debug_info, start_position, end_position, |
1443 locations); | 1441 locations); |
1444 } | 1442 } |
1445 return true; | 1443 return true; |
1446 } | 1444 } |
1447 UNREACHABLE(); | 1445 UNREACHABLE(); |
1448 } | 1446 } |
1449 | 1447 |
1450 void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) { | 1448 void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1537 if (shared == NULL) break; | 1535 if (shared == NULL) break; |
1538 // We found it if it's already compiled and has debug code. | 1536 // We found it if it's already compiled and has debug code. |
1539 if (shared->HasDebugCode()) { | 1537 if (shared->HasDebugCode()) { |
1540 Handle<SharedFunctionInfo> shared_handle(shared); | 1538 Handle<SharedFunctionInfo> shared_handle(shared); |
1541 // If the iteration count is larger than 1, we had to compile the outer | 1539 // If the iteration count is larger than 1, we had to compile the outer |
1542 // function in order to create this shared function info. So there can | 1540 // function in order to create this shared function info. So there can |
1543 // be no JSFunction referencing it. We can anticipate creating a debug | 1541 // be no JSFunction referencing it. We can anticipate creating a debug |
1544 // info while bypassing PrepareFunctionForBreakpoints. | 1542 // info while bypassing PrepareFunctionForBreakpoints. |
1545 if (iteration > 1) { | 1543 if (iteration > 1) { |
1546 AllowHeapAllocation allow_before_return; | 1544 AllowHeapAllocation allow_before_return; |
1547 CreateDebugInfo(shared_handle); | 1545 CreateBreakInfo(shared_handle); |
1548 } | 1546 } |
1549 return shared_handle; | 1547 return shared_handle; |
1550 } | 1548 } |
1551 } | 1549 } |
1552 // If not, compile to reveal inner functions. | 1550 // If not, compile to reveal inner functions. |
1553 HandleScope scope(isolate_); | 1551 HandleScope scope(isolate_); |
1554 // Code that cannot be compiled lazily are internal and not debuggable. | 1552 // Code that cannot be compiled lazily are internal and not debuggable. |
1555 DCHECK(shared->allows_lazy_compilation()); | 1553 DCHECK(shared->allows_lazy_compilation()); |
1556 if (!Compiler::CompileDebugCode(handle(shared))) break; | 1554 if (!Compiler::CompileDebugCode(handle(shared))) break; |
1557 } | 1555 } |
1558 return isolate_->factory()->undefined_value(); | 1556 return isolate_->factory()->undefined_value(); |
1559 } | 1557 } |
1560 | 1558 |
1561 | 1559 |
1562 // Ensures the debug information is present for shared. | 1560 // Ensures the debug information is present for shared. |
1563 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) { | 1561 bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) { |
1564 // Return if we already have the debug info for shared. | 1562 // Return if we already have the break info for shared. |
1565 if (shared->HasDebugInfo()) return true; | 1563 if (shared->HasBreakInfo()) return true; |
1566 if (!shared->IsSubjectToDebugging()) return false; | 1564 if (!shared->IsSubjectToDebugging()) return false; |
1567 if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) { | 1565 if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) { |
1568 return false; | 1566 return false; |
1569 } | 1567 } |
1570 | 1568 |
1571 // To prepare bytecode for debugging, we already need to have the debug | 1569 // To prepare bytecode for debugging, we already need to have the debug |
1572 // info (containing the debug copy) upfront, but since we do not recompile, | 1570 // info (containing the debug copy) upfront, but since we do not recompile, |
1573 // preparing for break points cannot fail. | 1571 // preparing for break points cannot fail. |
1574 CreateDebugInfo(shared); | 1572 CreateBreakInfo(shared); |
1575 CHECK(PrepareFunctionForBreakPoints(shared)); | 1573 CHECK(PrepareFunctionForBreakPoints(shared)); |
1576 return true; | 1574 return true; |
1577 } | 1575 } |
1578 | 1576 |
1577 void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) { | |
1578 HandleScope scope(isolate_); | |
1579 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared); | |
1579 | 1580 |
1580 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) { | 1581 // Initialize with break information. |
1581 // Create the debug info object. | 1582 |
1583 DCHECK(!debug_info->HasBreakInfo()); | |
1584 | |
1585 Factory* factory = isolate_->factory(); | |
1586 Handle<FixedArray> break_points( | |
1587 factory->NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction)); | |
1588 | |
1589 // Make a copy of the bytecode array if available. | |
1590 Handle<Object> maybe_debug_bytecode_array = factory->undefined_value(); | |
1591 if (shared->HasBytecodeArray()) { | |
1592 Handle<BytecodeArray> original(shared->bytecode_array()); | |
1593 maybe_debug_bytecode_array = factory->CopyBytecodeArray(original); | |
1594 } | |
1595 | |
1596 debug_info->set_flags(debug_info->flags() | DebugInfo::kHasBreakInfo); | |
1597 debug_info->set_debug_bytecode_array(*maybe_debug_bytecode_array); | |
1598 debug_info->set_break_points(*break_points); | |
1599 } | |
1600 | |
1601 Handle<DebugInfo> Debug::GetOrCreateDebugInfo( | |
1602 Handle<SharedFunctionInfo> shared) { | |
1603 if (shared->HasDebugInfo()) return handle(shared->GetDebugInfo()); | |
1604 | |
1605 // Create debug info and add it to the list. | |
1582 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); | 1606 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); |
1583 | |
1584 // Add debug info to the list. | |
1585 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 1607 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
1586 node->set_next(debug_info_list_); | 1608 node->set_next(debug_info_list_); |
1587 debug_info_list_ = node; | 1609 debug_info_list_ = node; |
1610 | |
1611 return debug_info; | |
1588 } | 1612 } |
1589 | 1613 |
1590 | 1614 void Debug::FindDebugInfo(Handle<DebugInfo> debug_info, |
1591 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { | 1615 DebugInfoListNode** prev, DebugInfoListNode** curr) { |
1592 HandleScope scope(isolate_); | 1616 HandleScope scope(isolate_); |
1593 Handle<SharedFunctionInfo> shared(debug_info->shared()); | 1617 *prev = nullptr; |
1594 | 1618 *curr = debug_info_list_; |
1595 DCHECK_NOT_NULL(debug_info_list_); | 1619 while (*curr != nullptr) { |
1596 // Run through the debug info objects to find this one and remove it. | 1620 if ((*curr)->debug_info().is_identical_to(debug_info)) return; |
1597 DebugInfoListNode* prev = NULL; | 1621 *prev = *curr; |
1598 DebugInfoListNode* current = debug_info_list_; | 1622 *curr = (*curr)->next(); |
1599 while (current != NULL) { | |
1600 if (current->debug_info().is_identical_to(debug_info)) { | |
1601 // Unlink from list. If prev is NULL we are looking at the first element. | |
1602 if (prev == NULL) { | |
1603 debug_info_list_ = current->next(); | |
1604 } else { | |
1605 prev->set_next(current->next()); | |
1606 } | |
1607 shared->set_debug_info(Smi::FromInt(debug_info->debugger_hints())); | |
1608 delete current; | |
1609 return; | |
1610 } | |
1611 // Move to next in list. | |
1612 prev = current; | |
1613 current = current->next(); | |
1614 } | 1623 } |
1615 | 1624 |
1616 UNREACHABLE(); | 1625 UNREACHABLE(); |
1617 } | 1626 } |
1618 | 1627 |
1628 void Debug::RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info) { | |
1629 HandleScope scope(isolate_); | |
1630 Handle<SharedFunctionInfo> shared(debug_info->shared()); | |
1631 | |
1632 bool should_unlink = debug_info->ClearBreakInfo(); | |
1633 if (should_unlink) { | |
1634 // Unlink from list. If prev is NULL we are looking at the first element. | |
1635 DebugInfoListNode* prev; | |
1636 DebugInfoListNode* curr; | |
1637 FindDebugInfo(debug_info, &prev, &curr); | |
1638 | |
1639 if (prev == nullptr) { | |
1640 debug_info_list_ = curr->next(); | |
1641 } else { | |
1642 prev->set_next(curr->next()); | |
1643 } | |
1644 shared->set_debug_info(Smi::FromInt(debug_info->debugger_hints())); | |
1645 delete curr; | |
1646 } | |
1647 } | |
1648 | |
1619 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1649 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1620 HandleScope scope(isolate_); | 1650 HandleScope scope(isolate_); |
1621 | 1651 |
1622 // Get the executing function in which the debug break occurred. | 1652 // Get the executing function in which the debug break occurred. |
1623 Handle<SharedFunctionInfo> shared(frame->function()->shared()); | 1653 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
1624 | 1654 |
1625 // With no debug info there are no break points, so we can't be at a return. | 1655 // With no debug info there are no break points, so we can't be at a return. |
1626 if (!shared->HasDebugInfo()) return false; | 1656 if (!shared->HasBreakInfo()) return false; |
1627 | 1657 |
1628 DCHECK(!frame->is_optimized()); | 1658 DCHECK(!frame->is_optimized()); |
1629 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1659 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1630 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 1660 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
1631 return location.IsReturn() || location.IsTailCall(); | 1661 return location.IsReturn() || location.IsTailCall(); |
1632 } | 1662 } |
1633 | 1663 |
1634 void Debug::ScheduleFrameRestart(StackFrame* frame) { | 1664 void Debug::ScheduleFrameRestart(StackFrame* frame) { |
1635 // Set a target FP for the FrameDropperTrampoline builtin to drop to once | 1665 // Set a target FP for the FrameDropperTrampoline builtin to drop to once |
1636 // we return from the debugger. | 1666 // we return from the debugger. |
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2448 isolate_->Throw(*isolate_->factory()->NewEvalError( | 2478 isolate_->Throw(*isolate_->factory()->NewEvalError( |
2449 MessageTemplate::kNoSideEffectDebugEvaluate)); | 2479 MessageTemplate::kNoSideEffectDebugEvaluate)); |
2450 } | 2480 } |
2451 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); | 2481 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); |
2452 isolate_->debug()->UpdateHookOnFunctionCall(); | 2482 isolate_->debug()->UpdateHookOnFunctionCall(); |
2453 isolate_->debug()->side_effect_check_failed_ = false; | 2483 isolate_->debug()->side_effect_check_failed_ = false; |
2454 } | 2484 } |
2455 | 2485 |
2456 } // namespace internal | 2486 } // namespace internal |
2457 } // namespace v8 | 2487 } // namespace v8 |
OLD | NEW |