| 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 /// An RpcException represents an exceptional event that happened | 7 /// An RpcException represents an exceptional event that happened |
| 8 /// while invoking an rpc. | 8 /// while invoking an rpc. |
| 9 abstract class RpcException implements Exception { | 9 abstract class RpcException implements Exception { |
| 10 RpcException(this.message); | 10 RpcException(this.message); |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 totalCollectionTimeInSeconds = heapMap['time']; | 820 totalCollectionTimeInSeconds = heapMap['time']; |
| 821 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; | 821 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; |
| 822 } | 822 } |
| 823 } | 823 } |
| 824 | 824 |
| 825 class HeapSnapshot { | 825 class HeapSnapshot { |
| 826 final ObjectGraph graph; | 826 final ObjectGraph graph; |
| 827 final DateTime timeStamp; | 827 final DateTime timeStamp; |
| 828 final Isolate isolate; | 828 final Isolate isolate; |
| 829 | 829 |
| 830 HeapSnapshot(this.isolate, ByteData data) : | 830 HeapSnapshot(this.isolate, chunks, nodeCount) : |
| 831 graph = new ObjectGraph(new ReadStream(data)), | 831 graph = new ObjectGraph(chunks, nodeCount), |
| 832 timeStamp = new DateTime.now() { | 832 timeStamp = new DateTime.now(); |
| 833 } | |
| 834 | 833 |
| 835 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { | 834 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { |
| 836 var result = []; | 835 var result = []; |
| 837 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { | 836 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { |
| 838 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); | 837 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); |
| 839 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj
) { | 838 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj
) { |
| 840 obj.retainedSize = v.retainedSize; | 839 obj.retainedSize = v.retainedSize; |
| 841 return new Future(() => obj); | 840 return new Future(() => obj); |
| 842 })); | 841 })); |
| 843 } | 842 } |
| 844 return result; | 843 return result; |
| 845 } | 844 } |
| 846 | |
| 847 | |
| 848 } | 845 } |
| 849 | 846 |
| 850 /// State for a running isolate. | 847 /// State for a running isolate. |
| 851 class Isolate extends ServiceObjectOwner with Coverage { | 848 class Isolate extends ServiceObjectOwner with Coverage { |
| 852 @reflectable VM get vm => owner; | 849 @reflectable VM get vm => owner; |
| 853 @reflectable Isolate get isolate => this; | 850 @reflectable Isolate get isolate => this; |
| 854 @observable int number; | 851 @observable int number; |
| 855 @observable DateTime startTime; | 852 @observable DateTime startTime; |
| 856 @observable Duration get upTime => | 853 @observable Duration get upTime => |
| 857 (new DateTime.now().difference(startTime)); | 854 (new DateTime.now().difference(startTime)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 } | 895 } |
| 899 | 896 |
| 900 /// Fetches and builds the class hierarchy for this isolate. Returns the | 897 /// Fetches and builds the class hierarchy for this isolate. Returns the |
| 901 /// Object class object. | 898 /// Object class object. |
| 902 Future<Class> getClassHierarchy() { | 899 Future<Class> getClassHierarchy() { |
| 903 return invokeRpc('getClassList', {}) | 900 return invokeRpc('getClassList', {}) |
| 904 .then(_loadClasses) | 901 .then(_loadClasses) |
| 905 .then(_buildClassHierarchy); | 902 .then(_buildClassHierarchy); |
| 906 } | 903 } |
| 907 | 904 |
| 905 Future<List<Class>> getClassRefs() async { |
| 906 ServiceMap classList = await invokeRpc('getClassList', {}); |
| 907 assert(classList.type == 'ClassList'); |
| 908 var classRefs = []; |
| 909 for (var cls in classList['classes']) { |
| 910 // Skip over non-class classes. |
| 911 if (cls is Class) { |
| 912 _classesByCid[cls.vmCid] = cls; |
| 913 classRefs.add(cls); |
| 914 } |
| 915 } |
| 916 return classRefs; |
| 917 } |
| 918 |
| 908 /// Given the class list, loads each class. | 919 /// Given the class list, loads each class. |
| 909 Future<List<Class>> _loadClasses(ServiceMap classList) { | 920 Future<List<Class>> _loadClasses(ServiceMap classList) { |
| 910 assert(classList.type == 'ClassList'); | 921 assert(classList.type == 'ClassList'); |
| 911 var futureClasses = []; | 922 var futureClasses = []; |
| 912 for (var cls in classList['classes']) { | 923 for (var cls in classList['classes']) { |
| 913 // Skip over non-class classes. | 924 // Skip over non-class classes. |
| 914 if (cls is Class) { | 925 if (cls is Class) { |
| 926 _classesByCid[cls.vmCid] = cls; |
| 915 futureClasses.add(cls.load()); | 927 futureClasses.add(cls.load()); |
| 916 } | 928 } |
| 917 } | 929 } |
| 918 return Future.wait(futureClasses); | 930 return Future.wait(futureClasses); |
| 919 } | 931 } |
| 920 | 932 |
| 921 /// Builds the class hierarchy and returns the Object class. | 933 /// Builds the class hierarchy and returns the Object class. |
| 922 Future<Class> _buildClassHierarchy(List<Class> classes) { | 934 Future<Class> _buildClassHierarchy(List<Class> classes) { |
| 923 rootClasses.clear(); | 935 rootClasses.clear(); |
| 924 objectClass = null; | 936 objectClass = null; |
| 925 for (var cls in classes) { | 937 for (var cls in classes) { |
| 926 if (cls.superclass == null) { | 938 if (cls.superclass == null) { |
| 927 rootClasses.add(cls); | 939 rootClasses.add(cls); |
| 928 } | 940 } |
| 929 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { | 941 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { |
| 930 objectClass = cls; | 942 objectClass = cls; |
| 931 } | 943 } |
| 932 } | 944 } |
| 933 assert(objectClass != null); | 945 assert(objectClass != null); |
| 934 return new Future.value(objectClass); | 946 return new Future.value(objectClass); |
| 935 } | 947 } |
| 936 | 948 |
| 949 Class getClassByCid(int cid) => _classesByCid[cid]; |
| 950 |
| 937 ServiceObject getFromMap(ObservableMap map) { | 951 ServiceObject getFromMap(ObservableMap map) { |
| 938 if (map == null) { | 952 if (map == null) { |
| 939 return null; | 953 return null; |
| 940 } | 954 } |
| 941 var mapType = _stripRef(map['type']); | 955 var mapType = _stripRef(map['type']); |
| 942 if (mapType == 'Isolate') { | 956 if (mapType == 'Isolate') { |
| 943 // There are sometimes isolate refs in ServiceEvents. | 957 // There are sometimes isolate refs in ServiceEvents. |
| 944 return vm.getFromMap(map); | 958 return vm.getFromMap(map); |
| 945 } | 959 } |
| 946 String mapId = map['id']; | 960 String mapId = map['id']; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 }; | 993 }; |
| 980 return isolate.invokeRpc('getObject', params); | 994 return isolate.invokeRpc('getObject', params); |
| 981 } | 995 } |
| 982 | 996 |
| 983 Future<ObservableMap> _fetchDirect() { | 997 Future<ObservableMap> _fetchDirect() { |
| 984 return invokeRpcNoUpgrade('getIsolate', {}); | 998 return invokeRpcNoUpgrade('getIsolate', {}); |
| 985 } | 999 } |
| 986 | 1000 |
| 987 @observable Class objectClass; | 1001 @observable Class objectClass; |
| 988 @observable final rootClasses = new ObservableList<Class>(); | 1002 @observable final rootClasses = new ObservableList<Class>(); |
| 1003 Map<int, Class> _classesByCid = new Map<int, Class>(); |
| 989 | 1004 |
| 990 @observable Library rootLibrary; | 1005 @observable Library rootLibrary; |
| 991 @observable ObservableList<Library> libraries = | 1006 @observable ObservableList<Library> libraries = |
| 992 new ObservableList<Library>(); | 1007 new ObservableList<Library>(); |
| 993 @observable ObservableMap topFrame; | 1008 @observable ObservableMap topFrame; |
| 994 | 1009 |
| 995 @observable String name; | 1010 @observable String name; |
| 996 @observable String vmName; | 1011 @observable String vmName; |
| 997 @observable ServiceFunction entry; | 1012 @observable ServiceFunction entry; |
| 998 | 1013 |
| 999 @observable final Map<String, double> timers = | 1014 @observable final Map<String, double> timers = |
| 1000 toObservable(new Map<String, double>()); | 1015 toObservable(new Map<String, double>()); |
| 1001 | 1016 |
| 1002 final HeapSpace newSpace = new HeapSpace(); | 1017 final HeapSpace newSpace = new HeapSpace(); |
| 1003 final HeapSpace oldSpace = new HeapSpace(); | 1018 final HeapSpace oldSpace = new HeapSpace(); |
| 1004 | 1019 |
| 1005 @observable String fileAndLine; | 1020 @observable String fileAndLine; |
| 1006 | 1021 |
| 1007 @observable DartError error; | 1022 @observable DartError error; |
| 1008 @observable HeapSnapshot latestSnapshot; | 1023 @observable HeapSnapshot latestSnapshot; |
| 1009 Completer<HeapSnapshot> _snapshotFetch; | 1024 StreamController _snapshotFetch; |
| 1025 |
| 1026 List<ByteData> _chunksInProgress; |
| 1010 | 1027 |
| 1011 void _loadHeapSnapshot(ServiceEvent event) { | 1028 void _loadHeapSnapshot(ServiceEvent event) { |
| 1012 latestSnapshot = new HeapSnapshot(this, event.data); | 1029 if (_snapshotFetch == null || _snapshotFetch.isClosed) { |
| 1030 // No outstanding snapshot request. Presumably another client asked for a |
| 1031 // snapshot. |
| 1032 Logger.root.info("Dropping unsolicited heap snapshot chunk"); |
| 1033 return; |
| 1034 } |
| 1035 |
| 1036 // Occasionally these actually arrive out of order. |
| 1037 var chunkIndex = event.chunkIndex; |
| 1038 var chunkCount = event.chunkCount; |
| 1039 if (_chunksInProgress == null) { |
| 1040 _chunksInProgress = new List(chunkCount); |
| 1041 } |
| 1042 _chunksInProgress[chunkIndex] = event.data; |
| 1043 _snapshotFetch.add("Receiving snapshot chunk ${chunkIndex + 1}" |
| 1044 " of $chunkCount..."); |
| 1045 |
| 1046 for (var i = 0; i < chunkCount; i++) { |
| 1047 if (_chunksInProgress[i] == null) return; |
| 1048 } |
| 1049 |
| 1050 var loadedChunks = _chunksInProgress; |
| 1051 _chunksInProgress = null; |
| 1052 |
| 1053 latestSnapshot = new HeapSnapshot(this, loadedChunks, event.nodeCount); |
| 1013 if (_snapshotFetch != null) { | 1054 if (_snapshotFetch != null) { |
| 1014 _snapshotFetch.complete(latestSnapshot); | 1055 latestSnapshot.graph.process(_snapshotFetch).then((graph) { |
| 1056 _snapshotFetch.add(latestSnapshot); |
| 1057 _snapshotFetch.close(); |
| 1058 }); |
| 1015 } | 1059 } |
| 1016 } | 1060 } |
| 1017 | 1061 |
| 1018 Future<HeapSnapshot> fetchHeapSnapshot() { | 1062 Stream fetchHeapSnapshot() { |
| 1019 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { | 1063 if (_snapshotFetch == null || _snapshotFetch.isClosed) { |
| 1020 _snapshotFetch = new Completer<HeapSnapshot>(); | 1064 _snapshotFetch = new StreamController(); |
| 1065 isolate.vm.streamListen('_Graph'); |
| 1021 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); | 1066 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); |
| 1022 } | 1067 } |
| 1023 return _snapshotFetch.future; | 1068 return _snapshotFetch.stream; |
| 1024 } | 1069 } |
| 1025 | 1070 |
| 1026 void updateHeapsFromMap(ObservableMap map) { | 1071 void updateHeapsFromMap(ObservableMap map) { |
| 1027 newSpace.update(map['new']); | 1072 newSpace.update(map['new']); |
| 1028 oldSpace.update(map['old']); | 1073 oldSpace.update(map['old']); |
| 1029 } | 1074 } |
| 1030 | 1075 |
| 1031 void _update(ObservableMap map, bool mapIsRef) { | 1076 void _update(ObservableMap map, bool mapIsRef) { |
| 1032 name = map['name']; | 1077 name = map['name']; |
| 1033 vmName = map['name']; | 1078 vmName = map['name']; |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 } | 1496 } |
| 1452 | 1497 |
| 1453 @observable String eventType; | 1498 @observable String eventType; |
| 1454 @observable Breakpoint breakpoint; | 1499 @observable Breakpoint breakpoint; |
| 1455 @observable ServiceMap topFrame; | 1500 @observable ServiceMap topFrame; |
| 1456 @observable ServiceMap exception; | 1501 @observable ServiceMap exception; |
| 1457 @observable ServiceObject inspectee; | 1502 @observable ServiceObject inspectee; |
| 1458 @observable ByteData data; | 1503 @observable ByteData data; |
| 1459 @observable int count; | 1504 @observable int count; |
| 1460 @observable String reason; | 1505 @observable String reason; |
| 1506 int chunkIndex, chunkCount, nodeCount; |
| 1461 | 1507 |
| 1462 @observable bool get isPauseEvent { | 1508 @observable bool get isPauseEvent { |
| 1463 return (eventType == kPauseStart || | 1509 return (eventType == kPauseStart || |
| 1464 eventType == kPauseExit || | 1510 eventType == kPauseExit || |
| 1465 eventType == kPauseBreakpoint || | 1511 eventType == kPauseBreakpoint || |
| 1466 eventType == kPauseInterrupted || | 1512 eventType == kPauseInterrupted || |
| 1467 eventType == kPauseException); | 1513 eventType == kPauseException); |
| 1468 } | 1514 } |
| 1469 | 1515 |
| 1470 void _update(ObservableMap map, bool mapIsRef) { | 1516 void _update(ObservableMap map, bool mapIsRef) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1483 } | 1529 } |
| 1484 if (map['exception'] != null) { | 1530 if (map['exception'] != null) { |
| 1485 exception = map['exception']; | 1531 exception = map['exception']; |
| 1486 } | 1532 } |
| 1487 if (map['inspectee'] != null) { | 1533 if (map['inspectee'] != null) { |
| 1488 inspectee = map['inspectee']; | 1534 inspectee = map['inspectee']; |
| 1489 } | 1535 } |
| 1490 if (map['_data'] != null) { | 1536 if (map['_data'] != null) { |
| 1491 data = map['_data']; | 1537 data = map['_data']; |
| 1492 } | 1538 } |
| 1539 if (map['chunkIndex'] != null) { |
| 1540 chunkIndex = map['chunkIndex']; |
| 1541 } |
| 1542 if (map['chunkCount'] != null) { |
| 1543 chunkCount = map['chunkCount']; |
| 1544 } |
| 1545 if (map['nodeCount'] != null) { |
| 1546 nodeCount = map['nodeCount']; |
| 1547 } |
| 1493 if (map['count'] != null) { | 1548 if (map['count'] != null) { |
| 1494 count = map['count']; | 1549 count = map['count']; |
| 1495 } | 1550 } |
| 1496 } | 1551 } |
| 1497 | 1552 |
| 1498 String toString() { | 1553 String toString() { |
| 1499 if (data == null) { | 1554 if (data == null) { |
| 1500 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; | 1555 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; |
| 1501 } else { | 1556 } else { |
| 1502 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " | 1557 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " |
| (...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3144 var v = list[i]; | 3199 var v = list[i]; |
| 3145 if ((v is ObservableMap) && _isServiceMap(v)) { | 3200 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 3146 list[i] = owner.getFromMap(v); | 3201 list[i] = owner.getFromMap(v); |
| 3147 } else if (v is ObservableList) { | 3202 } else if (v is ObservableList) { |
| 3148 _upgradeObservableList(v, owner); | 3203 _upgradeObservableList(v, owner); |
| 3149 } else if (v is ObservableMap) { | 3204 } else if (v is ObservableMap) { |
| 3150 _upgradeObservableMap(v, owner); | 3205 _upgradeObservableMap(v, owner); |
| 3151 } | 3206 } |
| 3152 } | 3207 } |
| 3153 } | 3208 } |
| OLD | NEW |