Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(441)

Side by Side Diff: runtime/vm/debugger.cc

Issue 10686003: Better breakpoint placement (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "vm/code_generator.h" 7 #include "vm/code_generator.h"
8 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 event.type = kExceptionThrown; 814 event.type = kExceptionThrown;
815 event.exception = &exc; 815 event.exception = &exc;
816 ASSERT(event_handler_ != NULL); 816 ASSERT(event_handler_ != NULL);
817 (*event_handler_)(&event); 817 (*event_handler_)(&event);
818 stack_trace_ = NULL; 818 stack_trace_ = NULL;
819 obj_cache_ = NULL; // Remote object cache is zone allocated. 819 obj_cache_ = NULL; // Remote object cache is zone allocated.
820 } 820 }
821 821
822 822
823 CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func, 823 CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func,
824 intptr_t token_pos) { 824 intptr_t first_token_pos,
825 intptr_t last_token_pos) {
825 ASSERT(func.HasCode()); 826 ASSERT(func.HasCode());
826 ASSERT(!func.HasOptimizedCode()); 827 ASSERT(!func.HasOptimizedCode());
827 Code& code = Code::Handle(func.unoptimized_code()); 828 Code& code = Code::Handle(func.unoptimized_code());
828 ASSERT(!code.IsNull()); 829 ASSERT(!code.IsNull());
829 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 830 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
831 // We attempt to find the PC descriptor that is closest to the
832 // beginning of the token range, in terms of native code address. If we
833 // don't find a PC descriptor within the given range, we pick the
834 // neares one to the beginning of the range, in terms of token position.
siva 2012/06/27 02:00:31 nearest
hausner 2012/06/27 17:09:18 Done.
830 intptr_t best_fit_index = -1; 835 intptr_t best_fit_index = -1;
831 intptr_t best_fit = INT_MAX; 836 intptr_t best_fit = INT_MAX;
837 uword lowest_pc = UINTPTR_MAX;
838 intptr_t lowest_pc_index = -1;
832 for (int i = 0; i < desc.Length(); i++) { 839 for (int i = 0; i < desc.Length(); i++) {
833 intptr_t desc_token_pos = desc.TokenIndex(i); 840 intptr_t desc_token_pos = desc.TokenIndex(i);
834 if (desc_token_pos < token_pos) { 841 if (desc_token_pos < first_token_pos) {
835 continue; 842 continue;
836 } 843 }
837 PcDescriptors::Kind kind = desc.DescriptorKind(i); 844 PcDescriptors::Kind kind = desc.DescriptorKind(i);
838 if ((kind == PcDescriptors::kIcCall) || 845 if ((kind == PcDescriptors::kIcCall) ||
839 (kind == PcDescriptors::kFuncCall) || 846 (kind == PcDescriptors::kFuncCall) ||
840 (kind == PcDescriptors::kReturn)) { 847 (kind == PcDescriptors::kReturn)) {
841 if ((desc_token_pos - token_pos) < best_fit) { 848 if ((desc_token_pos - first_token_pos) < best_fit) {
842 best_fit = desc_token_pos - token_pos; 849 best_fit = desc_token_pos - first_token_pos;
843 ASSERT(best_fit >= 0); 850 ASSERT(best_fit >= 0);
844 best_fit_index = i; 851 best_fit_index = i;
845 } 852 }
853 if ((first_token_pos <= desc_token_pos) &&
854 (desc_token_pos <= last_token_pos) &&
855 (desc.PC(i) < lowest_pc)) {
856 lowest_pc = desc.PC(i);
857 lowest_pc_index = i;
858 }
846 } 859 }
847 } 860 }
861 if (lowest_pc_index >= 0) {
862 // We found the the pc descriptor within the given token range that
863 // has the lowest execution address. This is the first possible
864 // breakpoint on the line. We use this instead of the nearest
865 // PC descriptor measured in token index distance.
866 best_fit_index = lowest_pc_index;
867 }
848 if (best_fit_index >= 0) { 868 if (best_fit_index >= 0) {
849 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index)); 869 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index));
850 // We should only ever have one code breakpoint at the same address. 870 // We should only ever have one code breakpoint at the same address.
851 // If we find an existing breakpoint, it must be an internal one which 871 // If we find an existing breakpoint, it must be an internal one which
852 // is used for stepping. 872 // is used for stepping.
853 if (bpt != NULL) { 873 if (bpt != NULL) {
854 ASSERT(bpt->src_bpt() == NULL); 874 ASSERT(bpt->src_bpt() == NULL);
855 return bpt; 875 return bpt;
856 } 876 }
857 877
858 bpt = new CodeBreakpoint(func, best_fit_index); 878 bpt = new CodeBreakpoint(func, best_fit_index);
859 if (verbose) { 879 if (verbose) {
860 OS::Print("Setting breakpoint in function '%s' (%s:%d) (PC %p)\n", 880 OS::Print("Setting breakpoint in function '%s' (%s:%d) (PC %p)\n",
861 String::Handle(func.name()).ToCString(), 881 String::Handle(func.name()).ToCString(),
862 String::Handle(bpt->SourceUrl()).ToCString(), 882 String::Handle(bpt->SourceUrl()).ToCString(),
863 bpt->LineNumber(), 883 bpt->LineNumber(),
864 bpt->pc()); 884 bpt->pc());
865 } 885 }
866 RegisterCodeBreakpoint(bpt); 886 RegisterCodeBreakpoint(bpt);
867 return bpt; 887 return bpt;
868 } 888 }
869 return NULL; 889 return NULL;
870 } 890 }
871 891
872 892
873 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function, 893 SourceBreakpoint* Debugger::SetBreakpoint(const Function& target_function,
874 intptr_t token_pos) { 894 intptr_t first_token_pos,
875 if ((token_pos < target_function.token_pos()) || 895 intptr_t last_token_pos) {
876 (target_function.end_token_pos() <= token_pos)) { 896 if ((last_token_pos < target_function.token_pos()) ||
897 (target_function.end_token_pos() < first_token_pos)) {
877 // The given token position is not within the target function. 898 // The given token position is not within the target function.
878 return NULL; 899 return NULL;
879 } 900 }
880 EnsureFunctionIsDeoptimized(target_function); 901 EnsureFunctionIsDeoptimized(target_function);
881 SourceBreakpoint* bpt = GetSourceBreakpoint(target_function, token_pos); 902 SourceBreakpoint* bpt = GetSourceBreakpoint(target_function, first_token_pos);
882 if (bpt != NULL) { 903 if (bpt != NULL) {
883 // A breakpoint for this location already exists, return it. 904 // A breakpoint for this location already exists, return it.
884 return bpt; 905 return bpt;
885 } 906 }
886 bpt = new SourceBreakpoint(nextId(), target_function, token_pos); 907 bpt = new SourceBreakpoint(nextId(), target_function, first_token_pos);
887 RegisterSourceBreakpoint(bpt); 908 RegisterSourceBreakpoint(bpt);
888 if (verbose && !target_function.HasCode()) { 909 if (verbose && !target_function.HasCode()) {
889 OS::Print("Registering breakpoint for " 910 OS::Print("Registering breakpoint for "
890 "uncompiled function '%s' at line %d\n", 911 "uncompiled function '%s' at line %d\n",
891 target_function.ToFullyQualifiedCString(), 912 target_function.ToFullyQualifiedCString(),
892 bpt->LineNumber()); 913 bpt->LineNumber());
893 } 914 }
894 915
895 if (target_function.HasCode()) { 916 if (target_function.HasCode()) {
896 CodeBreakpoint* cbpt = MakeCodeBreakpoint(target_function, token_pos); 917 CodeBreakpoint* cbpt =
918 MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos);
897 if (cbpt != NULL) { 919 if (cbpt != NULL) {
898 ASSERT(cbpt->src_bpt() == NULL); 920 ASSERT(cbpt->src_bpt() == NULL);
899 cbpt->set_src_bpt(bpt); 921 cbpt->set_src_bpt(bpt);
900 SignalBpResolved(bpt); 922 SignalBpResolved(bpt);
901 } else { 923 } else {
902 if (verbose) { 924 if (verbose) {
903 OS::Print("Failed to set breakpoint at '%s' line %d\n", 925 OS::Print("Failed to set breakpoint at '%s' line %d\n",
904 String::Handle(bpt->SourceUrl()).ToCString(), 926 String::Handle(bpt->SourceUrl()).ToCString(),
905 bpt->LineNumber()); 927 bpt->LineNumber());
906 } 928 }
(...skipping 17 matching lines...) Expand all
924 } 946 }
925 } 947 }
926 cbpt = cbpt->next(); 948 cbpt = cbpt->next();
927 } 949 }
928 } 950 }
929 951
930 952
931 SourceBreakpoint* Debugger::SetBreakpointAtEntry( 953 SourceBreakpoint* Debugger::SetBreakpointAtEntry(
932 const Function& target_function) { 954 const Function& target_function) {
933 ASSERT(!target_function.IsNull()); 955 ASSERT(!target_function.IsNull());
934 return SetBreakpoint(target_function, target_function.token_pos()); 956 return SetBreakpoint(target_function,
957 target_function.token_pos(),
958 target_function.end_token_pos());
935 } 959 }
936 960
937 961
938 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 962 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
939 intptr_t line_number) { 963 intptr_t line_number) {
940 Library& lib = Library::Handle(); 964 Library& lib = Library::Handle();
941 Script& script = Script::Handle(); 965 Script& script = Script::Handle();
942 const GrowableObjectArray& libs = 966 const GrowableObjectArray& libs =
943 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 967 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
944 for (int i = 0; i < libs.Length(); i++) { 968 for (int i = 0; i < libs.Length(); i++) {
945 lib ^= libs.At(i); 969 lib ^= libs.At(i);
946 script = lib.LookupScript(script_url); 970 script = lib.LookupScript(script_url);
947 if (!script.IsNull()) { 971 if (!script.IsNull()) {
948 break; 972 break;
949 } 973 }
950 } 974 }
951 if (script.IsNull()) { 975 if (script.IsNull()) {
952 if (verbose) { 976 if (verbose) {
953 OS::Print("Failed to find script with url '%s'\n", 977 OS::Print("Failed to find script with url '%s'\n",
954 script_url.ToCString()); 978 script_url.ToCString());
955 } 979 }
956 return NULL; 980 return NULL;
957 } 981 }
958 intptr_t token_pos_at_line = script.TokenIndexAtLine(line_number); 982 intptr_t first_token_idx, last_token_idx;
959 if (token_pos_at_line < 0) { 983 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
984 if (first_token_idx < 0) {
960 // Script does not contain the given line number. 985 // Script does not contain the given line number.
961 if (verbose) { 986 if (verbose) {
962 OS::Print("Script '%s' does not contain line number %d\n", 987 OS::Print("Script '%s' does not contain line number %d\n",
963 script_url.ToCString(), line_number); 988 script_url.ToCString(), line_number);
964 } 989 }
965 return NULL; 990 return NULL;
966 } 991 }
967 const Function& func = 992 const Function& func =
968 Function::Handle(lib.LookupFunctionInScript(script, token_pos_at_line)); 993 Function::Handle(lib.LookupFunctionInScript(script, first_token_idx));
969 if (func.IsNull()) { 994 if (func.IsNull()) {
970 if (verbose) { 995 if (verbose) {
971 OS::Print("No executable code at line %d in '%s'\n", 996 OS::Print("No executable code at line %d in '%s'\n",
972 line_number, script_url.ToCString()); 997 line_number, script_url.ToCString());
973 } 998 }
974 return NULL; 999 return NULL;
975 } 1000 }
976 return SetBreakpoint(func, token_pos_at_line); 1001 if (last_token_idx < 0) {
1002 // The token at first_token_index is past the requested source line.
1003 // Set the breakpoint at the closest position after that line.
1004 last_token_idx = func.end_token_pos();
1005 }
1006 return SetBreakpoint(func, first_token_idx, last_token_idx);
977 } 1007 }
978 1008
979 1009
980 intptr_t Debugger::CacheObject(const Object& obj) { 1010 intptr_t Debugger::CacheObject(const Object& obj) {
981 ASSERT(obj_cache_ != NULL); 1011 ASSERT(obj_cache_ != NULL);
982 return obj_cache_->AddObject(obj); 1012 return obj_cache_->AddObject(obj);
983 } 1013 }
984 1014
985 1015
986 bool Debugger::IsValidObjectId(intptr_t obj_id) { 1016 bool Debugger::IsValidObjectId(intptr_t obj_id) {
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 OS::Print("Resetting pending breakpoint to function %s\n", 1415 OS::Print("Resetting pending breakpoint to function %s\n",
1386 closure.ToFullyQualifiedCString()); 1416 closure.ToFullyQualifiedCString());
1387 } 1417 }
1388 bpt->set_function(closure); 1418 bpt->set_function(closure);
1389 } else { 1419 } else {
1390 if (verbose) { 1420 if (verbose) {
1391 OS::Print("Enable pending breakpoint for function '%s'\n", 1421 OS::Print("Enable pending breakpoint for function '%s'\n",
1392 String::Handle(lookup_function.name()).ToCString()); 1422 String::Handle(lookup_function.name()).ToCString());
1393 } 1423 }
1394 // Set breakpoint in newly compiled code of function func. 1424 // Set breakpoint in newly compiled code of function func.
1395 CodeBreakpoint* cbpt = MakeCodeBreakpoint(func, bpt->token_pos()); 1425 CodeBreakpoint* cbpt =
1426 MakeCodeBreakpoint(func, bpt->token_pos(), func.end_token_pos());
1396 if (cbpt != NULL) { 1427 if (cbpt != NULL) {
1397 cbpt->set_src_bpt(bpt); 1428 cbpt->set_src_bpt(bpt);
1398 SignalBpResolved(bpt); 1429 SignalBpResolved(bpt);
1399 } 1430 }
1400 } 1431 }
1401 bpt->Enable(); // Enables the code breakpoint as well. 1432 bpt->Enable(); // Enables the code breakpoint as well.
1402 } 1433 }
1403 bpt = bpt->next(); 1434 bpt = bpt->next();
1404 } 1435 }
1405 } 1436 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 } 1548 }
1518 1549
1519 1550
1520 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1551 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1521 ASSERT(bpt->next() == NULL); 1552 ASSERT(bpt->next() == NULL);
1522 bpt->set_next(code_breakpoints_); 1553 bpt->set_next(code_breakpoints_);
1523 code_breakpoints_ = bpt; 1554 code_breakpoints_ = bpt;
1524 } 1555 }
1525 1556
1526 } // namespace dart 1557 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698