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

Side by Side Diff: runtime/bin/vmservice/client/lib/src/service/object.dart

Issue 251043003: Observatory Display PC descriptors with disassembling (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 part of service; 5 part of service;
6 6
7 /// A [ServiceObject] is an object known to the VM service and is tied 7 /// A [ServiceObject] is an object known to the VM service and is tied
8 /// to an owning [Isolate]. 8 /// to an owning [Isolate].
9 abstract class ServiceObject extends Observable { 9 abstract class ServiceObject extends Observable {
10 /// The owner of this [ServiceObject]. This can be an [Isolate], a 10 /// The owner of this [ServiceObject]. This can be an [Isolate], a
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 @observable int firstTokenPos; 857 @observable int firstTokenPos;
858 @observable int lastTokenPos; 858 @observable int lastTokenPos;
859 bool get canCache => true; 859 bool get canCache => true;
860 bool get immutable => true; 860 bool get immutable => true;
861 861
862 String _shortUrl; 862 String _shortUrl;
863 String _url; 863 String _url;
864 864
865 Script._empty(ServiceObjectOwner owner) : super._empty(owner); 865 Script._empty(ServiceObjectOwner owner) : super._empty(owner);
866 866
867 ScriptLine getLine(int line) {
868 assert(line >= 1);
869 return lines[line - 1];
870 }
871
867 /// This function maps a token position to a line number. 872 /// This function maps a token position to a line number.
868 int tokenToLine(int token) => _tokenToLine[token]; 873 int tokenToLine(int token) => _tokenToLine[token];
869 Map _tokenToLine; 874 Map _tokenToLine;
870 875
871 /// This function maps a token position to a column number. 876 /// This function maps a token position to a column number.
872 int tokenToCol(int token) => _tokenToCol[token]; 877 int tokenToCol(int token) => _tokenToCol[token];
873 Map _tokenToCol; 878 Map _tokenToCol;
874 879
875 void _update(ObservableMap map, bool mapIsRef) { 880 void _update(ObservableMap map, bool mapIsRef) {
876 kind = map['kind']; 881 kind = map['kind'];
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 } 950 }
946 951
947 class CodeTick { 952 class CodeTick {
948 final int address; 953 final int address;
949 final int exclusiveTicks; 954 final int exclusiveTicks;
950 final int inclusiveTicks; 955 final int inclusiveTicks;
951 CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks); 956 CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks);
952 } 957 }
953 958
954 959
960 class PcDescriptor extends Observable {
961 final int address;
962 @reflectable final int deoptId;
963 @reflectable final int tokenPos;
964 @reflectable final int tryIndex;
965 @reflectable final String kind;
966 @observable Script script;
967 @observable String formattedLine;
968 PcDescriptor(this.address, this.deoptId, this.tokenPos, this.tryIndex,
969 this.kind);
970
971 @reflectable String formattedDeoptId() {
972 if (deoptId == -1) {
973 return 'N/A';
974 }
975 return deoptId.toString();
976 }
977
978 @reflectable String formattedTokenPos() {
979 if (tokenPos == -1) {
980 return '';
981 }
982 return tokenPos.toString();
983 }
984
985 void processScript(Script script) {
986 this.script = null;
987 if (tokenPos == -1) {
988 return;
989 }
990 var line = script.tokenToLine(tokenPos);
991 if (line == null) {
992 return;
993 }
994 this.script = script;
995 var scriptLine = script.getLine(line);
996 formattedLine = scriptLine.text;
997 }
998 }
999
955 class CodeInstruction extends Observable { 1000 class CodeInstruction extends Observable {
956 @observable final int address; 1001 @observable final int address;
957 @observable final String machine; 1002 @observable final String machine;
958 @observable final String human; 1003 @observable final String human;
1004 @observable CodeInstruction jumpTarget;
1005 @reflectable List<PcDescriptor> descriptors =
1006 new ObservableList<PcDescriptor>();
959 1007
960 static String formatPercent(num a, num total) { 1008 static String formatPercent(num a, num total) {
961 var percent = 100.0 * (a / total); 1009 var percent = 100.0 * (a / total);
962 return '${percent.toStringAsFixed(2)}%'; 1010 return '${percent.toStringAsFixed(2)}%';
963 } 1011 }
964 1012
965 CodeInstruction(this.address, this.machine, this.human); 1013 CodeInstruction(this.address, this.machine, this.human);
966 1014
1015 @reflectable bool get isComment => address == 0;
1016 @reflectable bool get hasDescriptors => descriptors.length > 0;
1017
967 @reflectable String formattedAddress() { 1018 @reflectable String formattedAddress() {
968 if (address == 0) { 1019 if (address == 0) {
969 return ''; 1020 return '';
970 } 1021 }
971 return '0x${address.toRadixString(16)}'; 1022 return '0x${address.toRadixString(16)}';
972 } 1023 }
973 1024
974 @reflectable String formattedInclusive(Code code) { 1025 @reflectable String formattedInclusive(Code code) {
975 if (code == null) { 1026 if (code == null) {
976 return ''; 1027 return '';
(...skipping 14 matching lines...) Expand all
991 if (code == null) { 1042 if (code == null) {
992 return ''; 1043 return '';
993 } 1044 }
994 var tick = code.addressTicks[address]; 1045 var tick = code.addressTicks[address];
995 if (tick == null) { 1046 if (tick == null) {
996 return ''; 1047 return '';
997 } 1048 }
998 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile); 1049 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile);
999 return '$pcent (${tick.exclusiveTicks})'; 1050 return '$pcent (${tick.exclusiveTicks})';
1000 } 1051 }
1052
1053 bool _isJumpInstruction() {
1054 return human.startsWith('j');
1055 }
1056
1057 int _getJumpAddress() {
1058 assert(_isJumpInstruction());
1059 var chunks = human.split(' ');
1060 if (chunks.length != 2) {
1061 // We expect jump instructions to be of the form 'j.. address'.
1062 return 0;
1063 }
1064 var address = chunks[1];
1065 if (address.startsWith('0x')) {
1066 // Chop off the 0x.
1067 address = address.substring(2);
1068 }
1069 try {
1070 return int.parse(address, radix:16);
1071 } catch (_) {
1072 return 0;
1073 }
1074 }
1075
1076 void _resolveJumpTarget(List<CodeInstruction> instructions) {
1077 if (!_isJumpInstruction()) {
1078 return;
1079 }
1080 int address = _getJumpAddress();
1081 if (address == 0) {
1082 // Could not determine jump address.
1083 print('Could not determine jump address for $human');
1084 return;
1085 }
1086 for (var i = 0; i < instructions.length; i++) {
1087 var instruction = instructions[i];
1088 if (instruction.address == address) {
1089 jumpTarget = instruction;
1090 return;
1091 }
1092 }
1093 print('Could not find instruction at ${address.toRadixString(16)}');
1094 }
1001 } 1095 }
1002 1096
1003 class CodeKind { 1097 class CodeKind {
1004 final _value; 1098 final _value;
1005 const CodeKind._internal(this._value); 1099 const CodeKind._internal(this._value);
1006 String toString() => '$_value'; 1100 String toString() => '$_value';
1007 1101
1008 static CodeKind fromString(String s) { 1102 static CodeKind fromString(String s) {
1009 if (s == 'Native') { 1103 if (s == 'Native') {
1010 return Native; 1104 return Native;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 @reflectable int startAddress = 0; 1143 @reflectable int startAddress = 0;
1050 @reflectable int endAddress = 0; 1144 @reflectable int endAddress = 0;
1051 @reflectable final callers = new List<CodeCallCount>(); 1145 @reflectable final callers = new List<CodeCallCount>();
1052 @reflectable final callees = new List<CodeCallCount>(); 1146 @reflectable final callees = new List<CodeCallCount>();
1053 @reflectable final instructions = new ObservableList<CodeInstruction>(); 1147 @reflectable final instructions = new ObservableList<CodeInstruction>();
1054 @reflectable final addressTicks = new ObservableMap<int, CodeTick>(); 1148 @reflectable final addressTicks = new ObservableMap<int, CodeTick>();
1055 @observable String formattedInclusiveTicks = ''; 1149 @observable String formattedInclusiveTicks = '';
1056 @observable String formattedExclusiveTicks = ''; 1150 @observable String formattedExclusiveTicks = '';
1057 @observable ServiceMap objectPool; 1151 @observable ServiceMap objectPool;
1058 @observable ServiceMap function; 1152 @observable ServiceMap function;
1153 @observable Script script;
1059 String name; 1154 String name;
1060 String vmName; 1155 String vmName;
1061 1156
1062 bool get canCache => true; 1157 bool get canCache => true;
1063 bool get immutable => true; 1158 bool get immutable => true;
1064 1159
1065 Code._empty(ServiceObjectOwner owner) : super._empty(owner); 1160 Code._empty(ServiceObjectOwner owner) : super._empty(owner);
1066 1161
1067 // Reset all data associated with a profile. 1162 // Reset all data associated with a profile.
1068 void resetProfileData() { 1163 void resetProfileData() {
1069 totalSamplesInProfile = 0; 1164 totalSamplesInProfile = 0;
1070 exclusiveTicks = 0; 1165 exclusiveTicks = 0;
1071 inclusiveTicks = 0; 1166 inclusiveTicks = 0;
1072 formattedInclusiveTicks = ''; 1167 formattedInclusiveTicks = '';
1073 formattedExclusiveTicks = ''; 1168 formattedExclusiveTicks = '';
1074 callers.clear(); 1169 callers.clear();
1075 callees.clear(); 1170 callees.clear();
1076 addressTicks.clear(); 1171 addressTicks.clear();
1077 } 1172 }
1078 1173
1174 void _updateDescriptors(Script script) {
1175 this.script = script;
1176 for (var instruction in instructions) {
1177 for (var descriptor in instruction.descriptors) {
1178 descriptor.processScript(script);
1179 }
1180 }
1181 }
1182
1183 void loadScript() {
1184 if (script != null) {
1185 // Already done.
1186 return;
1187 }
1188 if (kind != CodeKind.Dart){
1189 return;
1190 }
1191 if (function == null) {
1192 return;
1193 }
1194 if (function['script'] == null) {
1195 // Attempt to load the function.
1196 function.load().then((func) {
1197 var script = function['script'];
1198 if (script == null) {
1199 // Function doesn't have an associated script.
1200 return;
1201 }
1202 // Load the script and then update descriptors.
1203 script.load().then(_updateDescriptors);
1204 });
1205 return;
1206 }
1207 // Load the script and then update descriptors.
1208 function['script'].load().then(_updateDescriptors);
1209 }
1210
1079 /// Reload [this]. Returns a future which completes to [this] or 1211 /// Reload [this]. Returns a future which completes to [this] or
1080 /// a [ServiceError]. 1212 /// a [ServiceError].
1081 Future<ServiceObject> reload() { 1213 Future<ServiceObject> reload() {
1082 assert(kind != null); 1214 assert(kind != null);
1083 if (kind == CodeKind.Dart) { 1215 if (kind == CodeKind.Dart) {
1084 // We only reload Dart code. 1216 // We only reload Dart code.
1085 return super.reload(); 1217 return super.reload();
1086 } 1218 }
1087 return new Future.value(this); 1219 return new Future.value(this);
1088 } 1220 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 vmName = m['name']; 1269 vmName = m['name'];
1138 kind = CodeKind.fromString(m['kind']); 1270 kind = CodeKind.fromString(m['kind']);
1139 startAddress = int.parse(m['start'], radix:16); 1271 startAddress = int.parse(m['start'], radix:16);
1140 endAddress = int.parse(m['end'], radix:16); 1272 endAddress = int.parse(m['end'], radix:16);
1141 function = isolate.getFromMap(m['function']); 1273 function = isolate.getFromMap(m['function']);
1142 objectPool = isolate.getFromMap(m['object_pool']); 1274 objectPool = isolate.getFromMap(m['object_pool']);
1143 var disassembly = m['disassembly']; 1275 var disassembly = m['disassembly'];
1144 if (disassembly != null) { 1276 if (disassembly != null) {
1145 _processDisassembly(disassembly); 1277 _processDisassembly(disassembly);
1146 } 1278 }
1279 var descriptors = m['descriptors'];
1280 if (descriptors != null) {
1281 descriptors = descriptors['members'];
1282 _processDescriptors(descriptors);
1283 }
1147 // We are loaded if we have instructions or are not Dart code. 1284 // We are loaded if we have instructions or are not Dart code.
1148 _loaded = (instructions.length != 0) || (kind != CodeKind.Dart); 1285 _loaded = (instructions.length != 0) || (kind != CodeKind.Dart);
1149 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); 1286 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
1150 } 1287 }
1151 1288
1152 @observable bool hasDisassembly = false; 1289 @observable bool hasDisassembly = false;
1153 1290
1154 void _processDisassembly(List<String> disassembly){ 1291 void _processDisassembly(List<String> disassembly){
1155 assert(disassembly != null); 1292 assert(disassembly != null);
1156 instructions.clear(); 1293 instructions.clear();
1157 assert((disassembly.length % 3) == 0); 1294 assert((disassembly.length % 3) == 0);
1158 for (var i = 0; i < disassembly.length; i += 3) { 1295 for (var i = 0; i < disassembly.length; i += 3) {
1159 var address = 0; // Assume code comment. 1296 var address = 0; // Assume code comment.
1160 var machine = disassembly[i + 1]; 1297 var machine = disassembly[i + 1];
1161 var human = disassembly[i + 2]; 1298 var human = disassembly[i + 2];
1162 if (disassembly[i] != '') { 1299 if (disassembly[i] != '') {
1163 // Not a code comment, extract address. 1300 // Not a code comment, extract address.
1164 address = int.parse(disassembly[i]); 1301 address = int.parse(disassembly[i]);
1165 } 1302 }
1166 var instruction = new CodeInstruction(address, machine, human); 1303 var instruction = new CodeInstruction(address, machine, human);
1167 instructions.add(instruction); 1304 instructions.add(instruction);
1168 } 1305 }
1306 for (var instruction in instructions) {
1307 instruction._resolveJumpTarget(instructions);
1308 }
1309 }
1310
1311 void _processDescriptor(Map d) {
1312 var address = int.parse(d['pc'], radix:16);
1313 var deoptId = d['deoptId'];
1314 var tokenPos = d['tokenPos'];
1315 var tryIndex = d['tryIndex'];
1316 var kind = d['kind'].trim();
1317 for (var instruction in instructions) {
1318 if (instruction.address == address) {
1319 instruction.descriptors.add(new PcDescriptor(address,
1320 deoptId,
1321 tokenPos,
1322 tryIndex,
1323 kind));
1324 return;
1325 }
1326 }
1327 Logger.root.warning(
1328 'Could not find instruction with pc descriptor address: $address');
1329 }
1330
1331 void _processDescriptors(List<Map> descriptors) {
1332 for (Map descriptor in descriptors) {
1333 _processDescriptor(descriptor);
1334 }
1169 } 1335 }
1170 1336
1171 void _processTicks(List<String> profileTicks) { 1337 void _processTicks(List<String> profileTicks) {
1172 assert(profileTicks != null); 1338 assert(profileTicks != null);
1173 assert((profileTicks.length % 3) == 0); 1339 assert((profileTicks.length % 3) == 0);
1174 for (var i = 0; i < profileTicks.length; i += 3) { 1340 for (var i = 0; i < profileTicks.length; i += 3) {
1175 var address = int.parse(profileTicks[i], radix:16); 1341 var address = int.parse(profileTicks[i], radix:16);
1176 var exclusive = int.parse(profileTicks[i + 1]); 1342 var exclusive = int.parse(profileTicks[i + 1]);
1177 var inclusive = int.parse(profileTicks[i + 2]); 1343 var inclusive = int.parse(profileTicks[i + 2]);
1178 var tick = new CodeTick(address, exclusive, inclusive); 1344 var tick = new CodeTick(address, exclusive, inclusive);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 var v = list[i]; 1420 var v = list[i];
1255 if ((v is ObservableMap) && _isServiceMap(v)) { 1421 if ((v is ObservableMap) && _isServiceMap(v)) {
1256 list[i] = owner.getFromMap(v); 1422 list[i] = owner.getFromMap(v);
1257 } else if (v is ObservableList) { 1423 } else if (v is ObservableList) {
1258 _upgradeObservableList(v, owner); 1424 _upgradeObservableList(v, owner);
1259 } else if (v is ObservableMap) { 1425 } else if (v is ObservableMap) {
1260 _upgradeObservableMap(v, owner); 1426 _upgradeObservableMap(v, owner);
1261 } 1427 }
1262 } 1428 }
1263 } 1429 }
OLDNEW
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/elements/vm_view.html ('k') | runtime/bin/vmservice/client/notdotdot.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698