Chromium Code Reviews| 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 |