| OLD | NEW |
| 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 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 291 |
| 292 /// Default handler for coverage data. | 292 /// Default handler for coverage data. |
| 293 void processCoverageData(List coverageData) { | 293 void processCoverageData(List coverageData) { |
| 294 coverageData.forEach((scriptCoverage) { | 294 coverageData.forEach((scriptCoverage) { |
| 295 assert(scriptCoverage['script'] != null); | 295 assert(scriptCoverage['script'] != null); |
| 296 scriptCoverage['script']._processHits(scriptCoverage['hits']); | 296 scriptCoverage['script']._processHits(scriptCoverage['hits']); |
| 297 }); | 297 }); |
| 298 } | 298 } |
| 299 | 299 |
| 300 Future refreshCoverage() { | 300 Future refreshCoverage() { |
| 301 return vm.getAsMap(relativeLink('coverage')).then((ObservableMap map) { | 301 Map params = {}; |
| 302 var coverageOwner = (type == 'Isolate') ? this : owner; | 302 if (this is! Isolate) { |
| 303 var coverage = new ServiceObject._fromMap(coverageOwner, map); | 303 params['targetId'] = id; |
| 304 assert(coverage.type == 'CodeCoverage'); | 304 } |
| 305 var coverageList = coverage['coverage']; | 305 return isolate.invokeRpcNoUpgrade('getCoverage', params).then( |
| 306 assert(coverageList != null); | 306 (ObservableMap map) { |
| 307 processCoverageData(coverageList); | 307 var coverageOwner = (type == 'Isolate') ? this : owner; |
| 308 }); | 308 var coverage = new ServiceObject._fromMap(coverageOwner, map); |
| 309 assert(coverage.type == 'CodeCoverage'); |
| 310 var coverageList = coverage['coverage']; |
| 311 assert(coverageList != null); |
| 312 processCoverageData(coverageList); |
| 313 }); |
| 309 } | 314 } |
| 310 } | 315 } |
| 311 | 316 |
| 312 abstract class ServiceObjectOwner extends ServiceObject { | 317 abstract class ServiceObjectOwner extends ServiceObject { |
| 313 /// Creates an empty [ServiceObjectOwner]. | 318 /// Creates an empty [ServiceObjectOwner]. |
| 314 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); | 319 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); |
| 315 | 320 |
| 316 /// Builds a [ServiceObject] corresponding to the [id] from [map]. | 321 /// Builds a [ServiceObject] corresponding to the [id] from [map]. |
| 317 /// The result may come from the cache. The result will not necessarily | 322 /// The result may come from the cache. The result will not necessarily |
| 318 /// be [loaded]. | 323 /// be [loaded]. |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 | 491 |
| 487 Future<ObservableMap> _processMap(ObservableMap map) { | 492 Future<ObservableMap> _processMap(ObservableMap map) { |
| 488 // Verify that the top level response is a service map. | 493 // Verify that the top level response is a service map. |
| 489 if (!_isServiceMap(map)) { | 494 if (!_isServiceMap(map)) { |
| 490 return new Future.error( | 495 return new Future.error( |
| 491 new ServiceObject._fromMap(this, toObservable({ | 496 new ServiceObject._fromMap(this, toObservable({ |
| 492 'type': 'ServiceException', | 497 'type': 'ServiceException', |
| 493 'id': '', | 498 'id': '', |
| 494 'kind': 'FormatException', | 499 'kind': 'FormatException', |
| 495 'response': map, | 500 'response': map, |
| 496 'message': 'Top level service responses must be service maps.', | 501 'message': 'Top level service responses must be service maps: ${map}.', |
| 497 }))); | 502 }))); |
| 498 } | 503 } |
| 499 // Preemptively capture ServiceError and ServiceExceptions. | 504 // Preemptively capture ServiceError and ServiceExceptions. |
| 500 if (map['type'] == 'ServiceError') { | 505 if (map['type'] == 'ServiceError') { |
| 501 return new Future.error(new ServiceObject._fromMap(this, map)); | 506 return new Future.error(new ServiceObject._fromMap(this, map)); |
| 502 } else if (map['type'] == 'ServiceException') { | 507 } else if (map['type'] == 'ServiceException') { |
| 503 return new Future.error(new ServiceObject._fromMap(this, map)); | 508 return new Future.error(new ServiceObject._fromMap(this, map)); |
| 504 } | 509 } |
| 505 // map is now guaranteed to be a non-error/exception ServiceObject. | 510 // map is now guaranteed to be a non-error/exception ServiceObject. |
| 506 return new Future.value(map); | 511 return new Future.value(map); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 return new Future.error(error); | 543 return new Future.error(error); |
| 539 }, test: (e) => e is ServiceError).catchError((exception) { | 544 }, test: (e) => e is ServiceError).catchError((exception) { |
| 540 // ServiceException, forward to VM's ServiceException stream. | 545 // ServiceException, forward to VM's ServiceException stream. |
| 541 exceptions.add(exception); | 546 exceptions.add(exception); |
| 542 return new Future.error(exception); | 547 return new Future.error(exception); |
| 543 }, test: (e) => e is ServiceException); | 548 }, test: (e) => e is ServiceException); |
| 544 } | 549 } |
| 545 | 550 |
| 546 /// Get [id] as a [String] from the service directly. See [getAsMap]. | 551 /// Get [id] as a [String] from the service directly. See [getAsMap]. |
| 547 Future<String> getString(String id); | 552 Future<String> getString(String id); |
| 553 |
| 554 // Implemented in subclass. |
| 555 Future<String> invokeRpcRaw(String method, Map params); |
| 556 |
| 557 Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) { |
| 558 return invokeRpcRaw(method, params).then((String response) { |
| 559 var map = _parseJSON(response); |
| 560 if (Tracer.current != null) { |
| 561 Tracer.current.trace("Received response for ${method}/${params}}", |
| 562 map:map); |
| 563 } |
| 564 |
| 565 // Check for ill-formed responses. |
| 566 return _processMap(map); |
| 567 }).catchError((error) { |
| 568 |
| 569 // ServiceError, forward to VM's ServiceError stream. |
| 570 errors.add(error); |
| 571 return new Future.error(error); |
| 572 }, test: (e) => e is ServiceError).catchError((exception) { |
| 573 |
| 574 // ServiceException, forward to VM's ServiceException stream. |
| 575 exceptions.add(exception); |
| 576 return new Future.error(exception); |
| 577 }, test: (e) => e is ServiceException); |
| 578 } |
| 579 |
| 580 Future<ServiceObject> invokeRpc(String method, Map params) { |
| 581 // TODO(turnidge): Once we start implementing "get" requests |
| 582 // through the JsonRpc interface, we will need to start checking the |
| 583 // cache before making the request here. For now, we just make the |
| 584 // request without bothering with the cache. |
| 585 return invokeRpcNoUpgrade(method, params).then((ObservableMap response) { |
| 586 var obj = new ServiceObject._fromMap(this, response); |
| 587 // TODO(turnidge): Put the object into the cache if we can. |
| 588 return obj; |
| 589 }); |
| 590 } |
| 591 |
| 548 /// Force the VM to disconnect. | 592 /// Force the VM to disconnect. |
| 549 void disconnect(); | 593 void disconnect(); |
| 550 /// Completes when the VM first connects. | 594 /// Completes when the VM first connects. |
| 551 Future get onConnect; | 595 Future get onConnect; |
| 552 /// Completes when the VM disconnects or there was an error connecting. | 596 /// Completes when the VM disconnects or there was an error connecting. |
| 553 Future get onDisconnect; | 597 Future get onDisconnect; |
| 554 | 598 |
| 555 void _update(ObservableMap map, bool mapIsRef) { | 599 void _update(ObservableMap map, bool mapIsRef) { |
| 556 if (mapIsRef) { | 600 if (mapIsRef) { |
| 557 return; | 601 return; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 | 791 |
| 748 static const TAG_ROOT_ID = 'code/tag-0'; | 792 static const TAG_ROOT_ID = 'code/tag-0'; |
| 749 | 793 |
| 750 /// Returns the Code object for the root tag. | 794 /// Returns the Code object for the root tag. |
| 751 Code tagRoot() { | 795 Code tagRoot() { |
| 752 // TODO(turnidge): Use get() here instead? | 796 // TODO(turnidge): Use get() here instead? |
| 753 return _cache[TAG_ROOT_ID]; | 797 return _cache[TAG_ROOT_ID]; |
| 754 } | 798 } |
| 755 | 799 |
| 756 void processProfile(ServiceMap profile) { | 800 void processProfile(ServiceMap profile) { |
| 757 assert(profile.type == 'Profile'); | 801 assert(profile.type == 'CpuProfile'); |
| 758 var codeTable = new List<Code>(); | 802 var codeTable = new List<Code>(); |
| 759 var codeRegions = profile['codes']; | 803 var codeRegions = profile['codes']; |
| 760 for (var codeRegion in codeRegions) { | 804 for (var codeRegion in codeRegions) { |
| 761 Code code = codeRegion['code']; | 805 Code code = codeRegion['code']; |
| 762 assert(code != null); | 806 assert(code != null); |
| 763 codeTable.add(code); | 807 codeTable.add(code); |
| 764 } | 808 } |
| 765 _resetProfileData(); | 809 _resetProfileData(); |
| 766 _updateProfileData(profile, codeTable); | 810 _updateProfileData(profile, codeTable); |
| 767 var exclusiveTrie = profile['exclusive_trie']; | 811 var exclusiveTrie = profile['exclusive_trie']; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // Cache miss. Get the object from the vm directly. | 895 // Cache miss. Get the object from the vm directly. |
| 852 return vm.getAsMap(relativeLink(id)).then((ObservableMap map) { | 896 return vm.getAsMap(relativeLink(id)).then((ObservableMap map) { |
| 853 var obj = new ServiceObject._fromMap(this, map); | 897 var obj = new ServiceObject._fromMap(this, map); |
| 854 if (obj.canCache) { | 898 if (obj.canCache) { |
| 855 _cache.putIfAbsent(id, () => obj); | 899 _cache.putIfAbsent(id, () => obj); |
| 856 } | 900 } |
| 857 return obj; | 901 return obj; |
| 858 }); | 902 }); |
| 859 } | 903 } |
| 860 | 904 |
| 905 Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) { |
| 906 params['isolate'] = id; |
| 907 return vm.invokeRpcNoUpgrade(method, params); |
| 908 } |
| 909 |
| 910 |
| 911 Future<ServiceObject> invokeRpc(String method, Map params) { |
| 912 return invokeRpcNoUpgrade(method, params).then((ObservableMap response) { |
| 913 // TODO - needs to cache!!! move to constructor? |
| 914 return new ServiceObject._fromMap(this, response); |
| 915 }); |
| 916 } |
| 917 |
| 861 @observable Class objectClass; | 918 @observable Class objectClass; |
| 862 @observable final rootClasses = new ObservableList<Class>(); | 919 @observable final rootClasses = new ObservableList<Class>(); |
| 863 | 920 |
| 864 @observable Library rootLib; | 921 @observable Library rootLib; |
| 865 @observable ObservableList<Library> libraries = | 922 @observable ObservableList<Library> libraries = |
| 866 new ObservableList<Library>(); | 923 new ObservableList<Library>(); |
| 867 @observable ObservableMap topFrame; | 924 @observable ObservableMap topFrame; |
| 868 | 925 |
| 869 @observable String name; | 926 @observable String name; |
| 870 @observable String vmName; | 927 @observable String vmName; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 883 @observable HeapSnapshot latestSnapshot; | 940 @observable HeapSnapshot latestSnapshot; |
| 884 Completer<HeapSnapshot> _snapshotFetch; | 941 Completer<HeapSnapshot> _snapshotFetch; |
| 885 | 942 |
| 886 void loadHeapSnapshot(ServiceEvent event) { | 943 void loadHeapSnapshot(ServiceEvent event) { |
| 887 latestSnapshot = new HeapSnapshot(this, event.data); | 944 latestSnapshot = new HeapSnapshot(this, event.data); |
| 888 _snapshotFetch.complete(latestSnapshot); | 945 _snapshotFetch.complete(latestSnapshot); |
| 889 } | 946 } |
| 890 | 947 |
| 891 Future<HeapSnapshot> fetchHeapSnapshot() { | 948 Future<HeapSnapshot> fetchHeapSnapshot() { |
| 892 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { | 949 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { |
| 893 get('graph'); | |
| 894 _snapshotFetch = new Completer<HeapSnapshot>(); | 950 _snapshotFetch = new Completer<HeapSnapshot>(); |
| 951 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); |
| 895 } | 952 } |
| 896 return _snapshotFetch.future; | 953 return _snapshotFetch.future; |
| 897 } | 954 } |
| 898 | 955 |
| 899 void updateHeapsFromMap(ObservableMap map) { | 956 void updateHeapsFromMap(ObservableMap map) { |
| 900 newSpace.update(map['new']); | 957 newSpace.update(map['new']); |
| 901 oldSpace.update(map['old']); | 958 oldSpace.update(map['old']); |
| 902 } | 959 } |
| 903 | 960 |
| 904 void _update(ObservableMap map, bool mapIsRef) { | 961 void _update(ObservableMap map, bool mapIsRef) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 running = (!_isPaused && map['topFrame'] != null); | 1036 running = (!_isPaused && map['topFrame'] != null); |
| 980 idle = (!_isPaused && map['topFrame'] == null); | 1037 idle = (!_isPaused && map['topFrame'] == null); |
| 981 error = map['error']; | 1038 error = map['error']; |
| 982 | 1039 |
| 983 libraries.clear(); | 1040 libraries.clear(); |
| 984 libraries.addAll(map['libraries']); | 1041 libraries.addAll(map['libraries']); |
| 985 libraries.sort(ServiceObject.LexicalSortName); | 1042 libraries.sort(ServiceObject.LexicalSortName); |
| 986 } | 1043 } |
| 987 | 1044 |
| 988 Future<TagProfile> updateTagProfile() { | 1045 Future<TagProfile> updateTagProfile() { |
| 989 return vm.getAsMap(relativeLink('profile/tag')).then((ObservableMap m) { | 1046 return isolate.invokeRpcNoUpgrade('getTagProfile', {}).then( |
| 990 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; | 1047 (ObservableMap map) { |
| 991 tagProfile._processTagProfile(seconds, m); | 1048 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; |
| 992 return tagProfile; | 1049 tagProfile._processTagProfile(seconds, map); |
| 993 }); | 1050 return tagProfile; |
| 1051 }); |
| 994 } | 1052 } |
| 995 | 1053 |
| 996 @reflectable CodeTrieNode profileTrieRoot; | 1054 @reflectable CodeTrieNode profileTrieRoot; |
| 997 // The profile trie is serialized as a list of integers. Each node | 1055 // The profile trie is serialized as a list of integers. Each node |
| 998 // is recreated by consuming some portion of the list. The format is as | 1056 // is recreated by consuming some portion of the list. The format is as |
| 999 // follows: | 1057 // follows: |
| 1000 // [0] index into codeTable of code object. | 1058 // [0] index into codeTable of code object. |
| 1001 // [1] tick count (number of times this stack frame occured). | 1059 // [1] tick count (number of times this stack frame occured). |
| 1002 // [2] child node count | 1060 // [2] child node count |
| 1003 // Reading the trie is done by recursively reading the tree depth-first | 1061 // Reading the trie is done by recursively reading the tree depth-first |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1031 var children = _trieData[_trieDataCursor++]; | 1089 var children = _trieData[_trieDataCursor++]; |
| 1032 // Recursively read child nodes. | 1090 // Recursively read child nodes. |
| 1033 for (var i = 0; i < children; i++) { | 1091 for (var i = 0; i < children; i++) { |
| 1034 var child = _readTrieNode(codeTable); | 1092 var child = _readTrieNode(codeTable); |
| 1035 node.children.add(child); | 1093 node.children.add(child); |
| 1036 node.summedChildCount += child.count; | 1094 node.summedChildCount += child.count; |
| 1037 } | 1095 } |
| 1038 return node; | 1096 return node; |
| 1039 } | 1097 } |
| 1040 | 1098 |
| 1099 // TODO(turnidge): Make this an ObservableList instead. |
| 1041 ServiceMap breakpoints; | 1100 ServiceMap breakpoints; |
| 1042 | 1101 |
| 1043 void _removeBreakpoint(ServiceMap bpt) { | 1102 void _removeBreakpoint(ServiceMap bpt) { |
| 1044 var script = bpt['location']['script']; | 1103 var script = bpt['location']['script']; |
| 1045 var tokenPos = bpt['location']['tokenPos']; | 1104 var tokenPos = bpt['location']['tokenPos']; |
| 1046 assert(tokenPos != null); | 1105 assert(tokenPos != null); |
| 1047 if (script.loaded) { | 1106 if (script.loaded) { |
| 1048 var line = script.tokenToLine(tokenPos); | 1107 var line = script.tokenToLine(tokenPos); |
| 1049 assert(line != null); | 1108 assert(line != null); |
| 1050 assert(script.lines[line - 1].bpt == bpt); | 1109 if (script.lines[line - 1] != null) { |
| 1051 script.lines[line - 1].bpt = null; | 1110 assert(script.lines[line - 1].bpt == bpt); |
| 1111 script.lines[line - 1].bpt = null; |
| 1112 } |
| 1052 } | 1113 } |
| 1053 } | 1114 } |
| 1054 | 1115 |
| 1055 void _addBreakpoint(ServiceMap bpt) { | 1116 void _addBreakpoint(ServiceMap bpt) { |
| 1056 var script = bpt['location']['script']; | 1117 var script = bpt['location']['script']; |
| 1057 var tokenPos = bpt['location']['tokenPos']; | 1118 var tokenPos = bpt['location']['tokenPos']; |
| 1058 assert(tokenPos != null); | 1119 assert(tokenPos != null); |
| 1059 if (script.loaded) { | 1120 if (script.loaded) { |
| 1060 var line = script.tokenToLine(tokenPos); | 1121 var line = script.tokenToLine(tokenPos); |
| 1061 assert(line != null); | 1122 assert(line != null); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1083 breakpoints = newBreakpoints; | 1144 breakpoints = newBreakpoints; |
| 1084 } | 1145 } |
| 1085 | 1146 |
| 1086 Future<ServiceObject> _inProgressReloadBpts; | 1147 Future<ServiceObject> _inProgressReloadBpts; |
| 1087 | 1148 |
| 1088 Future reloadBreakpoints() { | 1149 Future reloadBreakpoints() { |
| 1089 // TODO(turnidge): Can reusing the Future here ever cause us to | 1150 // TODO(turnidge): Can reusing the Future here ever cause us to |
| 1090 // get stale breakpoints? | 1151 // get stale breakpoints? |
| 1091 if (_inProgressReloadBpts == null) { | 1152 if (_inProgressReloadBpts == null) { |
| 1092 _inProgressReloadBpts = | 1153 _inProgressReloadBpts = |
| 1093 get('debug/breakpoints').then((newBpts) { | 1154 invokeRpc('getBreakpoints', {}).then((newBpts) { |
| 1094 _updateBreakpoints(newBpts); | 1155 _updateBreakpoints(newBpts); |
| 1095 }).whenComplete(() { | 1156 }).whenComplete(() { |
| 1096 _inProgressReloadBpts = null; | 1157 _inProgressReloadBpts = null; |
| 1097 }); | 1158 }); |
| 1098 } | 1159 } |
| 1099 return _inProgressReloadBpts; | 1160 return _inProgressReloadBpts; |
| 1100 } | 1161 } |
| 1101 | 1162 |
| 1102 Future<ServiceObject> setBreakpoint(Script script, int line) { | 1163 Future<ServiceObject> addBreakpoint(Script script, int line) { |
| 1103 return get(script.id + "/setBreakpoint?line=${line}").then((result) { | 1164 // TODO(turnidge): Pass line as an int instead of a string. |
| 1104 if (result is DartError) { | 1165 return invokeRpc('addBreakpoint', |
| 1166 { 'script': script.id, 'line': '$line' }).then((result) { |
| 1167 if (result is ServiceMap && |
| 1168 result.type == 'Breakpoint' && |
| 1169 result['resolved'] && |
| 1170 script.loaded && |
| 1171 script.tokenToLine(result['location']['tokenPos']) != line) { |
| 1105 // Unable to set a breakpoint at desired line. | 1172 // Unable to set a breakpoint at desired line. |
| 1106 script.lines[line - 1].possibleBpt = false; | 1173 script.lines[line - 1].possibleBpt = false; |
| 1107 } | 1174 } |
| 1108 return reloadBreakpoints(); | 1175 // TODO(turnidge): Instead of reloading all of the breakpoints, |
| 1176 // rely on events to update the breakpoint list. |
| 1177 return reloadBreakpoints().then((_) { |
| 1178 return result; |
| 1179 }); |
| 1109 }); | 1180 }); |
| 1110 } | 1181 } |
| 1111 | 1182 |
| 1112 Future clearBreakpoint(ServiceMap bpt) { | 1183 Future removeBreakpoint(ServiceMap bpt) { |
| 1113 return get('${bpt.id}/clear').then((result) { | 1184 return invokeRpc('removeBreakpoint', |
| 1185 { 'breakpointId': bpt.id }).then((result) { |
| 1114 if (result is DartError) { | 1186 if (result is DartError) { |
| 1115 // TODO(turnidge): Handle this more gracefully. | 1187 // TODO(turnidge): Handle this more gracefully. |
| 1116 Logger.root.severe(result.message); | 1188 Logger.root.severe(result.message); |
| 1117 } | 1189 } |
| 1118 if (pauseEvent != null && | 1190 if (pauseEvent != null && |
| 1119 pauseEvent.breakpoint != null && | 1191 pauseEvent.breakpoint != null && |
| 1120 (pauseEvent.breakpoint['id'] == bpt['id'])) { | 1192 (pauseEvent.breakpoint['id'] == bpt['id'])) { |
| 1121 return isolate.reload(); | 1193 return isolate.reload(); |
| 1122 } else { | 1194 } else { |
| 1123 return reloadBreakpoints(); | 1195 return reloadBreakpoints(); |
| 1124 } | 1196 } |
| 1125 }); | 1197 }); |
| 1126 } | 1198 } |
| 1127 | 1199 |
| 1128 Future pause() { | 1200 Future pause() { |
| 1129 return get("debug/pause").then((result) { | 1201 return invokeRpc('pause', {}).then((result) { |
| 1130 if (result is DartError) { | 1202 if (result is DartError) { |
| 1131 // TODO(turnidge): Handle this more gracefully. | 1203 // TODO(turnidge): Handle this more gracefully. |
| 1132 Logger.root.severe(result.message); | 1204 Logger.root.severe(result.message); |
| 1133 } | 1205 } |
| 1134 return isolate.reload(); | 1206 return isolate.reload(); |
| 1135 }); | 1207 }); |
| 1136 } | 1208 } |
| 1137 | 1209 |
| 1138 Future resume() { | 1210 Future resume() { |
| 1139 return get("debug/resume").then((result) { | 1211 return invokeRpc('resume', {}).then((result) { |
| 1140 if (result is DartError) { | 1212 if (result is DartError) { |
| 1141 // TODO(turnidge): Handle this more gracefully. | 1213 // TODO(turnidge): Handle this more gracefully. |
| 1142 Logger.root.severe(result.message); | 1214 Logger.root.severe(result.message); |
| 1143 } | 1215 } |
| 1144 return isolate.reload(); | 1216 return isolate.reload(); |
| 1145 }); | 1217 }); |
| 1146 } | 1218 } |
| 1147 | 1219 |
| 1148 Future stepInto() { | 1220 Future stepInto() { |
| 1149 return get("debug/resume?step=into").then((result) { | 1221 return invokeRpc('resume', {'step': 'into'}).then((result) { |
| 1150 if (result is DartError) { | 1222 if (result is DartError) { |
| 1151 // TODO(turnidge): Handle this more gracefully. | 1223 // TODO(turnidge): Handle this more gracefully. |
| 1152 Logger.root.severe(result.message); | 1224 Logger.root.severe(result.message); |
| 1153 } | 1225 } |
| 1154 return isolate.reload(); | 1226 return isolate.reload(); |
| 1155 }); | 1227 }); |
| 1156 } | 1228 } |
| 1157 | 1229 |
| 1158 Future stepOver() { | 1230 Future stepOver() { |
| 1159 return get("debug/resume?step=over").then((result) { | 1231 return invokeRpc('resume', {'step': 'over'}).then((result) { |
| 1160 if (result is DartError) { | 1232 if (result is DartError) { |
| 1161 // TODO(turnidge): Handle this more gracefully. | 1233 // TODO(turnidge): Handle this more gracefully. |
| 1162 Logger.root.severe(result.message); | 1234 Logger.root.severe(result.message); |
| 1163 } | 1235 } |
| 1164 return isolate.reload(); | 1236 return isolate.reload(); |
| 1165 }); | 1237 }); |
| 1166 } | 1238 } |
| 1167 | 1239 |
| 1168 Future stepOut() { | 1240 Future stepOut() { |
| 1169 return get("debug/resume?step=out").then((result) { | 1241 return invokeRpc('resume', {'step': 'out'}).then((result) { |
| 1170 if (result is DartError) { | 1242 if (result is DartError) { |
| 1171 // TODO(turnidge): Handle this more gracefully. | 1243 // TODO(turnidge): Handle this more gracefully. |
| 1172 Logger.root.severe(result.message); | 1244 Logger.root.severe(result.message); |
| 1173 } | 1245 } |
| 1174 return isolate.reload(); | 1246 return isolate.reload(); |
| 1175 }); | 1247 }); |
| 1176 } | 1248 } |
| 1177 | 1249 |
| 1250 Future<ServiceMap> getStack() { |
| 1251 return invokeRpc('getStack', {}).then((result) { |
| 1252 if (result is DartError) { |
| 1253 // TODO(turnidge): Handle this more gracefully. |
| 1254 Logger.root.severe(result.message); |
| 1255 } |
| 1256 return result; |
| 1257 }); |
| 1258 } |
| 1259 |
| 1260 Future<ServiceObject> eval(ServiceObject target, |
| 1261 String expression) { |
| 1262 Map params = { |
| 1263 'targetId': target.id, |
| 1264 'expression': expression, |
| 1265 }; |
| 1266 return invokeRpc('eval', params); |
| 1267 } |
| 1268 |
| 1269 Future<ServiceObject> getRetainedSize(ServiceObject target) { |
| 1270 Map params = { |
| 1271 'targetId': target.id, |
| 1272 }; |
| 1273 return invokeRpc('getRetainedSize', params); |
| 1274 } |
| 1275 |
| 1276 Future<ServiceObject> getRetainingPath(ServiceObject target, var limit) { |
| 1277 Map params = { |
| 1278 'targetId': target.id, |
| 1279 'limit': limit.toString(), |
| 1280 }; |
| 1281 return invokeRpc('getRetainingPath', params); |
| 1282 } |
| 1283 |
| 1284 Future<ServiceObject> getInboundReferences(ServiceObject target, var limit) { |
| 1285 Map params = { |
| 1286 'targetId': target.id, |
| 1287 'limit': limit.toString(), |
| 1288 }; |
| 1289 return invokeRpc('getInboundReferences', params); |
| 1290 } |
| 1291 |
| 1292 Future<ServiceObject> getInstances(Class cls, var limit) { |
| 1293 Map params = { |
| 1294 'classId': cls.id, |
| 1295 'limit': limit.toString(), |
| 1296 }; |
| 1297 return invokeRpc('getInstances', params); |
| 1298 } |
| 1299 |
| 1178 final ObservableMap<String, ServiceMetric> dartMetrics = | 1300 final ObservableMap<String, ServiceMetric> dartMetrics = |
| 1179 new ObservableMap<String, ServiceMetric>(); | 1301 new ObservableMap<String, ServiceMetric>(); |
| 1180 | 1302 |
| 1181 final ObservableMap<String, ServiceMetric> vmMetrics = | 1303 final ObservableMap<String, ServiceMetric> vmMetrics = |
| 1182 new ObservableMap<String, ServiceMetric>(); | 1304 new ObservableMap<String, ServiceMetric>(); |
| 1183 | 1305 |
| 1184 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( | 1306 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( |
| 1185 String id, | 1307 String id, |
| 1186 ObservableMap<String, ServiceMetric> metricsMap) { | 1308 ObservableMap<String, ServiceMetric> metricsMap) { |
| 1187 return get(id).then((result) { | 1309 return get(id).then((result) { |
| (...skipping 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2399 | 2521 |
| 2400 | 2522 |
| 2401 static String formatPercent(num a, num total) { | 2523 static String formatPercent(num a, num total) { |
| 2402 var percent = 100.0 * (a / total); | 2524 var percent = 100.0 * (a / total); |
| 2403 return '${percent.toStringAsFixed(2)}%'; | 2525 return '${percent.toStringAsFixed(2)}%'; |
| 2404 } | 2526 } |
| 2405 | 2527 |
| 2406 void updateProfileData(Map profileData, | 2528 void updateProfileData(Map profileData, |
| 2407 List<Code> codeTable, | 2529 List<Code> codeTable, |
| 2408 int sampleCount) { | 2530 int sampleCount) { |
| 2409 // Assert we have a CodeRegion entry. | |
| 2410 assert(profileData['type'] == 'CodeRegion'); | |
| 2411 // Assert we are handed profile data for this code object. | 2531 // Assert we are handed profile data for this code object. |
| 2412 assert(profileData['code'] == this); | 2532 assert(profileData['code'] == this); |
| 2413 totalSamplesInProfile = sampleCount; | 2533 totalSamplesInProfile = sampleCount; |
| 2414 inclusiveTicks = int.parse(profileData['inclusive_ticks']); | 2534 inclusiveTicks = int.parse(profileData['inclusive_ticks']); |
| 2415 exclusiveTicks = int.parse(profileData['exclusive_ticks']); | 2535 exclusiveTicks = int.parse(profileData['exclusive_ticks']); |
| 2416 _resolveCalls(callers, profileData['callers'], codeTable); | 2536 _resolveCalls(callers, profileData['callers'], codeTable); |
| 2417 _resolveCalls(callees, profileData['callees'], codeTable); | 2537 _resolveCalls(callees, profileData['callees'], codeTable); |
| 2418 var ticks = profileData['ticks']; | 2538 var ticks = profileData['ticks']; |
| 2419 if (ticks != null) { | 2539 if (ticks != null) { |
| 2420 _processTicks(ticks); | 2540 _processTicks(ticks); |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2745 _convertNull(obj) { | 2865 _convertNull(obj) { |
| 2746 if (obj.isNull) { | 2866 if (obj.isNull) { |
| 2747 return null; | 2867 return null; |
| 2748 } | 2868 } |
| 2749 return obj; | 2869 return obj; |
| 2750 } | 2870 } |
| 2751 | 2871 |
| 2752 // Returns true if [map] is a service map. i.e. it has the following keys: | 2872 // Returns true if [map] is a service map. i.e. it has the following keys: |
| 2753 // 'id' and a 'type'. | 2873 // 'id' and a 'type'. |
| 2754 bool _isServiceMap(ObservableMap m) { | 2874 bool _isServiceMap(ObservableMap m) { |
| 2755 return (m != null) && (m['id'] != null) && (m['type'] != null); | 2875 return (m != null) && (m['type'] != null); |
| 2756 } | 2876 } |
| 2757 | 2877 |
| 2758 bool _hasRef(String type) => type.startsWith('@'); | 2878 bool _hasRef(String type) => type.startsWith('@'); |
| 2759 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type); | 2879 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type); |
| 2760 | 2880 |
| 2761 /// Recursively upgrades all [ServiceObject]s inside [collection] which must | 2881 /// Recursively upgrades all [ServiceObject]s inside [collection] which must |
| 2762 /// be an [ObservableMap] or an [ObservableList]. Upgraded elements will be | 2882 /// be an [ObservableMap] or an [ObservableList]. Upgraded elements will be |
| 2763 /// associated with [vm] and [isolate]. | 2883 /// associated with [vm] and [isolate]. |
| 2764 void _upgradeCollection(collection, ServiceObjectOwner owner) { | 2884 void _upgradeCollection(collection, ServiceObjectOwner owner) { |
| 2765 if (collection is ServiceMap) { | 2885 if (collection is ServiceMap) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2789 var v = list[i]; | 2909 var v = list[i]; |
| 2790 if ((v is ObservableMap) && _isServiceMap(v)) { | 2910 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 2791 list[i] = owner.getFromMap(v); | 2911 list[i] = owner.getFromMap(v); |
| 2792 } else if (v is ObservableList) { | 2912 } else if (v is ObservableList) { |
| 2793 _upgradeObservableList(v, owner); | 2913 _upgradeObservableList(v, owner); |
| 2794 } else if (v is ObservableMap) { | 2914 } else if (v is ObservableMap) { |
| 2795 _upgradeObservableMap(v, owner); | 2915 _upgradeObservableMap(v, owner); |
| 2796 } | 2916 } |
| 2797 } | 2917 } |
| 2798 } | 2918 } |
| OLD | NEW |