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

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 @observable PcDescriptor descriptor;
turnidge 2014/04/28 17:41:49 from offline: support multiple descriptors.
Cutch 2014/04/28 22:48:00 Done.
959 1006
960 static String formatPercent(num a, num total) { 1007 static String formatPercent(num a, num total) {
961 var percent = 100.0 * (a / total); 1008 var percent = 100.0 * (a / total);
962 return '${percent.toStringAsFixed(2)}%'; 1009 return '${percent.toStringAsFixed(2)}%';
963 } 1010 }
964 1011
965 CodeInstruction(this.address, this.machine, this.human); 1012 CodeInstruction(this.address, this.machine, this.human);
966 1013
1014 @reflectable bool get isComment => address == 0;
1015 @reflectable bool get hasDescriptor => descriptor != null;
1016
967 @reflectable String formattedAddress() { 1017 @reflectable String formattedAddress() {
968 if (address == 0) { 1018 if (address == 0) {
969 return ''; 1019 return '';
970 } 1020 }
971 return '0x${address.toRadixString(16)}'; 1021 return '0x${address.toRadixString(16)}';
972 } 1022 }
973 1023
974 @reflectable String formattedInclusive(Code code) { 1024 @reflectable String formattedInclusive(Code code) {
975 if (code == null) { 1025 if (code == null) {
976 return ''; 1026 return '';
(...skipping 14 matching lines...) Expand all
991 if (code == null) { 1041 if (code == null) {
992 return ''; 1042 return '';
993 } 1043 }
994 var tick = code.addressTicks[address]; 1044 var tick = code.addressTicks[address];
995 if (tick == null) { 1045 if (tick == null) {
996 return ''; 1046 return '';
997 } 1047 }
998 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile); 1048 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile);
999 return '$pcent (${tick.exclusiveTicks})'; 1049 return '$pcent (${tick.exclusiveTicks})';
1000 } 1050 }
1051
1052 bool _isJumpInstruction() {
1053 return human.startsWith('j');
1054 }
1055
1056 int _getJumpAddress() {
1057 assert(_isJumpInstruction());
1058 var chunks = human.split(' ');
1059 if (chunks.length != 2) {
1060 // We expect jump instructions to be of the form 'j.. address'.
1061 return 0;
1062 }
1063 var address = chunks[1];
1064 if (address.startsWith('0x')) {
1065 // Chop off the 0x.
1066 address = address.substring(2);
1067 }
1068 try {
1069 return int.parse(address, radix:16);
1070 } catch (_) {
1071 return 0;
1072 }
1073 }
1074
1075 void _resolveJumpTarget(List<CodeInstruction> instructions) {
1076 if (!_isJumpInstruction()) {
1077 return;
1078 }
1079 int address = _getJumpAddress();
1080 if (address == 0) {
1081 // Could not determine jump address.
1082 print('Could not determine jump address for $human');
1083 return;
1084 }
1085 for (var i = 0; i < instructions.length; i++) {
1086 var instruction = instructions[i];
1087 if (instruction.address == address) {
1088 jumpTarget = instruction;
1089 return;
1090 }
1091 }
1092 print('Could not find instruction at ${address.toRadixString(16)}');
1093 }
1001 } 1094 }
1002 1095
1003 class CodeKind { 1096 class CodeKind {
1004 final _value; 1097 final _value;
1005 const CodeKind._internal(this._value); 1098 const CodeKind._internal(this._value);
1006 String toString() => '$_value'; 1099 String toString() => '$_value';
1007 1100
1008 static CodeKind fromString(String s) { 1101 static CodeKind fromString(String s) {
1009 if (s == 'Native') { 1102 if (s == 'Native') {
1010 return Native; 1103 return Native;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 @reflectable int startAddress = 0; 1142 @reflectable int startAddress = 0;
1050 @reflectable int endAddress = 0; 1143 @reflectable int endAddress = 0;
1051 @reflectable final callers = new List<CodeCallCount>(); 1144 @reflectable final callers = new List<CodeCallCount>();
1052 @reflectable final callees = new List<CodeCallCount>(); 1145 @reflectable final callees = new List<CodeCallCount>();
1053 @reflectable final instructions = new ObservableList<CodeInstruction>(); 1146 @reflectable final instructions = new ObservableList<CodeInstruction>();
1054 @reflectable final addressTicks = new ObservableMap<int, CodeTick>(); 1147 @reflectable final addressTicks = new ObservableMap<int, CodeTick>();
1055 @observable String formattedInclusiveTicks = ''; 1148 @observable String formattedInclusiveTicks = '';
1056 @observable String formattedExclusiveTicks = ''; 1149 @observable String formattedExclusiveTicks = '';
1057 @observable ServiceMap objectPool; 1150 @observable ServiceMap objectPool;
1058 @observable ServiceMap function; 1151 @observable ServiceMap function;
1152 @observable Script script;
1059 String name; 1153 String name;
1060 String vmName; 1154 String vmName;
1061 1155
1062 bool get canCache => true; 1156 bool get canCache => true;
1063 bool get immutable => true; 1157 bool get immutable => true;
1064 1158
1065 Code._empty(ServiceObjectOwner owner) : super._empty(owner); 1159 Code._empty(ServiceObjectOwner owner) : super._empty(owner);
1066 1160
1067 // Reset all data associated with a profile. 1161 // Reset all data associated with a profile.
1068 void resetProfileData() { 1162 void resetProfileData() {
1069 totalSamplesInProfile = 0; 1163 totalSamplesInProfile = 0;
1070 exclusiveTicks = 0; 1164 exclusiveTicks = 0;
1071 inclusiveTicks = 0; 1165 inclusiveTicks = 0;
1072 formattedInclusiveTicks = ''; 1166 formattedInclusiveTicks = '';
1073 formattedExclusiveTicks = ''; 1167 formattedExclusiveTicks = '';
1074 callers.clear(); 1168 callers.clear();
1075 callees.clear(); 1169 callees.clear();
1076 addressTicks.clear(); 1170 addressTicks.clear();
1077 } 1171 }
1078 1172
1173 void _updateDescriptors(Script script) {
1174 this.script = script;
1175 for (var instruction in instructions) {
1176 if (instruction.descriptor != null) {
1177 instruction.descriptor.processScript(script);
1178 }
1179 }
1180 }
1181
1182 void loadScript() {
1183 if (script != null) {
1184 // Already done.
1185 return;
1186 }
1187 if (kind != CodeKind.Dart){
1188 return;
1189 }
1190 if (function == null) {
1191 return;
1192 }
1193 if (function['script'] == null) {
1194 // Attempt to load the function.
1195 function.load().then((func) {
1196 var script = function['script'];
1197 if (script == null) {
1198 // Function doesn't have an associated script.
1199 return;
1200 }
1201 // Load the script and then update descriptors.
1202 script.load().then(_updateDescriptors);
1203 });
1204 return;
1205 }
1206 // Load the script and then update descriptors.
1207 function['script'].load().then(_updateDescriptors);
1208 }
1209
1079 /// Reload [this]. Returns a future which completes to [this] or 1210 /// Reload [this]. Returns a future which completes to [this] or
1080 /// a [ServiceError]. 1211 /// a [ServiceError].
1081 Future<ServiceObject> reload() { 1212 Future<ServiceObject> reload() {
1082 assert(kind != null); 1213 assert(kind != null);
1083 if (kind == CodeKind.Dart) { 1214 if (kind == CodeKind.Dart) {
1084 // We only reload Dart code. 1215 // We only reload Dart code.
1085 return super.reload(); 1216 return super.reload();
1086 } 1217 }
1087 return new Future.value(this); 1218 return new Future.value(this);
1088 } 1219 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 vmName = m['name']; 1268 vmName = m['name'];
1138 kind = CodeKind.fromString(m['kind']); 1269 kind = CodeKind.fromString(m['kind']);
1139 startAddress = int.parse(m['start'], radix:16); 1270 startAddress = int.parse(m['start'], radix:16);
1140 endAddress = int.parse(m['end'], radix:16); 1271 endAddress = int.parse(m['end'], radix:16);
1141 function = isolate.getFromMap(m['function']); 1272 function = isolate.getFromMap(m['function']);
1142 objectPool = isolate.getFromMap(m['object_pool']); 1273 objectPool = isolate.getFromMap(m['object_pool']);
1143 var disassembly = m['disassembly']; 1274 var disassembly = m['disassembly'];
1144 if (disassembly != null) { 1275 if (disassembly != null) {
1145 _processDisassembly(disassembly); 1276 _processDisassembly(disassembly);
1146 } 1277 }
1278 var descriptors = m['descriptors'];
1279 if (descriptors != null) {
1280 descriptors = descriptors['members'];
1281 _processDescriptors(descriptors);
1282 }
1147 // We are loaded if we have instructions or are not Dart code. 1283 // We are loaded if we have instructions or are not Dart code.
1148 _loaded = (instructions.length != 0) || (kind != CodeKind.Dart); 1284 _loaded = (instructions.length != 0) || (kind != CodeKind.Dart);
1149 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); 1285 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
1150 } 1286 }
1151 1287
1152 @observable bool hasDisassembly = false; 1288 @observable bool hasDisassembly = false;
1153 1289
1154 void _processDisassembly(List<String> disassembly){ 1290 void _processDisassembly(List<String> disassembly){
1155 assert(disassembly != null); 1291 assert(disassembly != null);
1156 instructions.clear(); 1292 instructions.clear();
1157 assert((disassembly.length % 3) == 0); 1293 assert((disassembly.length % 3) == 0);
1158 for (var i = 0; i < disassembly.length; i += 3) { 1294 for (var i = 0; i < disassembly.length; i += 3) {
1159 var address = 0; // Assume code comment. 1295 var address = 0; // Assume code comment.
1160 var machine = disassembly[i + 1]; 1296 var machine = disassembly[i + 1];
1161 var human = disassembly[i + 2]; 1297 var human = disassembly[i + 2];
1162 if (disassembly[i] != '') { 1298 if (disassembly[i] != '') {
1163 // Not a code comment, extract address. 1299 // Not a code comment, extract address.
1164 address = int.parse(disassembly[i]); 1300 address = int.parse(disassembly[i]);
1165 } 1301 }
1166 var instruction = new CodeInstruction(address, machine, human); 1302 var instruction = new CodeInstruction(address, machine, human);
1167 instructions.add(instruction); 1303 instructions.add(instruction);
1168 } 1304 }
1305 for (var instruction in instructions) {
1306 instruction._resolveJumpTarget(instructions);
1307 }
1308 }
1309
1310 void _processDescriptor(Map d) {
1311 var address = int.parse(d['pc'], radix:16);
1312 var deoptId = d['deoptId'];
1313 var tokenPos = d['tokenPos'];
1314 var tryIndex = d['tryIndex'];
1315 var kind = d['kind'].trim();
1316 for (var instruction in instructions) {
1317 if (instruction.address == address) {
1318 instruction.descriptor = new PcDescriptor(address,
1319 deoptId,
1320 tokenPos,
1321 tryIndex,
1322 kind);
1323 return;
1324 }
1325 }
1326 Logger.root.warning(
1327 'Could not find instruction with pc descriptor address: $address');
1328 }
1329
1330 void _processDescriptors(List<Map> descriptors) {
1331 for (Map descriptor in descriptors) {
1332 _processDescriptor(descriptor);
1333 }
1169 } 1334 }
1170 1335
1171 void _processTicks(List<String> profileTicks) { 1336 void _processTicks(List<String> profileTicks) {
1172 assert(profileTicks != null); 1337 assert(profileTicks != null);
1173 assert((profileTicks.length % 3) == 0); 1338 assert((profileTicks.length % 3) == 0);
1174 for (var i = 0; i < profileTicks.length; i += 3) { 1339 for (var i = 0; i < profileTicks.length; i += 3) {
1175 var address = int.parse(profileTicks[i], radix:16); 1340 var address = int.parse(profileTicks[i], radix:16);
1176 var exclusive = int.parse(profileTicks[i + 1]); 1341 var exclusive = int.parse(profileTicks[i + 1]);
1177 var inclusive = int.parse(profileTicks[i + 2]); 1342 var inclusive = int.parse(profileTicks[i + 2]);
1178 var tick = new CodeTick(address, exclusive, inclusive); 1343 var tick = new CodeTick(address, exclusive, inclusive);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 var v = list[i]; 1419 var v = list[i];
1255 if ((v is ObservableMap) && _isServiceMap(v)) { 1420 if ((v is ObservableMap) && _isServiceMap(v)) {
1256 list[i] = owner.getFromMap(v); 1421 list[i] = owner.getFromMap(v);
1257 } else if (v is ObservableList) { 1422 } else if (v is ObservableList) {
1258 _upgradeObservableList(v, owner); 1423 _upgradeObservableList(v, owner);
1259 } else if (v is ObservableMap) { 1424 } else if (v is ObservableMap) {
1260 _upgradeObservableMap(v, owner); 1425 _upgradeObservableMap(v, owner);
1261 } 1426 }
1262 } 1427 }
1263 } 1428 }
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