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* prev = nullptr; |
826 node = node->next()) { | 824 DebugInfoListNode* current = debug_info_list_; |
827 ClearBreakPoints(node->debug_info()); | 825 while (current != nullptr) { |
828 } | 826 DebugInfoListNode* next = current->next(); |
829 // Remove all debug info. | 827 Handle<DebugInfo> debug_info = current->debug_info(); |
830 while (debug_info_list_ != NULL) { | 828 ClearBreakPoints(debug_info); |
831 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 829 if (debug_info->ClearBreakInfo()) { |
| 830 FreeDebugInfoListNode(prev, current); |
| 831 current = next; |
| 832 } else { |
| 833 prev = current; |
| 834 current = next; |
| 835 } |
832 } | 836 } |
833 } | 837 } |
834 | 838 |
835 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared, | 839 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared, |
836 bool returns_only) { | 840 bool returns_only) { |
837 if (IsBlackboxed(shared)) return; | 841 if (IsBlackboxed(shared)) return; |
838 // Make sure the function is compiled and has set up the debug info. | 842 // Make sure the function is compiled and has set up the debug info. |
839 if (!EnsureDebugInfo(shared)) return; | 843 if (!EnsureBreakInfo(shared)) return; |
840 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 844 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
841 // Flood the function with break points. | 845 // Flood the function with break points. |
842 if (debug_info->HasDebugCode()) { | 846 if (debug_info->HasDebugCode()) { |
843 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) { | 847 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) { |
844 if (returns_only && !it.GetBreakLocation().IsReturn()) continue; | 848 if (returns_only && !it.GetBreakLocation().IsReturn()) continue; |
845 it.SetDebugBreak(); | 849 it.SetDebugBreak(); |
846 } | 850 } |
847 } | 851 } |
848 if (debug_info->HasDebugBytecodeArray()) { | 852 if (debug_info->HasDebugBytecodeArray()) { |
849 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) { | 853 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) { |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 return; | 1028 return; |
1025 } | 1029 } |
1026 | 1030 |
1027 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 1031 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); |
1028 DCHECK(js_frame->function()->IsJSFunction()); | 1032 DCHECK(js_frame->function()->IsJSFunction()); |
1029 | 1033 |
1030 // Get the debug info (create it if it does not exist). | 1034 // Get the debug info (create it if it does not exist). |
1031 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); | 1035 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); |
1032 Handle<JSFunction> function(summary.function()); | 1036 Handle<JSFunction> function(summary.function()); |
1033 Handle<SharedFunctionInfo> shared(function->shared()); | 1037 Handle<SharedFunctionInfo> shared(function->shared()); |
1034 if (!EnsureDebugInfo(shared)) return; | 1038 if (!EnsureBreakInfo(shared)) return; |
1035 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1039 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1036 | 1040 |
1037 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame); | 1041 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame); |
1038 | 1042 |
1039 // Any step at a return is a step-out and we need to schedule DebugOnFunction | 1043 // Any step at a return is a step-out and we need to schedule DebugOnFunction |
1040 // call callback. | 1044 // call callback. |
1041 if (location.IsReturn()) { | 1045 if (location.IsReturn()) { |
1042 // On StepOut we'll ignore our further calls to current function in | 1046 // On StepOut we'll ignore our further calls to current function in |
1043 // PrepareStepIn callback. | 1047 // PrepareStepIn callback. |
1044 if (last_step_action() == StepOut) { | 1048 if (last_step_action() == StepOut) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 FloodWithOneShot(shared); | 1118 FloodWithOneShot(shared); |
1115 break; | 1119 break; |
1116 } | 1120 } |
1117 } | 1121 } |
1118 | 1122 |
1119 // Simple function for returning the source positions for active break points. | 1123 // Simple function for returning the source positions for active break points. |
1120 Handle<Object> Debug::GetSourceBreakLocations( | 1124 Handle<Object> Debug::GetSourceBreakLocations( |
1121 Handle<SharedFunctionInfo> shared, | 1125 Handle<SharedFunctionInfo> shared, |
1122 BreakPositionAlignment position_alignment) { | 1126 BreakPositionAlignment position_alignment) { |
1123 Isolate* isolate = shared->GetIsolate(); | 1127 Isolate* isolate = shared->GetIsolate(); |
1124 if (!shared->HasDebugInfo()) { | 1128 if (!shared->HasBreakInfo()) { |
1125 return isolate->factory()->undefined_value(); | 1129 return isolate->factory()->undefined_value(); |
1126 } | 1130 } |
1127 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1131 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1128 if (debug_info->GetBreakPointCount() == 0) { | 1132 if (debug_info->GetBreakPointCount() == 0) { |
1129 return isolate->factory()->undefined_value(); | 1133 return isolate->factory()->undefined_value(); |
1130 } | 1134 } |
1131 Handle<FixedArray> locations = | 1135 Handle<FixedArray> locations = |
1132 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); | 1136 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); |
1133 int count = 0; | 1137 int count = 0; |
1134 for (int i = 0; i < debug_info->break_points()->length(); ++i) { | 1138 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, | 1396 int end_position, bool restrict_to_function, |
1393 std::vector<BreakLocation>* locations) { | 1397 std::vector<BreakLocation>* locations) { |
1394 if (restrict_to_function) { | 1398 if (restrict_to_function) { |
1395 Handle<Object> result = | 1399 Handle<Object> result = |
1396 FindSharedFunctionInfoInScript(script, start_position); | 1400 FindSharedFunctionInfoInScript(script, start_position); |
1397 if (result->IsUndefined(isolate_)) return false; | 1401 if (result->IsUndefined(isolate_)) return false; |
1398 | 1402 |
1399 // Make sure the function has set up the debug info. | 1403 // Make sure the function has set up the debug info. |
1400 Handle<SharedFunctionInfo> shared = | 1404 Handle<SharedFunctionInfo> shared = |
1401 Handle<SharedFunctionInfo>::cast(result); | 1405 Handle<SharedFunctionInfo>::cast(result); |
1402 if (!EnsureDebugInfo(shared)) return false; | 1406 if (!EnsureBreakInfo(shared)) return false; |
1403 | 1407 |
1404 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1408 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1405 FindBreakablePositions(debug_info, start_position, end_position, locations); | 1409 FindBreakablePositions(debug_info, start_position, end_position, locations); |
1406 return true; | 1410 return true; |
1407 } | 1411 } |
1408 | 1412 |
1409 while (true) { | 1413 while (true) { |
1410 HandleScope scope(isolate_); | 1414 HandleScope scope(isolate_); |
1411 List<Handle<SharedFunctionInfo>> candidates; | 1415 List<Handle<SharedFunctionInfo>> candidates; |
1412 SharedFunctionInfo::ScriptIterator iterator(script); | 1416 SharedFunctionInfo::ScriptIterator iterator(script); |
(...skipping 12 matching lines...) Expand all Loading... |
1425 for (int i = 0; i < candidates.length(); ++i) { | 1429 for (int i = 0; i < candidates.length(); ++i) { |
1426 // Code that cannot be compiled lazily are internal and not debuggable. | 1430 // Code that cannot be compiled lazily are internal and not debuggable. |
1427 DCHECK(candidates[i]->allows_lazy_compilation()); | 1431 DCHECK(candidates[i]->allows_lazy_compilation()); |
1428 if (!candidates[i]->HasDebugCode()) { | 1432 if (!candidates[i]->HasDebugCode()) { |
1429 if (!Compiler::CompileDebugCode(candidates[i])) { | 1433 if (!Compiler::CompileDebugCode(candidates[i])) { |
1430 return false; | 1434 return false; |
1431 } else { | 1435 } else { |
1432 was_compiled = true; | 1436 was_compiled = true; |
1433 } | 1437 } |
1434 } | 1438 } |
1435 if (!EnsureDebugInfo(candidates[i])) return false; | 1439 if (!EnsureBreakInfo(candidates[i])) return false; |
1436 } | 1440 } |
1437 if (was_compiled) continue; | 1441 if (was_compiled) continue; |
1438 | 1442 |
1439 for (int i = 0; i < candidates.length(); ++i) { | 1443 for (int i = 0; i < candidates.length(); ++i) { |
1440 CHECK(candidates[i]->HasDebugInfo()); | 1444 CHECK(candidates[i]->HasBreakInfo()); |
1441 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo()); | 1445 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo()); |
1442 FindBreakablePositions(debug_info, start_position, end_position, | 1446 FindBreakablePositions(debug_info, start_position, end_position, |
1443 locations); | 1447 locations); |
1444 } | 1448 } |
1445 return true; | 1449 return true; |
1446 } | 1450 } |
1447 UNREACHABLE(); | 1451 UNREACHABLE(); |
1448 } | 1452 } |
1449 | 1453 |
1450 void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) { | 1454 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; | 1541 if (shared == NULL) break; |
1538 // We found it if it's already compiled and has debug code. | 1542 // We found it if it's already compiled and has debug code. |
1539 if (shared->HasDebugCode()) { | 1543 if (shared->HasDebugCode()) { |
1540 Handle<SharedFunctionInfo> shared_handle(shared); | 1544 Handle<SharedFunctionInfo> shared_handle(shared); |
1541 // If the iteration count is larger than 1, we had to compile the outer | 1545 // 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 | 1546 // function in order to create this shared function info. So there can |
1543 // be no JSFunction referencing it. We can anticipate creating a debug | 1547 // be no JSFunction referencing it. We can anticipate creating a debug |
1544 // info while bypassing PrepareFunctionForBreakpoints. | 1548 // info while bypassing PrepareFunctionForBreakpoints. |
1545 if (iteration > 1) { | 1549 if (iteration > 1) { |
1546 AllowHeapAllocation allow_before_return; | 1550 AllowHeapAllocation allow_before_return; |
1547 CreateDebugInfo(shared_handle); | 1551 CreateBreakInfo(shared_handle); |
1548 } | 1552 } |
1549 return shared_handle; | 1553 return shared_handle; |
1550 } | 1554 } |
1551 } | 1555 } |
1552 // If not, compile to reveal inner functions. | 1556 // If not, compile to reveal inner functions. |
1553 HandleScope scope(isolate_); | 1557 HandleScope scope(isolate_); |
1554 // Code that cannot be compiled lazily are internal and not debuggable. | 1558 // Code that cannot be compiled lazily are internal and not debuggable. |
1555 DCHECK(shared->allows_lazy_compilation()); | 1559 DCHECK(shared->allows_lazy_compilation()); |
1556 if (!Compiler::CompileDebugCode(handle(shared))) break; | 1560 if (!Compiler::CompileDebugCode(handle(shared))) break; |
1557 } | 1561 } |
1558 return isolate_->factory()->undefined_value(); | 1562 return isolate_->factory()->undefined_value(); |
1559 } | 1563 } |
1560 | 1564 |
1561 | 1565 |
1562 // Ensures the debug information is present for shared. | 1566 // Ensures the debug information is present for shared. |
1563 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) { | 1567 bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) { |
1564 // Return if we already have the debug info for shared. | 1568 // Return if we already have the break info for shared. |
1565 if (shared->HasDebugInfo()) return true; | 1569 if (shared->HasBreakInfo()) return true; |
1566 if (!shared->IsSubjectToDebugging()) return false; | 1570 if (!shared->IsSubjectToDebugging()) return false; |
1567 if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) { | 1571 if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) { |
1568 return false; | 1572 return false; |
1569 } | 1573 } |
1570 | 1574 |
1571 // To prepare bytecode for debugging, we already need to have the debug | 1575 // 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, | 1576 // info (containing the debug copy) upfront, but since we do not recompile, |
1573 // preparing for break points cannot fail. | 1577 // preparing for break points cannot fail. |
1574 CreateDebugInfo(shared); | 1578 CreateBreakInfo(shared); |
1575 CHECK(PrepareFunctionForBreakPoints(shared)); | 1579 CHECK(PrepareFunctionForBreakPoints(shared)); |
1576 return true; | 1580 return true; |
1577 } | 1581 } |
1578 | 1582 |
| 1583 void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) { |
| 1584 HandleScope scope(isolate_); |
| 1585 Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared); |
1579 | 1586 |
1580 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) { | 1587 // Initialize with break information. |
1581 // Create the debug info object. | 1588 |
| 1589 DCHECK(!debug_info->HasBreakInfo()); |
| 1590 |
| 1591 Factory* factory = isolate_->factory(); |
| 1592 Handle<FixedArray> break_points( |
| 1593 factory->NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction)); |
| 1594 |
| 1595 // Make a copy of the bytecode array if available. |
| 1596 Handle<Object> maybe_debug_bytecode_array = factory->undefined_value(); |
| 1597 if (shared->HasBytecodeArray()) { |
| 1598 Handle<BytecodeArray> original(shared->bytecode_array()); |
| 1599 maybe_debug_bytecode_array = factory->CopyBytecodeArray(original); |
| 1600 } |
| 1601 |
| 1602 debug_info->set_flags(debug_info->flags() | DebugInfo::kHasBreakInfo); |
| 1603 debug_info->set_debug_bytecode_array(*maybe_debug_bytecode_array); |
| 1604 debug_info->set_break_points(*break_points); |
| 1605 } |
| 1606 |
| 1607 Handle<DebugInfo> Debug::GetOrCreateDebugInfo( |
| 1608 Handle<SharedFunctionInfo> shared) { |
| 1609 if (shared->HasDebugInfo()) return handle(shared->GetDebugInfo()); |
| 1610 |
| 1611 // Create debug info and add it to the list. |
1582 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); | 1612 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); |
1583 | |
1584 // Add debug info to the list. | |
1585 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 1613 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
1586 node->set_next(debug_info_list_); | 1614 node->set_next(debug_info_list_); |
1587 debug_info_list_ = node; | 1615 debug_info_list_ = node; |
| 1616 |
| 1617 return debug_info; |
1588 } | 1618 } |
1589 | 1619 |
1590 | 1620 void Debug::FindDebugInfo(Handle<DebugInfo> debug_info, |
1591 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { | 1621 DebugInfoListNode** prev, DebugInfoListNode** curr) { |
1592 HandleScope scope(isolate_); | 1622 HandleScope scope(isolate_); |
1593 Handle<SharedFunctionInfo> shared(debug_info->shared()); | 1623 *prev = nullptr; |
1594 | 1624 *curr = debug_info_list_; |
1595 DCHECK_NOT_NULL(debug_info_list_); | 1625 while (*curr != nullptr) { |
1596 // Run through the debug info objects to find this one and remove it. | 1626 if ((*curr)->debug_info().is_identical_to(debug_info)) return; |
1597 DebugInfoListNode* prev = NULL; | 1627 *prev = *curr; |
1598 DebugInfoListNode* current = debug_info_list_; | 1628 *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 } | 1629 } |
1615 | 1630 |
1616 UNREACHABLE(); | 1631 UNREACHABLE(); |
1617 } | 1632 } |
1618 | 1633 |
| 1634 void Debug::RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info) { |
| 1635 bool should_unlink = debug_info->ClearBreakInfo(); |
| 1636 if (should_unlink) { |
| 1637 DebugInfoListNode* prev; |
| 1638 DebugInfoListNode* node; |
| 1639 FindDebugInfo(debug_info, &prev, &node); |
| 1640 FreeDebugInfoListNode(prev, node); |
| 1641 } |
| 1642 } |
| 1643 |
| 1644 void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev, |
| 1645 DebugInfoListNode* node) { |
| 1646 DCHECK(node->debug_info()->IsEmpty()); |
| 1647 |
| 1648 // Unlink from list. If prev is NULL we are looking at the first element. |
| 1649 if (prev == nullptr) { |
| 1650 debug_info_list_ = node->next(); |
| 1651 } else { |
| 1652 prev->set_next(node->next()); |
| 1653 } |
| 1654 |
| 1655 // Pack debugger hints back into the SFI::debug_info field. |
| 1656 Handle<DebugInfo> debug_info(node->debug_info()); |
| 1657 debug_info->shared()->set_debug_info( |
| 1658 Smi::FromInt(debug_info->debugger_hints())); |
| 1659 |
| 1660 delete node; |
| 1661 } |
| 1662 |
1619 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1663 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1620 HandleScope scope(isolate_); | 1664 HandleScope scope(isolate_); |
1621 | 1665 |
1622 // Get the executing function in which the debug break occurred. | 1666 // Get the executing function in which the debug break occurred. |
1623 Handle<SharedFunctionInfo> shared(frame->function()->shared()); | 1667 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
1624 | 1668 |
1625 // With no debug info there are no break points, so we can't be at a return. | 1669 // With no debug info there are no break points, so we can't be at a return. |
1626 if (!shared->HasDebugInfo()) return false; | 1670 if (!shared->HasBreakInfo()) return false; |
1627 | 1671 |
1628 DCHECK(!frame->is_optimized()); | 1672 DCHECK(!frame->is_optimized()); |
1629 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1673 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1630 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 1674 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
1631 return location.IsReturn() || location.IsTailCall(); | 1675 return location.IsReturn() || location.IsTailCall(); |
1632 } | 1676 } |
1633 | 1677 |
1634 void Debug::ScheduleFrameRestart(StackFrame* frame) { | 1678 void Debug::ScheduleFrameRestart(StackFrame* frame) { |
1635 // Set a target FP for the FrameDropperTrampoline builtin to drop to once | 1679 // Set a target FP for the FrameDropperTrampoline builtin to drop to once |
1636 // we return from the debugger. | 1680 // we return from the debugger. |
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2448 isolate_->Throw(*isolate_->factory()->NewEvalError( | 2492 isolate_->Throw(*isolate_->factory()->NewEvalError( |
2449 MessageTemplate::kNoSideEffectDebugEvaluate)); | 2493 MessageTemplate::kNoSideEffectDebugEvaluate)); |
2450 } | 2494 } |
2451 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); | 2495 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); |
2452 isolate_->debug()->UpdateHookOnFunctionCall(); | 2496 isolate_->debug()->UpdateHookOnFunctionCall(); |
2453 isolate_->debug()->side_effect_check_failed_ = false; | 2497 isolate_->debug()->side_effect_check_failed_ = false; |
2454 } | 2498 } |
2455 | 2499 |
2456 } // namespace internal | 2500 } // namespace internal |
2457 } // namespace v8 | 2501 } // namespace v8 |
OLD | NEW |