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

Side by Side Diff: pkg/dartino_compiler/lib/vm_context.dart

Issue 2065933004: Support for accessing arrays in the debugger (Closed) Base URL: git@github.com:dartino/sdk.git@master
Patch Set: Created 4 years, 6 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
OLDNEW
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dartino 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.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 library dartino.vm_session; 5 library dartino.vm_session;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'dart:typed_data' show 9 import 'dart:typed_data' show
10 ByteData; 10 ByteData;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 import 'src/vm_connection.dart' show 57 import 'src/vm_connection.dart' show
58 VmConnection; 58 VmConnection;
59 59
60 import 'program_info.dart' show 60 import 'program_info.dart' show
61 IdOffsetMapping, 61 IdOffsetMapping,
62 NameOffsetMapping, 62 NameOffsetMapping,
63 ProgramInfoJson; 63 ProgramInfoJson;
64 64
65 import 'package:compiler/src/elements/elements.dart' show 65 import 'package:compiler/src/elements/elements.dart' show
66 ClassElement, 66 ClassElement;
67 FieldElement;
68 67
69 class SessionCommandTransformerBuilder 68 class SessionCommandTransformerBuilder
70 extends CommandTransformerBuilder<Pair<int, ByteData>> { 69 extends CommandTransformerBuilder<Pair<int, ByteData>> {
71 70
72 Pair<int, ByteData> makeCommand(int code, ByteData payload) { 71 Pair<int, ByteData> makeCommand(int code, ByteData payload) {
73 return new Pair<int, ByteData>(code, payload); 72 return new Pair<int, ByteData>(code, payload);
74 } 73 }
75 } 74 }
76 75
77 // TODO(sigurdm): for now only the stdio and stderr events are actually 76 // TODO(sigurdm): for now only the stdio and stderr events are actually
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 compiler, 848 compiler,
850 debugState)); 849 debugState));
851 } 850 }
852 return stackTrace; 851 return stackTrace;
853 } 852 }
854 853
855 Future<RemoteObject> uncaughtException() async { 854 Future<RemoteObject> uncaughtException() async {
856 assert(vmState == VmState.terminating); 855 assert(vmState == VmState.terminating);
857 if (debugState.currentUncaughtException == null) { 856 if (debugState.currentUncaughtException == null) {
858 await sendCommand(const ProcessUncaughtExceptionRequest()); 857 await sendCommand(const ProcessUncaughtExceptionRequest());
859 VmCommand response = await readNextCommand(); 858 debugState.currentUncaughtException = await readStructuredObject();
860 if (response is DartValue) {
861 debugState.currentUncaughtException = new RemoteValue(response);
862 } else {
863 assert(response is InstanceStructure);
864 List<DartValue> fields = await readInstanceStructureFields(response);
865 debugState.currentUncaughtException =
866 new RemoteInstance(response, fields);
867 }
868 } 859 }
869 return debugState.currentUncaughtException; 860 return debugState.currentUncaughtException;
870 } 861 }
871 862
872 Future<BackTrace> backTrace({int processId}) async { 863 Future<BackTrace> backTrace({int processId}) async {
873 processId ??= debugState.currentProcess; 864 processId ??= debugState.currentProcess;
874 assert(isSpawned); 865 assert(isSpawned);
875 if (debugState.currentBackTrace == null) { 866 if (debugState.currentBackTrace == null) {
876 ProcessBacktrace backtraceResponse = 867 ProcessBacktrace backtraceResponse =
877 await runCommand( 868 await runCommand(
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 String fieldName = debugState.lookupFieldName(klass, i); 935 String fieldName = debugState.lookupFieldName(klass, i);
945 if (fieldName == null) { 936 if (fieldName == null) {
946 fieldName = '<unnamed>'; 937 fieldName = '<unnamed>';
947 } 938 }
948 sb.writeln(' $fieldName: ${dartValueToString(value)}'); 939 sb.writeln(' $fieldName: ${dartValueToString(value)}');
949 } 940 }
950 sb.write('}'); 941 sb.write('}');
951 return '$sb'; 942 return '$sb';
952 } 943 }
953 944
945 String arrayStructureToString(List<DartValue> items) {
946 StringBuffer sb = new StringBuffer();
947 sb.writeln("Array with length ${items.length} [");
948 for (int i = 0; i < items.length; i++) {
949 sb.writeln(" $i = ${dartValueToString(items[i])}");
950 }
951 sb.write("]");
952 return '$sb';
953 }
954
954 String noSuchMethodErrorToString(List<DartValue> nsmFields) { 955 String noSuchMethodErrorToString(List<DartValue> nsmFields) {
955 assert(nsmFields.length == 3); 956 assert(nsmFields.length == 3);
956 ClassValue receiverClass = nsmFields[1]; 957 ClassValue receiverClass = nsmFields[1];
957 Integer receiverSelector = nsmFields[2]; 958 Integer receiverSelector = nsmFields[2];
958 DartinoSelector selector = new DartinoSelector(receiverSelector.value); 959 DartinoSelector selector = new DartinoSelector(receiverSelector.value);
959 960
960 String method = 961 String method =
961 dartinoSystem.lookupSymbolBySelector(selector.encodedSelector); 962 dartinoSystem.lookupSymbolBySelector(selector.encodedSelector);
962 DartinoClass klass = dartinoSystem.lookupClassById(receiverClass.classId); 963 DartinoClass klass = dartinoSystem.lookupClassById(receiverClass.classId);
963 // TODO(ahe): If DartinoClass is a synthetic closure class, improve the 964 // TODO(ahe): If DartinoClass is a synthetic closure class, improve the
(...skipping 13 matching lines...) Expand all
977 case SelectorKind.Getter: 978 case SelectorKind.Getter:
978 return "NoSuchMethodError: " 979 return "NoSuchMethodError: "
979 "Class '$name' has no getter named '$method'$raw"; 980 "Class '$name' has no getter named '$method'$raw";
980 981
981 case SelectorKind.Setter: 982 case SelectorKind.Setter:
982 return "NoSuchMethodError: " 983 return "NoSuchMethodError: "
983 "Class '$name' has no setter named '$method'$raw"; 984 "Class '$name' has no setter named '$method'$raw";
984 } 985 }
985 } 986 }
986 987
987 Future<List<DartValue>> readInstanceStructureFields( 988 Future<RemoteObject> readStructuredObject() async {
988 InstanceStructure structure) async { 989 VmCommand response = await readNextCommand();
989 List<DartValue> fields = <DartValue>[]; 990 if (response is DartValue) {
990 for (int i = 0; i < structure.fields; i++) { 991 return new RemoteValue(response);
991 fields.add(await readNextCommand()); 992 } else if (response is InstanceStructure) {
993 List<DartValue> fields = new List<DartValue>();
994 for (int i = 0; i < response.fields; i++) {
995 fields.add(await readNextCommand());
996 }
997 return new RemoteInstance(response, fields);
998 } else if (response is ArrayStructure) {
999 List<DartValue> values = new List<DartValue>();
1000 for (int i = 0; i < response.length; i++) {
1001 values.add(await readNextCommand());
1002 }
1003 return new RemoteArray(response, values);
1004 } else {
1005 return new RemoteErrorObject("Failed reading structured object.");
992 } 1006 }
993 return fields;
994 } 1007 }
995 1008
996 String exceptionToString(RemoteObject exception) { 1009 String exceptionToString(RemoteObject exception) {
997 String message; 1010 String message;
998 if (exception is RemoteValue) { 1011 if (exception is RemoteValue) {
999 message = dartValueToString(exception.value); 1012 message = dartValueToString(exception.value);
1000 } else if (exception is RemoteInstance) { 1013 } else if (exception is RemoteInstance) {
1001 InstanceStructure structure = exception.instance; 1014 InstanceStructure structure = exception.instance;
1002 int classId = structure.classId; 1015 int classId = structure.classId;
1003 DartinoClass klass = dartinoSystem.lookupClassById(classId); 1016 DartinoClass klass = dartinoSystem.lookupClassById(classId);
(...skipping 12 matching lines...) Expand all
1016 throw new UnimplementedError(); 1029 throw new UnimplementedError();
1017 } 1030 }
1018 return 'Uncaught exception: $message'; 1031 return 'Uncaught exception: $message';
1019 } 1032 }
1020 1033
1021 Future<RemoteObject> _processVariable( 1034 Future<RemoteObject> _processVariable(
1022 List<String> names, bool getStructure) async { 1035 List<String> names, bool getStructure) async {
1023 assert(isSpawned); 1036 assert(isSpawned);
1024 assert(names.isNotEmpty); 1037 assert(names.isNotEmpty);
1025 String localName = names.first; 1038 String localName = names.first;
1039 int frame = debugState.currentFrame;
1026 LocalValue local = await lookupValue(localName); 1040 LocalValue local = await lookupValue(localName);
1027 if (local == null) { 1041 if (local == null) {
1028 return new RemoteErrorObject("No local '$localName' in scope."); 1042 return new RemoteErrorObject("No local '$localName' in scope.");
1029 } 1043 }
1030 1044
1031 List<int> fieldIndices = new List<int>(); 1045 List<int> fieldIndices = new List<int>();
1032 List<String> namesTillHere = <String>[localName]; 1046 List<String> namesTillHere = <String>[localName];
1033 for (String fieldName in names.skip(1)) { 1047 for (String fieldName in names.skip(1)) {
1034 RemoteValue remoteValue = 1048 RemoteValue remoteValue = await processLocal(
1035 await processLocal(local, fieldAccesses: fieldIndices); 1049 frame,
1050 local.slot,
1051 fieldAccesses: fieldIndices);
1036 DartValue value = remoteValue.value; 1052 DartValue value = remoteValue.value;
1037 if (value is Instance) { 1053 if (value is Instance) {
1038 ClassElement classElement = 1054 ClassElement classElement =
1039 dartinoSystem.classesById[value.classId].element; 1055 dartinoSystem.classesById[value.classId].element;
1040 int fieldIndex = getFieldIndex(classElement, fieldName); 1056 int fieldIndex = getFieldIndex(classElement, fieldName);
1041 if (fieldIndex == null) { 1057 if (fieldIndex == null) {
1042 return new RemoteErrorObject( 1058 return new RemoteErrorObject(
1043 "'${namesTillHere.join(".")}' has type ${classElement}" 1059 "'${namesTillHere.join(".")}' has type ${classElement}"
1044 " that does not have a field named '${fieldName}'."); 1060 " that does not have a field named '${fieldName}'.");
1045 } 1061 }
1046 fieldIndices.add(fieldIndex); 1062 fieldIndices.add(fieldIndex);
1063 } else if (value is Array) {
1064 int index = int.parse(fieldName, onError: (_) => -1);
1065 if (index < 0 || index > value.length) {
1066 return new RemoteErrorObject(
1067 "${namesTillHere.join(".")}' is an array with length "
1068 "${value.length}. It cannot be indexed with ${fieldName}");
1069 }
1070 fieldIndices.add(index);
1047 } else { 1071 } else {
1048 return new RemoteErrorObject("'${namesTillHere.join(".")}' " 1072 return new RemoteErrorObject("'${namesTillHere.join(".")}' "
1049 "is a primitive value '${dartValueToString(value)}' " 1073 "is a primitive value '${dartValueToString(value)}' "
1050 "and does not have a field named '${fieldName}'"); 1074 "and does not have a field named '${fieldName}'");
1051 } 1075 }
1052 namesTillHere.add(fieldName); 1076 namesTillHere.add(fieldName);
1053 } 1077 }
1054 if (getStructure) { 1078 if (getStructure) {
1055 return await processLocalStructure(local, fieldAccesses: fieldIndices); 1079 return await processLocalStructure(
1080 frame, local.slot, fieldAccesses: fieldIndices);
1056 } else { 1081 } else {
1057 return await processLocal(local, fieldAccesses: fieldIndices); 1082 return await processLocal(frame, local.slot, fieldAccesses: fieldIndices);
1058 } 1083 }
1059 } 1084 }
1060 1085
1061 Future<RemoteValue> processVariable(List<String> names) { 1086 Future<RemoteValue> processVariable(List<String> names) {
1062 return _processVariable(names, false); 1087 return _processVariable(names, false);
1063 } 1088 }
1064 1089
1065 Future<RemoteObject> processVariableStructure(List<String> names) { 1090 Future<RemoteObject> processVariableStructure(List<String> names) {
1066 return _processVariable(names, true); 1091 return _processVariable(names, true);
1067 } 1092 }
1068 1093
1069 Future<List<RemoteObject>> processAllVariables() async { 1094 Future<List<RemoteObject>> processAllVariables() async {
1070 assert(isSpawned); 1095 assert(isSpawned);
1071 BackTrace trace = await backTrace(); 1096 BackTrace trace = await backTrace();
1072 ScopeInfo info = trace.scopeInfoForCurrentFrame; 1097 ScopeInfo info = trace.scopeInfoForCurrentFrame;
1073 List<RemoteObject> variables = []; 1098 List<RemoteObject> variables = [];
1074 for (ScopeInfo current = info; 1099 for (ScopeInfo current = info;
1075 current != ScopeInfo.sentinel; 1100 current != ScopeInfo.sentinel;
1076 current = current.previous) { 1101 current = current.previous) {
1077 variables.add(await processLocal(current.local, name: current.name)); 1102 variables.add(await processLocal(
1103 debugState.currentFrame, current.local.slot, name: current.name));
1078 } 1104 }
1079 return variables; 1105 return variables;
1080 } 1106 }
1081 1107
1082 Future<LocalValue> lookupValue(String name) async { 1108 Future<LocalValue> lookupValue(String name) async {
1083 assert(isSpawned); 1109 assert(isSpawned);
1084 BackTrace trace = await backTrace(); 1110 BackTrace trace = await backTrace();
1085 return trace.scopeInfoForCurrentFrame.lookup(name); 1111 return trace.scopeInfoForCurrentFrame.lookup(name);
1086 } 1112 }
1087 1113
1088 Future<RemoteValue> processLocal( 1114 Future<RemoteValue> processLocal(
1089 LocalValue local, 1115 int frameNumber,
1116 int localSlot,
1090 {String name, 1117 {String name,
1091 List<int> fieldAccesses: const <int>[]}) async { 1118 List<int> fieldAccesses: const <int>[]}) async {
1092 var actualFrameNumber = debugState.actualCurrentFrameNumber;
1093 VmCommand response = await runCommand( 1119 VmCommand response = await runCommand(
1094 new ProcessInstance(actualFrameNumber, local.slot, fieldAccesses)); 1120 new ProcessInstance(frameNumber, localSlot, fieldAccesses));
1095 assert(response is DartValue); 1121 assert(response is DartValue);
1096 return new RemoteValue(response, name: name); 1122 return new RemoteValue(response, name: name);
1097 } 1123 }
1098 1124
1099 Future<RemoteObject> processLocalStructure( 1125 Future<RemoteObject> processLocalStructure(
1100 LocalValue local, 1126 int frameNumber,
1127 int localSlot,
1101 {String name, 1128 {String name,
1102 List<int> fieldAccesses: const <int>[]}) async { 1129 List<int> fieldAccesses: const <int>[]}) async {
1103 var frameNumber = debugState.actualCurrentFrameNumber; 1130 frameNumber ??= debugState.actualCurrentFrameNumber;
1104 await sendCommand( 1131 await sendCommand(
1105 new ProcessInstanceStructure(frameNumber, local.slot, fieldAccesses)); 1132 new ProcessInstanceStructure(frameNumber, localSlot, fieldAccesses));
1106 VmCommand response = await readNextCommand(); 1133 return await readStructuredObject();
1107 if (response is DartValue) {
1108 return new RemoteValue(response);
1109 } else {
1110 assert(response is InstanceStructure);
1111 List<DartValue> fields = await readInstanceStructureFields(response);
1112 return new RemoteInstance(response, fields);
1113 }
1114 } 1134 }
1115 1135
1116 String remoteObjectToString(RemoteObject object) { 1136 String remoteObjectToString(RemoteObject object) {
1117 String message; 1137 String message;
1118 if (object is RemoteValue) { 1138 if (object is RemoteValue) {
1119 message = dartValueToString(object.value); 1139 message = dartValueToString(object.value);
1120 } else if (object is RemoteInstance) { 1140 } else if (object is RemoteInstance) {
1121 message = instanceStructureToString(object.instance, object.fields); 1141 message = instanceStructureToString(object.instance, object.fields);
1142 } else if (object is RemoteArray) {
1143 message = arrayStructureToString(object.values);
1122 } else { 1144 } else {
1123 throw new UnimplementedError(); 1145 throw new UnimplementedError();
1124 } 1146 }
1125 if (object.name != null) { 1147 if (object.name != null) {
1126 // Prefix with name. 1148 // Prefix with name.
1127 message = "${object.name}: $message"; 1149 message = "${object.name}: $message";
1128 } 1150 }
1129 return message; 1151 return message;
1130 } 1152 }
1131 1153
1132 bool toggleInternal() { 1154 bool toggleInternal() {
1133 debugState.showInternalFrames = !debugState.showInternalFrames; 1155 debugState.showInternalFrames = !debugState.showInternalFrames;
1134 if (debugState.currentBackTrace != null) { 1156 if (debugState.currentBackTrace != null) {
1135 debugState.currentBackTrace.visibilityChanged(); 1157 debugState.currentBackTrace.visibilityChanged();
1136 } 1158 }
1137 return debugState.showInternalFrames; 1159 return debugState.showInternalFrames;
1138 } 1160 }
1139 } 1161 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698