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